Skip to main content
Salfio Docs

Search documentation

Type to search this documentation.

On this pageOverview

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:

  1. List integrations to find your Slack integration's id.
  2. List that integration's channels to find the channel names.
  3. 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.

  • 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 @Salfio in 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/clients if 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_….

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).

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…" }.

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"] } ] }.

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.

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.

Export
Suggest an edit to this page

Documentation menu