Chatfuel

Files and Tasks API Reference

Upload files and read file URLs, and follow long-running jobs such as contact exports and Google Calendar syncs with getTask and taskUpdated.

Last updated on

Files and tasks are the two helpers that the rest of the Chatfuel Public API relies on. Files are images, videos, audio and documents: you upload them over HTTP and pass their IDs to mutations, and you read files that contacts sent through their URLs. Tasks represent long-running jobs, such as a CSV contact export or a Google Calendar sync, that you start with a mutation and then follow until they finish.

How to upload a file

Uploads go to a separate HTTP endpoint as multipart/form-data, with the same Authorization: Bearer <token> header as GraphQL requests:

EndpointUse it forLowest role
POST /api/filestorage/upload/bot?botID=…&fileType=…Images and videos in flows, catalog images, specialist photos, CSV files for contact importEditor
POST /api/filestorage/upload/livechat?botID=…&contactID=…&fileType=…Attachments in chat messagesAgent
POST /api/filestorage/upload/plugin?botID=…&pluginID=…&fileType=…Header media of a filled WhatsApp template; pluginID is the FilledWhatsAppTemplateIDAgent
POST /api/filestorage/upload/widget?widgetID=…&fileType=ImageThe website widget avatarEditor

All of them live on https://panel.chatfuel.com. fileType is Image, Video, Audio or Document. An optional extension parameter sets the file extension without a dot, such as jpg or pdf:

curl -s "https://panel.chatfuel.com/api/filestorage/upload/bot?botID=$BOT_ID&fileType=Document&extension=csv" \
  -H "Authorization: Bearer $CHATFUEL_VIRTUAL_USER_TOKEN" \
  -F "[email protected]"

The response describes the stored file (some fields are left out here):

{
  "id": "6f1c…",
  "type": "Document",
  "status": "Downloaded",
  "contentType": "text/csv",
  "size": 48213,
  "extension": "csv",
  "createdAt": "2026-10-06T10:15:00Z",
  "deleteAfter": "2026-10-06T12:15:00Z"
}

Pass id as a FileID, for example to csvContactImportCreate, goodsProductCreate or whatsappAttachmentMessageSend. A file that is not used within two hours, shown in deleteAfter, is deleted.

How to read a file

type Query {
  # A file by ID: { id url type status size }.
  file(id: FileID!): File!
}

type Mutation {
  # Starts downloading a file that is stored with an external service, such as media a contact sent on a channel.
  fileStartDownload(id: FileID!): File!
}

status tells you whether the file is ready:

  • Downloaded: url points to the file.
  • NotDownloaded: the file is still with the external service. Call fileStartDownload and read the file again later.
  • DownloadInProgress: Chatfuel is fetching it.
  • Failed: the download failed.
  • Expired: the file was deleted after its retention period, or never existed.

Store the file ID rather than the URL, and read url again when you need the file.

How to follow a task

Operations that take a while return a Task immediately and continue in the background: csvContactExportStartBySegment, csvContactExportStartByIDsList and specialistStartGoogleCalendarSync. A task belongs to its bot, and any virtual user of the bot can read it (Agent).

type Query {
  getTask(id: TaskID!): Task!
}

type Subscription {
  taskUpdated(id: TaskID!): Task!
}
query Export($taskID: TaskID!) {
  getTask(id: $taskID) {
    id
    completedPoints
    totalPoints
    deadline
    statuses { type startedAt }   # Created, InProgress, Paused, Cancelled, Failed, Finished
    data {
      __typename
      ... on CSVContactsExport { file { url status } }
    }
  }
}

statuses is the history of the task; the last entry is the current status. Progress is completedPoints out of totalPoints. When a contact export reaches Finished, data.file is the CSV to download. Prefer the taskUpdated subscription over polling; if you poll, wait a few seconds between calls.

Common issues

The upload returns 400

A required query parameter such as botID, contactID, widgetID or fileType is missing or wrong, or the body is not multipart/form-data. Send the file as the first part of the form, as curl -F does.

"FileDoesNotExist" when using an uploaded file

The file was uploaded more than two hours ago and never used, so it was deleted. Upload it again right before the mutation that uses it.

A task stays in "InProgress"

Large exports and syncs can take several minutes. Check completedPoints to see that it is moving, and deadline for the latest time the task is expected to finish.

On this page