---
title: "Chatfuel Public API Quickstart"
description: "Create a personal API token, find your bot ID, create a virtual user and make your first Chatfuel Public API query and mutation in about ten minutes."
canonical_url: https://chatfuel.com/docs/public-api/quickstart
markdown_url: https://chatfuel.com/docs/public-api/quickstart.md
last_updated: 2026-10-06
lang: en
site: https://chatfuel.com/docs
llms_txt: https://chatfuel.com/llms.txt
---

# Chatfuel Public API Quickstart

Create a personal API token, find your bot ID, create a virtual user and make your first Chatfuel Public API query and mutation in about ten minutes.

The quickstart takes you from no token to a working Chatfuel Public API call in five steps: create your personal API token, find the bot ID, create a virtual user, read contacts with the virtual user token, and change a contact. You need the **Admin** role in the bot, a terminal with `curl` and `jq`, and about ten minutes.

## Step 1: Create your personal API token [#step-1-create-your-personal-api-token]

The personal API token is called the **CLI token** in the Chatfuel dashboard. You use it only to manage virtual users and other account-level settings.

1. Sign in to the Chatfuel dashboard at panel.chatfuel.com.
2. Open the account menu (your name or avatar) and select **CLI token**. The page is also available directly at `https://panel.chatfuel.com/integration/auth/token`.
3. Click **Create token**, then **Copy token**.
4. Save the personal API token in a password manager or a secret store. Chatfuel shows the token only once.

Keep the personal API token in an environment variable for the rest of the quickstart:

```bash
export CHATFUEL_PERSONAL_TOKEN="paste-your-cli-token-here"
```

Anyone with the personal API token can act as you in every bot you can access. Never commit it to a repository or put it in client-side code.

## Step 2: Find your bot ID [#step-2-find-your-bot-id]

Every Public API operation works inside a bot. List the bots your account can access with the personal API token:

```bash
QUERY='query MyBots {
  currentUser {
    botsV2(first: 50) {
      edges { node { id title } }
    }
  }
}'

jq -n --arg query "$QUERY" '{query: $query}' |
curl -s https://panel.chatfuel.com/graphql \
  -H "Authorization: Bearer $CHATFUEL_PERSONAL_TOKEN" \
  -H "Content-Type: application/json" \
  --data-binary @-
```

The bot ID is also visible in the dashboard address bar: it is the part after `/automation/` when a bot is open. Save it:

```bash
export BOT_ID="your-bot-id"
```

## Step 3: Create a virtual user [#step-3-create-a-virtual-user]

A virtual user is an API-only member of one bot. It gets its own token, which you use for all other calls. Create one with the `createVirtualUser` mutation and the personal API token:

```bash
QUERY='mutation CreateVirtualUser($botID: BotID!) {
  createVirtualUser(
    botID: $botID
    name: "Quickstart integration"
    role: { roleType: Editor, botPermissions: [] }
  ) {
    member { id role { roleTypeV2 } user { id name accountType } }
    authToken
  }
}'

jq -n --arg query "$QUERY" --arg botID "$BOT_ID" \
  '{query: $query, variables: {botID: $botID}}' |
curl -s https://panel.chatfuel.com/graphql \
  -H "Authorization: Bearer $CHATFUEL_PERSONAL_TOKEN" \
  -H "Content-Type: application/json" \
  --data-binary @-
```

The response contains the new member and its token:

```json
{
  "data": {
    "createVirtualUser": {
      "member": {
        "id": "6f1c…",
        "role": { "roleTypeV2": "Editor" },
        "user": { "id": "6f1b…", "name": "Quickstart integration", "accountType": "Virtual" }
      },
      "authToken": "3c9e…"
    }
  }
}
```

`authToken` is shown only in this response. Save it, together with `member.id`, which you need later to regenerate the token or remove the virtual user:

```bash
export CHATFUEL_VIRTUAL_USER_TOKEN="paste-authToken-here"
```

The role can be `Editor` or `Agent`. [Virtual users](https://chatfuel.com/docs/public-api/virtual-users) explains what each role allows.

## Step 4: Read contacts with the virtual user token [#step-4-read-contacts-with-the-virtual-user-token]

Switch to the virtual user token and read the bot title and the first ten contacts:

```bash
QUERY='query Contacts($botID: BotID!) {
  bot(id: $botID) {
    title
    contactsConnection(platforms: [whatsapp, instagram, facebook, tiktok, widget], first: 10) {
      edges { node { id name note updatedAt } }
      pageInfo { hasNextPage endCursor }
    }
  }
}'

jq -n --arg query "$QUERY" --arg botID "$BOT_ID" \
  '{query: $query, variables: {botID: $botID}}' |
curl -s https://panel.chatfuel.com/graphql \
  -H "Authorization: Bearer $CHATFUEL_VIRTUAL_USER_TOKEN" \
  -H "Content-Type: application/json" \
  --data-binary @-
```

To get the next page, pass `pageInfo.endCursor` as the `after` argument. [Making requests](https://chatfuel.com/docs/public-api/requests) shows the full pagination pattern.

## Step 5: Change a contact [#step-5-change-a-contact]

Take a contact `id` from the previous response and set a note on it with `contactSetNote`:

```bash
export CONTACT_ID="a-contact-id-from-step-4"

QUERY='mutation SetNote($contactID: ContactID!, $note: String) {
  contactSetNote(id: $contactID, note: $note) { id note }
}'

jq -n --arg query "$QUERY" --arg contactID "$CONTACT_ID" --arg note "Synced from CRM" \
  '{query: $query, variables: {contactID: $contactID, note: $note}}' |
curl -s https://panel.chatfuel.com/graphql \
  -H "Authorization: Bearer $CHATFUEL_VIRTUAL_USER_TOKEN" \
  -H "Content-Type: application/json" \
  --data-binary @-
```

The note now appears on the contact card in the dashboard, and the virtual user is listed in the bot's teammates with the **API** label. From here, browse the [contacts reference](https://chatfuel.com/docs/public-api/contacts) and [messaging reference](https://chatfuel.com/docs/public-api/messaging), or read about [tokens and authentication](https://chatfuel.com/docs/public-api/authentication) before going to production.

## Common issues [#common-issues]

### "NotEnoughPermissions" when creating a virtual user [#notenoughpermissions-when-creating-a-virtual-user]

`createVirtualUser` works only with a personal API token of a user who has the **Admin** role in the bot. A virtual user token is always rejected for this mutation, even if the virtual user exists in the same bot.

### "VirtualUserRoleNotAllowed" [#virtualuserrolenotallowed]

The role must be `Editor` or `Agent`. Virtual users can't be Admins or have a Custom role.

### "Unauthorized" [#unauthorized]

The token is missing, mistyped or revoked, or the header lacks the `Bearer ` prefix. Send `Authorization: Bearer <token>` and check that the token was not regenerated in the meantime.
