Chat API Documentation – xMagic
1. Key Terminology
- Agent: Represents an AI agent within the xMagic platform.
- Job: Denotes a specialized task or job performed by a agent.
- Chat Types: The
chat_typeparameter determines where and how a chat session appears in the xMagic UI. The main chat types are:- PLAYGROUND: Creates a chat session inside the Preview section of Studio. This is used for testing and iterating on agent behavior before deployment.
- CONFIGURATION: Used for chat sessions within the Studio's AI agent builder, typically for configuration or setup flows.
- INTERACT: Creates a chat session in the Interact section of the agent, representing live, production conversations as seen by end-users after deployment.
- STANDARD: Represents a chat session as it would appear to an external user accessing a shared agent (public or organization view), simulating the real end-user experience.
2. Authentication & Base URL
See the Authentication page for details on API keys.
Base URL:
https://api.xmagic.ai/xmagic-backend/v1
3. API Endpoints
3.1. Create New Chat
Creates a new chat session for a specified agent.
Endpoint
POST /agents/{agent_id}/chats
Authentication
Required header:
x-api-key: YOUR_API_KEY
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| agent_id | string | Yes | The unique identifier of the agent |
Request Body (JSON)
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| title | string | No | "New Chat" | The title of the chat session |
| chat_type | string | No | "standard" | The chat type ("playground", "configuration", "interact" or "standard") |
| metadata | object | No | A key-value map of custom metadata (string keys and string values) to attach to the chat. Metadata is displayed in the Threads table UI. |
Example Request
curl -X POST "https://api.xmagic.ai/xmagic-backend/v1/agents/{agent_id}/chats" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "My Test Chat",
"chat_type": "standard",
"metadata": {"customer_id": "cust_123", "customer_email": "john@example.com"}
}'
Success Response
Status Code: 200 OK
{
"data": {
"chat": {
"id": "67890ba3b59d451d9c89ccc9",
"title": "My Test Chat",
"chat_type": "standard",
"agent_id": "689b40d20571c35e6713fa0e",
"created_at": "2024-03-13T12:00:00Z"
}
}
}
Error Response
Status Code: 400 Bad Request / 401 Unauthorized / 404 Not Found
{
"error_code": "DESCRIPTIVE_ERROR_CODE",
"message": "Error description"
}
Note: If an error occurs, a JSON response may not always be returned; please rely on the HTTP status code instead.
3.2. Upload Files
Uploads files to be used in chat queries.
Endpoint
POST /uploaded-files
Authentication
Required header:
x-api-key: YOUR_API_KEY
Request Parameters (Form Data)
| Parameter | Type | Required | Description |
|---|---|---|---|
| file | file | Yes | The file to upload (multipart/form-data) |
| virtual_user_email | string | No | Email of the person uploading the file. Must be a valid, non-empty email address. |
Optionally include virtual_user_email to identify the person uploading the file
when several users share an API key. If the email does not match a virtual user
in your organization, one is created automatically. The email does not need to
match a platform user, and the person does not need an xMagic account.
Example Request
curl -X POST "https://api.xmagic.ai/xmagic-backend/v1/uploaded-files" \
-H "x-api-key: YOUR_API_KEY" \
-F "file=@/path/to/your/document.pdf"
To identify the person uploading the file, add
-F "virtual_user_email=alice@example.com" to the request.
Success Response
Status Code: 200 OK
{
"data": "681e297b3wbfbfeb1573cc07"
}
Error Response
Status Code: 400 Bad Request
{
"error_code": "FILE_UPLOAD_FAILED",
"message": "File upload failed"
}
Note: If an error occurs, a JSON response may not always be returned; please rely on the HTTP status code instead.
3.3. Send Query to Chat
Sends a query/message to an existing chat session and receives a response from the AI.
💡 Tip: The initial AI response is intentionally kept fast and minimal for performance. Responses with complex payloads or large output files require an additional retrieval step to access all assets. For details, refer to Section 3.5.
Endpoint
POST /agents/{agent_id}/chats/{chat_id}/query
Authentication
Required header:
x-api-key: YOUR_API_KEY
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| agent_id | string | Yes | The unique identifier of the agent |
| chat_id | string | Yes | The unique identifier of the chat |
Request Body (JSON)
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| query | string | Yes* | null | The message/question to send |
| message_id | string | No | auto-generated | Unique identifier for the message. Must be a valid 24-character hex string (MongoDB ObjectId). Generate one using new ObjectId() in JS/TS or from bson import ObjectId; str(ObjectId()) in Python. |
| job_id | string | No | null | Specific job to use |
| is_stream | boolean | No | false | Whether to stream the response |
| virtual_user_email | string | No | null | Identify the user sending this query by their email. A virtual user is created automatically if the email does not exist in your organization. |
| pin_response | boolean | No | false | Whether to pin the response |
| uploaded_files | string[] | No | [] | Array of uploaded file IDs |
| shortcut_id | string | No | null | Shortcut to execute |
| shortcut_fields_with_values | object[] | No | [] | Field values for the shortcut (see below) |
*Required unless shortcut_id is provided
Virtual user attribution
Optionally include virtual_user_email to identify the person sending the query
when several users share an API key. This works for both streaming and
non-streaming queries:
{
"query": "Summarize this document",
"virtual_user_email": "alice@example.com"
}
If the email does not match a virtual user in your organization, the API creates one automatically. The email does not need to match a platform user, and the person does not need an xMagic account. Authentication and permissions continue to use your API key.
Include virtual_user_email in each query you want to associate with that user.
If provided, it must be a valid, non-empty email address.
shortcut_fields_with_values Object
| Property | Type | Description |
|---|---|---|
| field_name | string | The name of the shortcut field |
| field_value | string | number | The value to populate the field with |
Example Request
curl -X POST "https://api.xmagic.ai/xmagic-backend/v1/agents/{agent_id}/chats/{chat_id}/query" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"query": "What is machine learning?",
"is_stream": false
}'
Example Request with Shortcut
curl -X POST "https://api.xmagic.ai/xmagic-backend/v1/agents/{agent_id}/chats/{chat_id}/query" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"shortcut_id": "some-shortcut-id",
"shortcut_fields_with_values": [
{
"field_name": "customer_name",
"field_value": "John Doe"
},
{
"field_name": "email",
"field_value": "john@example.com"
},
{
"field_name": "amount",
"field_value": 2500
}
],
"is_stream": false
}'
Example Request with Files
curl -X POST "https://api.xmagic.ai/xmagic-backend/v1/agents/{agent_id}/chats/{chat_id}/query" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"query": "Analyze this document and provide insights",
"uploaded_files": ["681e297b3wbfbfeb1573cc07"],
"is_stream": false
}'
Success Response (Non-streaming)
Status Code: 200 OK
{
"data": {
"text": "Machine learning is a subset of artificial intelligence...",
"message_id": "68270f28aa30f26d4c79944d"
}
}
Success Response (Streaming)
Status Code: 200 OK
Content-Type: text/event-stream
The streaming response uses Server-Sent Events (SSE) format. Each event is a data: line followed by two newlines (\n\n). The payload after data: is a complete JSON object (except for the terminal [DONE] sentinel).
data: {"text": "", "extended_text": null, "type": "metadata", "subtype": null, "data": {"message_id": "68270f28aa30f26d4c79944d"}, "elapsed_ms": null}
data: {"text": "", "extended_text": null, "type": "ping", "subtype": null, "data": null}
data: {"text": "Let me think about this...", "extended_text": null, "type": "reasoning", "subtype": null, "data": null}
data: {"text": "", "extended_text": null, "type": "end_reasoning", "subtype": null, "data": null}
data: {"text": "'File Creator' is working on your request", "extended_text": null, "type": "live_update", "subtype": "tool_call_start", "data": {"tool_name": "File Creator"}, "elapsed_ms": 820}
data: {"text": "Create file…", "extended_text": null, "type": "live_update", "subtype": "tool_call_start", "data": {"tool_name": "create_file"}, "elapsed_ms": 1250}
data: {"text": "Create file done", "extended_text": null, "type": "live_update", "subtype": "tool_call_result", "data": {"tool_name": "create_file", "preview": {"title": "Create: output.json", "content": "{...}", "content_type": "json", "status": "completed"}}, "elapsed_ms": 3100}
data: {"text": "File Creator done", "extended_text": null, "type": "live_update", "subtype": "tool_call_end", "data": {"tool_name": "File Creator"}, "elapsed_ms": 3250}
data: {"text": "Machine", "extended_text": null, "type": "response", "subtype": null, "data": null}
data: {"text": " learning", "extended_text": null, "type": "response", "subtype": null, "data": null}
data: {"text": " is...", "extended_text": null, "type": "response", "subtype": null, "data": null}
data: {"text": "", "extended_text": null, "type": "end_response", "subtype": null, "data": null}
data: [DONE]
SSE Event Schema
Every JSON event (except [DONE]) has the following top-level fields:
| Field | Type | Description |
|---|---|---|
type | string | The event type (see table below) |
subtype | string | null | Further classifies live_update events (e.g. tool_call_start) |
text | string | Primary text payload for this event |
extended_text | string | null | Additional text payload (reserved for future use; may be null) |
data | object | null | Structured payload — shape depends on event type (see below) |
elapsed_ms | number | null | Milliseconds elapsed since the request started. Present on all live_update events. null on metadata. Omitted on all other event types (ping, reasoning, response, etc.). |
SSE Event Types
| Type | Subtype | Description |
|---|---|---|
metadata | — | First event — data.message_id contains the message ID |
ping | — | Heartbeat while the model is initializing |
reasoning | — | Incremental reasoning/thinking token; concatenate text values |
end_reasoning | — | Signals reasoning is complete |
response | — | Incremental response token; concatenate text values |
end_response | — | Signals the response is complete |
live_update | tool_call_start | A tool call has begun; data.tool_name is the tool identifier |
live_update | tool_call_result | A tool call completed; data.preview contains the rendered output |
live_update | tool_call_end | A subagent or high-level tool has finished |
error | — | An error occurred; text contains the error message |
[DONE] | — | Stream termination sentinel — not a JSON object, signals end of stream |
live_update — data Object
| Field | Type | Description |
|---|---|---|
tool_name | string | Internal name of the tool that was called |
preview | object | null | Present on tool_call_result events (see below) |
live_update — preview Object
| Field | Type | Description |
|---|---|---|
title | string | Human-readable label for the tool output |
content | string | Rendered content of the tool result |
content_type | string | One of text, markdown, json, html, image, etc. |
status | string | completed or error |
Note: Additional event types and fields may be added in future API versions. Implement a fallback to safely ignore unrecognized events or fields.
Error Response
Status Code: 400 Bad Request / 404 Not Found / 500 Internal Server Error
{
"error_code": "DESCRIPTIVE_ERROR_CODE",
"message": "Error description"
}
Note: If an error occurs, a JSON response may not always be returned; please rely on the HTTP status code instead.
3.4. Send Async Query to Chat (with Webhooks)
Sends a query/message to an existing chat session asynchronously and delivers the response via webhook. This is useful for long-running operations where you don't want to maintain an open HTTP connection.
💡 Tip: The initial AI response is intentionally kept fast and minimal for performance. Responses with complex payloads or large output files require an additional retrieval step to access all assets. For details, refer to Section 3.5.
Endpoint
POST /agents/{agent_id}/chats/{chat_id}/async_query
Authentication
Required header:
x-api-key: YOUR_API_KEY
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| agent_id | string | Yes | The unique identifier of the agent |
| chat_id | string | Yes | The unique identifier of the chat |
Request Body (JSON)
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| query | string | Yes* | null | The message/question to send |
| message_id | string | No | auto-generated | Unique identifier for the message. Must be a valid 24-character hex string (MongoDB ObjectId). Generate one using new ObjectId() in JS/TS or from bson import ObjectId; str(ObjectId()) in Python. |
| job_id | string | No | null | Specific job to use |
| pin_response | boolean | No | false | Whether to pin the response |
| uploaded_files | string[] | No | [] | Array of uploaded file IDs |
| shortcut_id | string | No | null | Shortcut to execute |
| shortcut_fields_with_values | object[] | No | [] | Field values for the shortcut (see Section 3.3 for object schema) |
| webhook_url | string | Yes | null | The webhook URL for receiving results (POST method) |
| virtual_user_email | string | No | null | Identify the user sending this query by their email. A virtual user is created automatically if the email does not exist in your organization. |
*Required unless shortcut_id is provided
To identify the person sending an asynchronous query, include
virtual_user_email as described in Virtual user attribution.
Example Request
curl -X POST "https://api.xmagic.ai/xmagic-backend/v1/agents/{agent_id}/chats/{chat_id}/async_query" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"query": "What is machine learning?",
"webhook_url": "https://webhook.site/your-unique-url"
}'
Example Request with Files
curl -X POST "https://api.xmagic.ai/xmagic-backend/v1/agents/{agent_id}/chats/{chat_id}/async_query" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"query": "Analyze this document and provide insights",
"uploaded_files": ["681e297b3wbfbfeb1573cc07"],
"webhook_url": "https://webhook.site/your-unique-url"
}'
Success Response
Status Code: 200 OK
{
"data": {
"message_id": "68270f28aa30f26d4c79944d"
}
}
Error Response
Status Code: 400 Bad Request / 404 Not Found / 500 Internal Server Error
{
"error_code": "DESCRIPTIVE_ERROR_CODE",
"message": "Error description"
}
Note: If an error occurs, a JSON response may not always be returned; please rely on the HTTP status code instead.
Webhook Response
Results are sent via a POST request to the webhook_url provided in the parameters. The request body will be a JSON object containing the following structure:
{
"status": "success",
"error_message": null,
"data": {
"id": "68270f28aa30f26d4c79944d",
"query": "What is machine learning?",
"response": "Machine learning is a subset of artificial intelligence...",
"chat_id": "67890ba3b59d451d9c89ccc9",
"agent_id": "689b40d20571c35e6713fa0e",
"created_at": "2024-03-13T12:00:00Z",
"updated_at": "2024-03-13T12:01:30Z",
"message_type": "ai_chat",
"is_pinned": false,
"downloadable_output": {
"KXpmUj": "https://xchat-resource-prod.s3.amazonaws.com/outputs/output_file.xlsx?..."
},
"reasoning": "I need to analyze the question first...",
"quick_action_id": null,
"quick_action_fields_with_values": []
}
}
3.5. Get Message by ID
Retrieves detailed message data, including any associated downloadable assets such as output files, generated reports, and other artifacts.
💡 Tip: Use this endpoint when you need to access:
- Generated output files
- Processed documents
- Large data attachments
- Complete message metadata and assets
Note: Use the
message_idfrom the initial query response (Section 3.3 or Section 3.4) to retrieve the full message details.
Endpoint
GET /agents/{agent_id}/chats/{chat_id}/message/{message_id}
Authentication
Required header:
x-api-key: YOUR_API_KEY
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| agent_id | string | Yes | The unique identifier of the agent |
| chat_id | string | Yes | The unique identifier of the chat |
| message_id | string | Yes | The unique identifier of the message |
Query Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| downloadable_output | boolean | No | false | Include downloadable file links |
Example Request
curl -X GET "https://api.xmagic.ai/xmagic-backend/v1/agents/{agent_id}/chats/{chat_id}/message/{message_id}?downloadable_output=true" \
-H "x-api-key: YOUR_API_KEY"
Success Response
Status Code: 200 OK
{
"data": {
"id": "68270f28aa30f26d4c79944d",
"query": "Analyze this document and provide insights",
"response": "Based on the analysis of your document, here are the key insights...",
"chat_id": "67890ba3b59d451d9c89ccc9",
"agent_id": "689b40d20571c35e6713fa0e",
"created_at": "2024-03-13T12:00:00Z",
"updated_at": "2024-03-13T12:01:30Z",
"message_type": "ai_chat",
"is_pinned": false,
"downloadable_output": {
"KXpmUj": "https://xchat-resource-prod.s3.amazonaws.com/outputs/analysis_report.xlsx?AWSAccessKeyId=...&Signature=...&Expires=1747394995",
"AxbAUa": "https://xchat-resource-prod.s3.amazonaws.com/outputs/summary.pdf?AWSAccessKeyId=...&Signature=...&Expires=1747394995"
},
"reasoning": "I need to analyze the document structure first...",
"ai_resolution_status": "completed",
"quick_action_id": null,
"quick_action_fields_with_values": []
}
}
The quick_action_id and quick_action_fields_with_values fields are always present. When the message was triggered by a quick action (shortcut), quick_action_id contains the quick action's ID and quick_action_fields_with_values contains an array of field name/value pairs. Otherwise, quick_action_id is null and quick_action_fields_with_values is an empty array.
Note: Check the property downloadable_output to download the files.
Checking message processing status: Use the ai_resolution_status field to determine whether the agent has finished processing:
| Value | Description |
|---|---|
in_progress | The agent is still working on the response |
waiting | The agent has sent a notification that requires user review before it can continue |
completed | Processing is finished and all outputs are available |
Poll Get Message by ID to know the status of your message and to retrieve output files once ai_resolution_status is completed.
Error Response
Status Code: 404 Not Found / 401 Unauthorized
{
"error_code": "MESSAGE_NOT_FOUND",
"message": "The specified message could not be found"
}
Note: If an error occurs, a JSON response may not always be returned; please rely on the HTTP status code instead.
3.6. Get Chat Message History
Retrieves all messages in a chat session, optionally starting from a specific message.
Endpoint
GET /agents/{agent_id}/chats/{chat_id}/messages
Authentication
Required header:
x-api-key: YOUR_API_KEY
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| agent_id | string | Yes | The unique identifier of the agent |
| chat_id | string | Yes | The unique identifier of the chat |
Request Body (JSON)
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| from_message | string | No | null | Message ID to start from (inclusive). Returns this message and all subsequent ones. Useful for fetching only new messages since a known point. |
| page | integer | No | 1 | 1-indexed page number. |
| page_size | integer | No | 50 | Number of messages per page. Min 1, max 100. |
| order | string | No | "asc" | Sort order by creation time. "asc" = oldest first, "desc" = newest first. |
Example Request
curl -X GET "https://api.xmagic.ai/xmagic-backend/v1/agents/{agent_id}/chats/{chat_id}/messages" \
-H "x-api-key: YOUR_API_KEY"
Example Request (paginated, newest first)
curl -X GET "https://api.xmagic.ai/xmagic-backend/v1/agents/{agent_id}/chats/{chat_id}/messages" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"page": 2,
"page_size": 20,
"order": "desc"
}'
Example Request (from a specific message)
curl -X GET "https://api.xmagic.ai/xmagic-backend/v1/agents/{agent_id}/chats/{chat_id}/messages" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"from_message": "68270f28aa30f26d4c79944d"
}'
Success Response
Status Code: 200 OK
{
"data": {
"messages": [
{
"id": "68270f28aa30f26d4c79944d",
"query": "What is machine learning?",
"response": "Machine learning is a subset of artificial intelligence...",
"chat_id": "67890ba3b59d451d9c89ccc9",
"agent_id": "689b40d20571c35e6713fa0e",
"created_at": "2024-03-13T12:00:00Z",
"updated_at": "2024-03-13T12:01:30Z",
"message_type": "ai_chat",
"downloadable_output": {
"KXpmUj": "https://xchat-resource-prod.s3.amazonaws.com/outputs/output_file.xlsx?..."
},
"reasoning": "I need to analyze the question first...",
"ai_resolution_status": "completed",
"quick_action_id": "69b32767fbf23d0772e21619",
"quick_action_fields_with_values": [
{ "field_name": "customer_name", "field_value": "John Doe" }
]
}
],
"total": 42,
"page": 1,
"page_size": 50,
"count": 42,
"has_more": false
}
}
Pagination fields
| Field | Type | Description |
|---|---|---|
total | integer | Total number of messages matching the query (across all pages). |
page | integer | The current page number (1-indexed). |
page_size | integer | The maximum number of messages per page. |
count | integer | The number of messages actually returned in this page (≤ page_size). |
has_more | boolean | true if there are additional pages beyond the current one. |
Quick action fields
The quick_action_id and quick_action_fields_with_values fields are always present in each message object:
| Field | Type | Description |
|---|---|---|
quick_action_id | string | null | The ID of the quick action that triggered the query. null when the message was not triggered by a quick action. |
quick_action_fields_with_values | array | The field name/value pairs that were passed to the quick action. Each item has field_name (string) and field_value (string or number). Empty array [] when the message was not triggered by a quick action. |
Messages are returned in chronological order by default (order: "asc"). If from_message is provided, only messages from that point onward are returned.
Error Response
Status Code: 404 Not Found / 400 Bad Request / 401 Unauthorized
{
"error_code": "DESCRIPTIVE_ERROR_CODE",
"message": "Error description"
}
Note: If an error occurs, a JSON response may not always be returned; please rely on the HTTP status code instead.
3.7. Delete Message
Deletes a specific message from a chat session.
Endpoint
DELETE /agents/{agent_id}/chats/{chat_id}/message/{message_id}
Authentication
Required header:
x-api-key: YOUR_API_KEY
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| agent_id | string | Yes | The unique identifier of the persona |
| chat_id | string | Yes | The unique identifier of the chat |
| message_id | string | Yes | The unique identifier of the message |
Example Request
curl -X DELETE "https://api.xmagic.ai/xmagic-backend/v1/agents/{agent_id}/chats/{chat_id}/message/{message_id}" \
-H "x-api-key: YOUR_API_KEY"
Success Response
Status Code: 200 OK
{}
Error Response
Status Code: 404 Not Found / 401 Unauthorized
{
"error_code": "MESSAGE_NOT_FOUND",
"message": "The specified message could not be found or cannot be deleted"
}
Note: If an error occurs, a JSON response may not always be returned; please rely on the HTTP status code instead.