Skip to content

Chat

The Chat endpoint receives a message through an API inbox, records the conversation in SquadOS, and normally runs the assigned agent. The response can return in the same request or be delivered later to a webhook.

Prefer the API inbox ID for {id}. For backward compatibility, the endpoint also accepts the ID of an agent that has an active API inbox.

Terminal window
curl -X POST https://api.squados.io/v1/chat/API_INBOX_ID \
-H "Authorization: Bearer pk_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"message": "What are your opening hours?",
"sync": true
}'

The token and inbox must belong to the same organization. An inactive inbox, an inbox for another channel, or an inbox from another organization is rejected.

FieldTypeRequiredDescription
messagestringConditionalMessage text. Send text, at least one attachment, or both.
roleuser | assistantNoDefault: user. With assistant, the message is only stored in history; the agent does not run.
conversation_idstring (UUID)NoContinues a specific conversation in the organization. Takes precedence over external_user_id.
external_user_idstringNoStable contact identifier from your system. Without conversation_id, reuses the latest conversation for this identifier in the organization.
user_namestringNoContact name. Updates the conversation name and, when a contact is linked, the name shown in Conversations.
syncbooleanNoWith true, returns the agent response in the same call. With false and webhook_url, queues asynchronous processing.
webhook_urlstring (HTTP/HTTPS URL)NoAsynchronous callback destination. Without this URL, the response is direct. With sync: true, the response remains direct and no callback is sent.
attachmentsarray of AttachmentConditionalImages, audio, or files. Can replace message in an attachment-only request.
metadataobjectNoFree-form correlation data. It is also returned in the asynchronous callback.
onlyStoragebooleanNoWith true, stores the message without running the agent. Useful for syncing external history.
FieldTypeRequiredDescription
namestringRecommendedFile name. When omitted, SquadOS uses attachment.
urlstringYesAn HTTP/HTTPS URL accessible to SquadOS or a complete data URL such as data:image/png;base64,.... Raw base64 without the data: prefix is not accepted.
typeimage | audio | fileRecommendedAttachment category. If omitted or invalid, SquadOS tries to infer it from mimeType; video is treated as file.
mimeTypestringRecommendedMIME type such as image/jpeg, audio/mpeg, or application/pdf.

Actual processing depends on the agent’s capabilities and settings. For example, audio can be transcribed and file text can be extracted before reaching the model.

SquadOS resolves the conversation in this order:

  1. If conversation_id is provided, continue that conversation if it belongs to the token’s organization.
  2. Without conversation_id, if external_user_id is provided, find the latest conversation for that identifier in the organization.
  3. Without either value, create a new conversation.

If the matched conversation is archived, a new conversation is created. Always retain the returned conversation_id: it is the most precise way to continue a thread. external_user_id is useful when your system prefers to retain only its own contact identifier.

Terminal window
curl -X POST https://api.squados.io/v1/chat/API_INBOX_ID \
-H "Authorization: Bearer pk_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"message": "I am back. What is my order status?",
"sync": true,
"external_user_id": "crm-customer-123",
"user_name": "Maria Silva"
}'

The response is direct when there is no webhook_url or when sync: true. The endpoint contract has no fixed 10-second timeout; configure your client timeout to accommodate the agent’s execution time.

Response 200

{
"success": true,
"conversation_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"message_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"response": "Our store is open Monday through Friday from 9 AM to 6 PM.",
"model": "provider/model",
"credits_used": 1,
"attachments_processed": 0
}

model and credits_used reflect the actual execution and vary by agent, provider, and usage.

Send webhook_url and do not use sync: true. The API acknowledges receipt with 202; this initial acknowledgment does not contain the assistant response or its message_id.

Terminal window
curl -X POST https://api.squados.io/v1/chat/API_INBOX_ID \
-H "Authorization: Bearer pk_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"message": "Analyze the attached report",
"sync": false,
"webhook_url": "https://integration.example.com/squados/callback",
"metadata": { "ticket_id": "TKT-12345" }
}'

With sync: false, processing goes through the asynchronous queue and the acknowledgment includes its group:

{
"status": "debounced",
"group_id": "d4e5f6a7-b8c9-0123-def0-234567890123",
"conversation_id": "c3d4e5f6-a7b8-9012-cdef-123456789012"
}

If sync is omitted, the asynchronous acknowledgment can use "status": "processing" and contain only status and conversation_id.

When processing finishes, SquadOS sends a POST to the supplied URL. A successful callback uses event: "message.completed" and includes success, agent_id, conversation_id, message_id, response, model, credits_used, attachments_processed, responding_agent_name, metadata, and timestamp. An agent transfer can produce an earlier callback with pre_transfer: true. See Webhooks for payloads and delivery considerations.

Use role: "assistant" to record a message produced outside SquadOS, or onlyStorage: true to persist either role without running the pipeline. Provide conversation_id when the message must enter an existing conversation; without it, normal resolution rules apply and a conversation can be created.

Terminal window
curl -X POST https://api.squados.io/v1/chat/API_INBOX_ID \
-H "Authorization: Bearer pk_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"message": "Your order has been processed.",
"role": "assistant",
"conversation_id": "550e8400-e29b-41d4-a716-446655440000"
}'

Response 200

{
"success": true,
"conversation_id": "550e8400-e29b-41d4-a716-446655440000",
"message_id": null
}

message can be omitted when attachments contains at least one item:

{
"sync": true,
"attachments": [
{
"name": "contract.pdf",
"url": "https://files.example.com/contract.pdf",
"type": "file",
"mimeType": "application/pdf"
}
]
}
HTTPcodeWhen it happens
400invalid_requestInvalid JSON, invalid role, wrong field type, or both text and attachments are missing.
401unauthorizedToken is missing, invalid, revoked, or outside its validity period.
403forbiddenThe inbox does not belong to the token’s organization or is not an API inbox.
403trigger_inactiveThe API inbox is inactive or the legacy agent does not have an active API inbox.
404not_foundRoute or conversation_id was not found in the organization.

Error responses use the shape { "error": "message", "code": "code" }. See Errors for the shared API contract.