---
title: "Channels API Reference"
description: "Read a bot's connected channels and manage WhatsApp, Instagram, Facebook, TikTok and website widget settings. Connecting channels needs the personal token."
canonical_url: https://chatfuel.com/docs/public-api/channels
markdown_url: https://chatfuel.com/docs/public-api/channels.md
last_updated: 2026-10-06
lang: en
site: https://chatfuel.com/docs
llms_txt: https://chatfuel.com/llms.txt
---

# Channels API Reference

Read a bot's connected channels and manage WhatsApp, Instagram, Facebook, TikTok and website widget settings. Connecting channels needs the personal token.

A Chatfuel bot talks to contacts through connected channels: a WhatsApp number, an Instagram account, a Facebook Page, a TikTok account and the website chat widget. Through the Public API a virtual user can see which channels are connected, publish to Instagram, generate a wa.me link and change the website widget. Connecting and disconnecting channels, including connection links for your clients, needs a [personal API token](https://chatfuel.com/docs/public-api/authentication), because it grants access to someone's social accounts.

## How to see connected channels [#how-to-see-connected-channels]

Every connected channel is a contact scope of the bot (**Agent**):

```graphql
query Channels($botID: BotID!) {
  bot(id: $botID) {
    contactScopes {
      id
      __typename
      ... on WhatsAppPhoneContactScope { phone { id } }
      ... on InstagramAccountContactScope { instagramAccount { id } }
      ... on FacebookContactScope { facebookPage { id } }
      ... on TikTokAccountContactScope { tiktokAccount { id } }
      ... on WebWidgetContactScope { webWidget { id name isEnabled domains color } }
    }
    waPhoneConnectionState { waPhoneID status errorCode }
    botWhatsAppLink { phoneNumber title message }
  }
}
```

Under a virtual user token, `currentUser.instagramAccount(id:)` and `currentUser.tiktokAccount(id:)` return the accounts connected to the virtual user's bot (**Agent**). The lists `currentUser.instagramAccounts`, `tiktokAccounts`, `fbBusinesses` and `whatsAppBusinessAccounts` contain the social accounts a real person has linked, so they are useful only with the personal API token.

## How to connect and disconnect channels [#how-to-connect-and-disconnect-channels]

All of these are **Personal token only**:

```graphql
type Mutation {
  botConnectFacebookPage(botID: BotID!, pageID: FbPageID!): Bot!
  botConnectInstagramAccount(botID: BotID!, instagramAccountID: InstagramAccountID!): Bot!
  botConnectTikTokAccount(botID: BotID!, tiktokAccountID: TikTokAccountID!): Bot!
  botDisconnectContactScope(botID: BotID!, contactScopeID: ContactScopeID!): Bot!
}
```

These mutations connect accounts that the person behind the token has already linked to Chatfuel. To connect an account that belongs to someone else, such as your client, use a connection link.

## How to let a client connect their own account [#how-to-let-a-client-connect-their-own-account]

A connection link lets someone without dashboard access connect their WhatsApp, Instagram, TikTok or Facebook account to the bot. An access refresh link lets them grant permissions again for an account that is already connected. Both are **Personal token only**:

```graphql
type Mutation {
  # Creating a new link for the same bot and platform invalidates the previous one.
  # Redirect URLs, if set, must start with https://.
  botPlatformConnectionLinkCreate(botID: BotID!, platform: PlatformOperationLinkPlatform!, onSuccessRedirectURL: String, onFailureRedirectURL: String): PlatformConnectionLink!
  botPlatformConnectionLinkRevoke(botID: BotID!, linkID: PlatformOperationLinkID!): Bot!
  botPlatformAccessRefreshLinkCreate(botID: BotID!, platform: PlatformOperationLinkPlatform!, onSuccessRedirectURL: String, onFailureRedirectURL: String): PlatformAccessRefreshLink!
  botPlatformAccessRefreshLinkRevoke(botID: BotID!, linkID: PlatformOperationLinkID!): Bot!
}
```

`platform` is `whatsapp`, `instagram`, `tiktok` or `facebook`. The result contains the `url` to send to your client and its `expiresAt`. `bot.activePlatformConnectionLinks` and `bot.activePlatformAccessRefreshLinks` return the current links per platform, also with the personal API token only. When the client finishes, Chatfuel sends them to `onSuccessRedirectURL` or `onFailureRedirectURL`, and the new channel appears in `bot.contactScopes`.

## WhatsApp [#whatsapp]

```graphql
type Mutation {
  # Editor. A wa.me link with a prefilled message. title: 3 to 128 characters.
  # Errors: NoPhoneConnectedToBot, BotAlreadyHasWhatsAppLink
  botGenerateWhatsAppLink(botID: BotID!, title: String!, message: String): Bot!
  # Agent. Whether a payment method is attached to the WhatsApp Business Account in Meta.
  whatsAppBusinessAccountPaymentMethodHealthy(botID: BotID!, wabaID: WhatsappBusinessAccountID!): Boolean!
  # Personal token only. Profile picture of the number; the new picture arrives in whatsAppBusinessPhoneNumberUpdated.
  whatsAppPhoneSetProfileImageFile(id: WhatsAppBusinessPhoneID!, fileID: FileID!): WhatsAppBusinessPhoneNumber!
  # Personal token only. Sync contacts and chats of a number that also runs the WhatsApp Business app.
  whatsAppPhoneSyncBizAppData(id: WhatsAppBusinessPhoneID!): WhatsAppBusinessPhoneNumber!
  # Personal token only. Refresh your WhatsApp accounts from Meta in the background.
  whatsAppEntitiesStartRefetch: Boolean!
}

type Subscription {
  # Agent.
  waPhoneConnectionStateUpdated(botID: BotID!): WAPhoneConnectionState!
  whatsAppBusinessPhoneNumberUpdated(phoneID: WhatsAppBusinessPhoneID!): WhatsAppBusinessPhoneNumber!
}
```

## Instagram [#instagram]

Publishing posts to the connected Instagram account needs **Editor**. Media URLs must be publicly reachable, because Instagram downloads them.

```graphql
type Mutation {
  instagramAccountPublishImage(botID: BotID!, input: InstagramPublishImageInput!): InstagramPublishedMedia!     # { imageURL, caption }
  instagramAccountPublishCarousel(botID: BotID!, input: InstagramPublishCarouselInput!): InstagramPublishedMedia! # 2 to 10 items
  # Reels and video stories wait until Instagram finishes processing, up to 5 minutes.
  instagramAccountPublishReel(botID: BotID!, input: InstagramPublishReelInput!): InstagramPublishedMedia!       # { videoURL, caption, coverURL, shareToFeed, thumbOffset }
  instagramAccountPublishStory(botID: BotID!, input: InstagramPublishStoryInput!): InstagramPublishedMedia!     # { mediaType, mediaURL }

  # Agent. Refresh the account and its latest posts from Instagram (count up to 100).
  botInstagramRefetchLatestMedias(id: BotID!, count: Int!): Bot!
  instagramAccountRefetchMetaInfo(id: InstagramAccountID!): InstagramAccount!
  instagramAccountRefetchLatestMedias(id: InstagramAccountID!, count: Int!): InstagramAccount!
}

type Subscription {
  # Agent. A new post appeared on the connected account.
  botInstagramMediaAdded(id: BotID!): InstagramMedia!
}
```

`bot.instagramMediasConnection(first, after)` lists the account's posts (**Agent**). Publishing errors include `InvalidIGToken`, `InstagramDoesNotConnected`, `InstagramCarouselSizeInvalid` and `InstagramPublishContainerProcessingFailed`.

## Facebook [#facebook]

Facebook Page sync works with the Pages you have linked yourself, so all of it is **Personal token only**: `fbPagesSyncForBusiness(businessID)`, `fbPageSyncLatestPosts(pageID, count)` and the `fbPagesSyncStatusUpdated` and `fbPagePostsSyncStatusUpdated(pageID)` subscriptions.

## Website chat widget [#website-chat-widget]

The widget's ID comes from `bot.contactScopes` (`WebWidgetContactScope.webWidget.id`). Changing it needs **Editor**:

```graphql
type Mutation {
  webWidgetSetName(id: WebWidgetID!, name: String!): WebWidget!          # WebWidgetNameEmpty, WebWidgetNameTooLong
  webWidgetSetColor(id: WebWidgetID!, color: String!): WebWidget!
  webWidgetSetAvatar(id: WebWidgetID!, fileID: FileID!): WebWidget!      # upload to /upload/widget first
  webWidgetSetDomains(id: WebWidgetID!, domains: [String!]!): WebWidget! # WebWidgetDomainValidationFailed
  webWidgetSetIsEnabled(id: WebWidgetID!, isEnabled: Boolean!): WebWidget!
}
```

[Set up the chat widget for your website](https://chatfuel.com/docs/website/set-up-chat-widget-for-website) explains how the widget is installed on a site.

## Common issues [#common-issues]

### "NotEnoughPermissions" when connecting a channel with a virtual user token [#notenoughpermissions-when-connecting-a-channel-with-a-virtual-user-token]

Virtual users can't connect or disconnect channels or create connection links. Use the personal API token of a bot Admin, or send your client a connection link.

### "InvalidIGToken" [#invalidigtoken]

Instagram revoked Chatfuel's access to the account. Create an access refresh link with `botPlatformAccessRefreshLinkCreate` and ask the account owner to open it.

### "BotAlreadyHasWhatsAppLink" [#botalreadyhaswhatsapplink]

The bot already has a wa.me link. Read it from `bot.botWhatsAppLink`.
