Skip to content
engage-ai

List supported messaging platforms

GET/channels/providers

Generated from the connectors compiled into this build, not from a hand-maintained list. A newly deployed connector appears here immediately, with its capabilities and the JSON Schema for its settings — which is how a dashboard renders a configuration form for a platform it has never seen.

Responses

  • 200Every registered platform.
  • 401Missing, malformed, revoked or expired API key.
  • 404Not found, or not visible to this organization.
  • 422Request failed validation.
  • 429Rate limited.
  • 500Unexpected error. The correlationId ties it to our logs.
Request
curl "https://api.getengageai.app/channels/providers" \
  -H "Authorization: Bearer $ENGAGE_API_KEY"
Response · 200
[
  {
    "providerKey": "telegram_bot",
    "displayName": "Telegram",
    "family": "string",
    "category": "Footwear",
    "authType": "string",
    "capabilities": {
      "text": true,
      "media": true,
      "templates": true,
      "interactive": true,
      "reactions": true,
      "typingIndicator": true,
      "readReceipts": true,
      "deliveryReceipts": true,
      "profileLookup": true,
      "threading": true,
      "maxTextLength": 0,
      "maxMediaBytes": 0,
      "replyWindowHours": 0,
      "supportedContentTypes": [
        "string"
      ]
    },
    "configSchema": {},
    "rateLimitPerMinute": 0,
    "docsUrl": "https://core.telegram.org/bots/api",
    "isBeta": true
  }
]

Link a messaging account to this organization

POST/channels/connect

Returns the webhook URL to register with the provider and a per-connection secret. Credentials are encrypted before they reach the database and are never returned. Re-connecting the same account updates it; connecting an account already held by another organization is rejected, since inbound events carry no tenant marker.

The credentials are checked against the provider before they are stored. If the provider rejects them this returns 422 and nothing is saved, so a mistyped token is caught while the person who typed it is still looking at the form. If the provider cannot be reached, the connection is saved as DEGRADED rather than refused — our signup should not depend on their uptime — and verification says so.

verified: true is the only value that means the credentials are known good. Note that a provider can only confirm what it can see: WhatsApp proves the access token and phone number id, but the app secret and verify token are exercised only by an inbound webhook, so they remain unproven until a message arrives.

Body
application/json

Request body

  • providerKeystringrequired

    From GET /channels/providers, e.g. whatsapp_cloud

    Min 3 characters · Max 64 characters

  • externalAccountIdstringrequired

    The provider's own id for the account: phone number id, page id, bot id.

    Max 255 characters

  • displayNamestringrequired

    Max 255 characters

  • credentialsobjectrequired

    Provider-specific. Encrypted with AES-256-GCM before it reaches the database and never returned by any endpoint.

  • settingsobject

    Validated against the connector's configSchema.

  • scopesstring[]
  • verifyboolean

    Check the credentials against the provider before saving. Defaults to true. Set false only for fixtures — a connection saved unverified fails later, when nobody is still looking at the form.

  • tokenExpiresAtstring (date-time)

    Set for OAuth credentials so the engine can refresh before expiry.

Response fields 201
  • connectionIdstring (uuid)required
  • webhookUrlstringrequired

    Register this with the provider.

  • verifiedbooleanrequired

    True only when the provider confirmed these credentials. False also means "not checked" — read verification for which.

  • verificationstring | nullrequired

    Why verification was skipped or inconclusive. Null when it succeeded.

  • webhookSecretstring | nullrequired

    Shown once, and null for WhatsApp and Telegram. Those providers authenticate inbound events with a credential you supplied, so this value is not the one to give them — read registration.verifyWith for the field that is.

  • registrationobject | nullrequired

    How to register the webhook URL with the provider. Null when nothing is needed.

ChannelConnected

  • connectionIdstring (uuid)required
  • webhookUrlstringrequired

    Register this with the provider.

  • verifiedbooleanrequired

    True only when the provider confirmed these credentials. False also means "not checked" — read verification for which.

  • verificationstring | nullrequired

    Why verification was skipped or inconclusive. Null when it succeeded.

  • webhookSecretstring | nullrequired

    Shown once, and null for WhatsApp and Telegram. Those providers authenticate inbound events with a credential you supplied, so this value is not the one to give them — read registration.verifyWith for the field that is.

  • registrationobject | nullrequired

    How to register the webhook URL with the provider. Null when nothing is needed.

Responses

  • 201Connected. The secret is shown once.
  • 401Missing, malformed, revoked or expired API key.
  • 404Not found, or not visible to this organization.
  • 409This account is already linked to a different organization. Inbound events carry no tenant marker, so one number or bot cannot serve two.
  • 422Request failed validation.
  • 429Rate limited.
  • 500Unexpected error. The correlationId ties it to our logs.
