AgentStack Docs
AgentStack Docs
AgentStack documentation
Get started
Build your agent
Actions
Analytics
Channels
Help Desk
Help Center
Developers
Embed the widgetControl the widgetListen for widget eventsBrowser integration boundariesClient-side formsREST API authenticationPagination and errorsRate limitsREST API: agent sign-upREST API: agentsREST API: sources and ingestionREST API: actionsREST API: channelsREST API: analytics and activityREST API: topicsREST API: contactsREST API: conversations and notesREST API: inbox and teamsREST API: chatREST API: roles and membersREST API: organizationREST API: API keysREST API: audit logsREST API: billingREST API: custom domainsREST API: domainsREST API: Help CenterREST API: Help PageREST API: Notion connectionREST API: voice callsIdentity verificationWebhooksMCP serverMCP scopesMCP toolsMCP clientsllms.txt
Workspace
    Developers

    REST API: inbox and teams

    Automate ticket routing and keep human ownership explicit.

    Inbox automation works on tickets and teams, not on anonymous chat text. Before you assign a ticket, change its status or team, reply, add a note, close it, or resume AI, fetch the ticket and its thread. A takeover changes the ownership of a ticket. Show this change to the human team. Do not let competing workers repeatedly take over the same ticket.

    Teams have their own membership lifecycle. Before you add or remove a person, read the team state and the member state. Use team deletion only for planned cleanup, after you reroute the tickets. Inbox list pagination differs from the common after cursor pattern. Read the route schema. Do not reuse a generic list helper.

    Two routes read the agent behind the ticket, and both refuse an agent that waits for deletion with 404 AGENT_NOT_FOUND: POST /inbox/tickets/takeover and POST /inbox/tickets/{ticketId}/team. A refused team move keeps the current team and writes no ticket event. Assignment, status changes, replies, notes, and close do not read the agent, so they still work on the same ticket. Match on the error code and read the ticket again before you retry.

    AI Compose and Copilot draft help a human workflow. They do not send a reply by themselves. Before your integration calls the ticket reply endpoint, a responsible actor must review the proposed content. Log ticket identifiers and error codes. This makes routing and permission failures easy to investigate.

    Attach a file to a reply

    POST /inbox/tickets/{ticketId}/attachments stores one file for a ticket and returns {uploadId, filename, contentType, sizeBytes}. Pass the uploadId in the attachmentUploadIds of POST /inbox/tickets/{ticketId}/reply. An upload id attaches to one message only. The route is also the MCP tool upload_attachment, and it needs a token with mcp:send that acts for a person. An API key gets 412 ACTOR_NOT_USER, the same refusal the reply route gives it, because a file uploaded with a key could never be sent.

    Send exactly one of two bodies. {filename, contentType, dataBase64} carries the bytes inline, at most 10 MB once decoded. {sourceUrl, filename?} names an https URL that the server fetches, at most 25 MB, and takes the type from the response. The server refuses a URL that resolves to a private or internal address, re-checks each redirect, and follows at most three. The allowed types match the Inbox composer: images except SVG, plain text, and PDF. A PNG, JPEG, WebP or GIF must really be that image. Errors: 400 ATTACHMENT_SOURCE_INVALID (not exactly one body shape, bad base64, or a URL that is not https), 400 ATTACHMENT_SOURCE_BLOCKED (an internal address), 413 ATTACHMENT_TOO_LARGE, 415 ATTACHMENT_TYPE_NOT_ALLOWED, 502 ATTACHMENT_FETCH_FAILED, and 404 TICKET_NOT_FOUND.

    A request body on the platform is limited in size, so a large file sent as base64 can be refused before it reaches the API. For a file over about 3 MB, prefer sourceUrl.

    Find a ticket and check email delivery

    GET /mcp/tickets/find finds a ticket by text, by customer email, or by the chat session that the ticket came from. Give at least one of query, customerEmail, or chatSessionId. A call with none of them is refused with 400 INVALID_INPUT. The filters combine with AND, and the response returns at most 100 rows in the same shape as the ticket list.

    GET /mcp/tickets/{ticketId}/email-deliveries lists the outbound emails on one ticket, newest first, at most 100. Each row gives the recipient, the subject, the SendGrid delivery status, the delivered time, and the bounce reason. It covers the email threads that are linked to the ticket itself, such as fallback emails. Replies on an email-channel conversation are not linked to one ticket, so they are not listed. It reports only what SendGrid did with an email. A ticket that does not exist, or that you cannot see, returns 404 TICKET_NOT_FOUND. The ticket list field undeliveredReason gives the stored reason that the fallback path refused, or null.

    Both routes are under /api/v1/mcp/ and they are also the MCP tools find_tickets and list_email_deliveries. They need the same Standard plan as the other inbox routes. A lower plan gets 402 PLAN_GATE_FAILED.

    Changes

    • 2026-10-20 — New route POST /inbox/tickets/{ticketId}/attachments uploads a file for a reply from base64 or an https URL.
    • 2026-09-24 — GET /inbox/tickets accepts view=undelivered. The view lists tickets whose reply could not reach the customer. Each ticket row has a new undeliveredReason field. It gives the stored reason that the fallback path refused, or null when no refusal is stored. An undelivered ticket can also have null: its fallback attempts ran out, or it has no fallback email thread.
    • 2026-09-24 — New route GET /mcp/tickets/find finds a ticket by text, customer email, or chat session.
    • 2026-09-24 — New route GET /mcp/tickets/{ticketId}/email-deliveries lists the SendGrid outcome of each outbound email on a ticket.

    REST API: conversations and notes

    Inspect conversations, send messages, and manage durable notes.

    REST API: chat

    Request synchronous or streaming chat responses from a backend service.

    On this page

    Attach a file to a replyFind a ticket and check email deliveryChanges