/v1/admin/tickets/{ticket}/aiThe /ai command of the website's reply box: the assistant writes the next
reply to the trader, following your instruction. The instruction itself stays
behind as an internal note, so the team can see what was asked for, while the
trader only ever sees the answer.
That note is what this answers with. The reply follows a few seconds later:
it is written on the ticket's channel as text_delta, and lands in
the conversation as a message from ai
once it is done. See listen on a websocket.
The ticket stays with whoever holds it. The assistant does not take the
conversation over, and the status moves to awaiting_trader like any other
reply. It works on a ticket where the assistant is
blocked: the block is about the trader
calling it in, not about the team using it.
When the assistant cannot answer, because the firm's AI allowance is used up
or the AI is down, a note with the event ai_command_failed follows instead,
and nothing reaches the trader.
Every call is a reply written by the AI
It counts against the firm's AI allowance like any answer of the assistant.
Retrying with the same Idempotency-Key asks once.
Needs a firm. Our own staff name one with the Propper-Workspace header.
Request
| Field | Description |
|---|---|
instruction | What the assistant should write, up to 2000 characters. Required |
curl -X POST "https://api.proppertrading.com/v1/admin/tickets/tkt_rqfzx8upvc24x5sg/ai" \
-H "Authorization: Bearer ptat_9f2c1a44_3b8e7d2f5c9a1b4e6d8f0a2c4e6b8d1f" \
-H "Propper-Workspace: acme" \
-H "Idempotency-Key: 9c1e3a5b-7d9f-4b2d-8e4a-6c8e0a2b4d6f" \
-H "Content-Type: application/json" \
-d '{"instruction": "Ask politely which device they trade from, in one sentence."}'
Response
201, with the note:
{
"data": {
"object": "ticket_message",
"id": "tmsg_uhvtxfdk5kx28qmh",
"ticket_id": "tkt_rqfzx8upvc24x5sg",
"from": "admin",
"author": "Ios Tester",
"body": "/ai Ask politely which device they trade from, in one sentence.",
"image_url": null,
"image_name": null,
"internal": true,
"streaming": false,
"via_email": false,
"event": "ai_command",
"read_at": null,
"created_at": "2026-10-15T22:20:47+00:00"
},
"meta": {
"request_id": "req_01m50sxk3v8q2r7hm4tn6wd9fa"
}
}
Errors
| Status | Code | Meaning |
|---|---|---|
| 400 | workspace_required | Asked by our own staff without naming a firm |
| 400 | missing_idempotency_key | A POST without an Idempotency-Key header |
| 401 | invalid_token | Not a token, or the secret does not match |
| 401 | revoked_token | Signed out here or from another device |
| 401 | expired_token | Ninety days without use, or a set expiry passed |
| 403 | admin_access_required | This account no longer helps run the environment |
| 403 | insufficient_scope | This device does not hold admin:write |
| 403 | workspace_not_permitted | The Propper-Workspace header names an environment this account cannot act in |
| 403 | forbidden | Without view_tickets and manage_tickets |
| 404 | resource_not_found | No ticket with that id in this firm |
| 409 | ticket_ended | The ticket was resolved or closed |
| 409 | assistant_unavailable | The firm switched the assistant off for its team. The ticket's can.ai says so in advance |
| 422 | validation_failed | No instruction, or one longer than 2000 characters |