Assign a Slack channel to a client over the API
Discover an organization's integrations and a Slack integration's channels, then bind a channel to a client so its messages are assigned automatically — entirely over the API or MCP.
Salfio assigns incoming communications to clients using assignment rules. For Slack, a rule binds a channel to a client, so every message in that channel is attributed to the right client without any manual sorting.
This guide does the whole thing programmatically — no dashboard step — which is what you want when you're onboarding many clients at once. It walks the three calls end to end:
- List integrations to find your Slack integration's id.
- List that integration's channels to find the channel names.
- Set the client's assignment rules to bind a channel to a client.
Every call is shown as both a REST request and its MCP-tool equivalent — the two surfaces are 1:1 and share the same authorization and rate limits.
Prerequisites
Section titled “Prerequisites”- A Salfio organization with Slack connected — see Connect Slack. The Slack bot must be a member of the channels you want to bind (invite it with
/invite @Salfioin Slack); the channels endpoint only lists channels the bot is in. - A Salfio API key (
sk_live_…). See Authentication for how to mint one and how to present it. - The client id you want to bind the channel to. List your clients with
GET /v1/clientsif you don't have it yet.
All examples use the base URL https://api.salfio.com/v1 and pass the key as Authorization: Bearer sk_live_….
1. Find your Slack integration
Section titled “1. Find your Slack integration”List the organization's integrations and pick the one whose type is slack. The integrationId is what you'll bind the rule to.
curl -s https://api.salfio.com/v1/integrations \
-H "Authorization: Bearer sk_live_…"
{
"data": [
{
"integrationId": "8f2a…",
"type": "slack",
"providerEmail": "acme.slack.com",
"connectionStatus": "active",
"enabled": true,
"connectedAt": "2026-05-01T09:12:00Z",
"lastSyncedAt": "2026-06-28T20:00:00Z"
}
],
"meta": {}
}The list includes integrations of every status — check connectionStatus and enabled. A disconnected, expired, or disabled Slack integration can't serve channels until it's reconnected in the dashboard.
MCP: call the list_integrations tool (no arguments).
2. List the channels the bot is in
Section titled “2. List the channels the bot is in”Pass the Slack integrationId to the channels endpoint. It returns the channels the Salfio bot is a member of — the valid set of names to bind.
curl -s https://api.salfio.com/v1/integrations/8f2a…/channels \
-H "Authorization: Bearer sk_live_…"
{
"data": [
{ "id": "C0123ABCD", "name": "acme-project", "isPrivate": false, "isExtShared": false, "memberCount": 12 },
{ "id": "C0456EFGH", "name": "general", "isPrivate": false, "isExtShared": false, "memberCount": 48 }
],
"meta": {}
}If a channel you expect is missing, the bot probably isn't in it — invite it in Slack and try again. Channels are cached briefly, so a freshly-invited channel may take a moment to appear.
This endpoint is Slack-only. Pointing it at a Gmail or meeting integration returns 400 invalid_argument — those integration types have no channel concept.
MCP: call list_integration_channels with { "integration_id": "8f2a…" }.
3. Bind the channel to a client
Section titled “3. Bind the channel to a client”Create the rule with the slackChannels shorthand — a list of channel names. The server expands each name into the matching criteria, so you never hand-build the query structure.
This is a replace-all write. The rules array becomes the client's entire rule set — any integration you omit has its existing rule removed. Always read the current rules first (GET …/assignment-rules), modify, then send the full set back. Sending one rule when the client already had others will delete the others.
curl -s -X PUT https://api.salfio.com/v1/clients/ad44…/assignment-rules \
-H "Authorization: Bearer sk_live_…" \
-H "Content-Type: application/json" \
-d '{
"rules": [
{ "integrationId": "8f2a…", "slackChannels": ["acme-project"] }
]
}'The response echoes the saved rules (with the server-expanded filterCriteria) plus a reapplyStats summary of how many existing conversations were re-evaluated against the new rules:
{
"data": {
"rules": [
{
"ruleId": "7c1d…",
"integrationId": "8f2a…",
"integrationType": "slack",
"providerEmail": "acme.slack.com",
"filterCriteria": { "condition": "or", "rules": [ { "field": "channel", "operator": "equals", "value": "acme-project" } ] },
"enabled": true,
"priority": 0,
"createdAt": "2026-06-29T08:00:00Z",
"updatedAt": "2026-06-29T08:00:00Z"
}
],
"reapplyStats": {
"conversationsEvaluated": 31,
"conversationsMatched": 9,
"assignmentsCreated": 9,
"assignmentsRemoved": 0
}
},
"meta": {}
}A save also kicks off a Slack history backfill for the bound channels, so recent messages get attributed too — not just new ones.
MCP: call set_assignment_rules with { "client_id": "ad44…", "rules": [ { "integration_id": "8f2a…", "slack_channels": ["acme-project"] } ] }.
Verify
Section titled “Verify”Read the rules back. The Slack rule now carries the expanded filterCriteria:
curl -s https://api.salfio.com/v1/clients/ad44…/assignment-rules \
-H "Authorization: Bearer sk_live_…"In the Salfio dashboard, the same binding shows up under the client's Assignment Rules — the API and the dashboard write the same data.
Errors you might hit
Section titled “Errors you might hit”| Status | Code | When |
|---|---|---|
400 |
invalid_argument |
The channels endpoint was called on a non-Slack integration, or you sent both slackChannels and filterCriteria on one rule (they're mutually exclusive). |
404 |
not_found |
The integration or client doesn't exist or belongs to a different organization. The API returns 404 either way — it never reveals cross-tenant existence. |
409 |
conflict |
The Slack integration isn't active (disconnected, expired, or disabled). Reconnect it in the dashboard. |
429 |
rate_limited |
You hit the org/tool rate limit. Honour Retry-After. See Rate Limits. |
Bind several channels at once. slackChannels takes a list: ["acme-project", "acme-support"]. All of them are OR-ed into the client's Slack rule.
Non-Slack integrations. There's no channel concept for Gmail, meetings, etc. — bind those with a raw filterCriteria object instead of slackChannels. The two are mutually exclusive on a single rule.
Onboarding many clients. The three calls compose cleanly in a loop: list integrations once, list channels once, then PUT per client. Mind the rate limits — 100 requests/minute per organization.
Related
Section titled “Related”GET /v1/integrations— list integrations.GET /v1/integrations/{integrationId}/channels— list a Slack integration's channels.GET/PUT /v1/clients/{clientId}/assignment-rules— read and replace a client's rules.- Model Context Protocol (MCP) — the same tools from an MCP client.
- Authentication — minting and presenting an API key.