Request
curl -X POST "https://api.getengageai.app/channels/connect" \
  -H "Authorization: Bearer $ENGAGE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "providerKey": "telegram_bot",
    "externalAccountId": "7654321",
    "displayName": "Acme Support (Telegram)",
    "credentials": {
      "botToken": "7654321:AAHdqTcvCH1vGWJxfSeofSAs0K5PALDsaw",
      "webhookSecretToken": "a-random-string-you-chose"
    },
    "settings": {
      "botUsername": "acme_support_bot"
    }
  }'
Response · 201
{
  "connectionId": "3f6c2a1e-8b4d-4e7a-9c15-2d0b7e6f4a91",
  "webhookUrl": "https://api.getengageai.app/webhooks/telegram_bot?connection=7654321",
  "verified": true,
  "verification": "string",
  "webhookSecret": "string",
  "registration": {
    "verifyWith": "string",
    "instructions": "string"
  }
}

Disconnect a messaging account

DELETE/channels/connections/{id}

Stops this account being used, and destroys its stored credentials — a business that disconnects an account has withdrawn its trust, and keeping an encrypted access token for an integration nobody uses is a liability with no upside.

Inbound events for it are ignored from this moment: the webhook lookup skips disconnected accounts, and the provider will keep delivering for a while regardless of what we think.

Conversations and messages are kept. Disconnecting a number does not mean giving up what customers said on it, so the connection is retired rather than erased.

To swap one account for another, disconnect the old one and connect the new — they are separate accounts and nothing is carried over. Reconnecting the same account later revives this connection with fresh credentials and a new webhook secret, so the old webhook registration must be updated at the provider.

Path parameters

  • idstring (uuid)required
Response fields 200
  • disconnectedtruerequired

Responses

  • 200Disconnected.
  • 401Missing, malformed, revoked or expired API key.
  • 404Not found, or not visible to this organization.
  • 422Request failed validation.
  • 429Rate limited.
  • 500Unexpected error. The correlationId ties it to our logs.
Request
curl -X DELETE "https://api.getengageai.app/channels/connections/$ID" \
  -H "Authorization: Bearer $ENGAGE_API_KEY"
Response · 200
{
  "disconnected": true
}

List linked accounts

GET/channels/connections

Query parameters

  • cursorstring
  • limitinteger

    Max 100

Response fields 200
  • itemsChannelConnection[]required
  • nextCursorstring | nullrequired

    Opaque. Pass back verbatim as cursor. Null means the end.

  • hasMorebooleanrequired

ChannelConnection

  • idstring (uuid)required
  • providerKeystringrequired
  • displayNamestringrequired
  • statusenumrequired

    DEGRADED still sends; REVOKED needs a human to re-authorise.

    One of PENDING, ACTIVE, DEGRADED, REVOKED, DISABLED, ERROR

  • autoReplyModeenumrequired

    How far automation may go on this channel without a human.

    One of OFF, SUGGEST, AUTO_WITH_THRESHOLD, AUTO

  • capabilitiesChannelCapabilitiesrequired

ChannelCapabilities

  • textbooleanrequired
  • mediabooleanrequired
  • templatesbooleanrequired
  • interactivebooleanrequired
  • reactionsbooleanrequired
  • typingIndicatorbooleanrequired
  • readReceiptsbooleanrequired
  • deliveryReceiptsbooleanrequired
  • profileLookupbooleanrequired
  • threadingbooleanrequired
  • maxTextLengthintegerrequired

    The engine truncates outbound replies to this.

    Min -9007199254740991

  • maxMediaBytesinteger

    Min -9007199254740991

  • replyWindowHoursinteger | nullrequired

    Hours after the customer's last message during which free-form replies are allowed. Null means the platform has no such window.

  • supportedContentTypesstring[]required

Responses

  • 200A page of connections. Never includes credentials.
  • 401Missing, malformed, revoked or expired API key.
  • 404Not found, or not visible to this organization.
  • 422Request failed validation.
  • 429Rate limited.
  • 500Unexpected error. The correlationId ties it to our logs.
Request
curl "https://api.getengageai.app/channels/connections" \
  -H "Authorization: Bearer $ENGAGE_API_KEY"
Response · 200
{
  "items": [
    {
      "id": "3f6c2a1e-8b4d-4e7a-9c15-2d0b7e6f4a91",
      "providerKey": "telegram_bot",
      "displayName": "Acme Support (Telegram)",
      "status": "PENDING",
      "autoReplyMode": "OFF",
      "capabilities": {
        "text": true,
        "media": true,
        "templates": true,
        "interactive": true,
        "reactions": true,
        "typingIndicator": true,
        "readReceipts": true,
        "deliveryReceipts": true,
        "profileLookup": true,
        "threading": true,
        "maxTextLength": 0,
        "maxMediaBytes": 0,
        "replyWindowHours": 0,
        "supportedContentTypes": [
          "string"
        ]
      }
    }
  ],
  "nextCursor": null,
  "hasMore": false
}