Send a message to a run
The agent reads it at its next step boundary (before its next model call; a call or tool under way is not interrupted), as a user turn of its own (never inside page or tool text), and it then shows as a message step. A run paused because it asked for help takes the message as the answer and goes on; runs paused by a person (Pause a run), for a CAPTCHA, or for the model provider's safety checks get it after the resume (only a resume acknowledges safety checks). Values of the run's variables and secrets in it are replaced by their %name%. 409 invalid_state once the run has finished (use Resume a run for a run that stopped at its step limit), 409 run_not_live (or session_ended) when the server running it stopped, 409 too_many_messages after 50 to one run. 10 per minute per run, 60 per minute per project.
/v1/agent/runs/{id}/messagesRequest
| Method and path | POST/v1/agent/runs/{id}/messages |
|---|---|
| Base URL | https://api.boxline.dev |
| Authentication | Your API key in the x-api-key header (or Authorization: Bearer). The examples read it from BOXLINE_API_KEY. |
| Safe retries | Send an Idempotency-Key header to retry without creating anything twice. See Idempotency keys. |
| Rate limit | Yes. See Rate limits for the numbers and headers. |
Path parameters
| Name | Type | Default | Allowed values | Description |
|---|---|---|---|---|
idrequired | string | – | – |
Headers
| Name | Type | Default | Allowed values | Description |
|---|---|---|---|---|
Idempotency-Key | string | – | – | Makes a retry safe: the same key and body within 24 hours returns the first response (with Idempotent-Replayed: true) instead of creating something twice. 1 to 255 printable ASCII characters without spaces, e.g. a UUID. Keys belong to the project (a new API key is replayed only to its caller). At most 300 new keys per minute per project (429). 1 to 255 characters. |
Body
JSON with content-type: application/json. Required.
| Name | Type | Default | Allowed values | Description |
|---|---|---|---|---|
textrequired | string | – | – | 1 to 2000 characters. |
curl -X POST "https://api.boxline.dev/v1/agent/runs/$RUN_ID/messages" \ -H "x-api-key: $BOXLINE_API_KEY" \ -H "content-type: application/json" \ -H "Idempotency-Key: $(uuidgen)" \ -d '{"text": "Also open page C and include its heading in the answer."}'import { Boxline } from "@boxline/sdk";const bx = new Boxline(); // reads BOXLINE_API_KEY and BOXLINE_API_URLconst sent = await bx.agent.sendMessage("RUN_ID", "Also open page C and include its heading in the answer.");console.log(sent.id, sent.delivered); // false now; the agent reads it at its next stepfrom boxline import Boxlinebx = Boxline() # reads BOXLINE_API_KEY and BOXLINE_API_URLsent = bx.agent.send_message("RUN_ID", "Also open page C and include its heading in the answer.")print(sent["id"], sent["delivered"]) # False now; the agent reads it at its next stepboxline message RUN_ID "Also open page C and include its heading in the answer."Responses
202
Queued for the agent's next step.
Headers
RateLimit-Limit: Requests allowed in the current window of this route's limit. (Rate limits)RateLimit-Remaining: Requests left in the current window. (Rate limits)RateLimit-Reset: Seconds until the window starts again. (Rate limits)Idempotent-Replayed:truewhen this is the kept response of an earlier request with the same Idempotency-Key. (Idempotency keys)
Fields
| Name | Type | Default | Allowed values | Description |
|---|---|---|---|---|
id | string | – | – | |
at | string | – | – | Format: date-time. |
delivered | boolean | – | false |
{ "id": "msg_Hk2Lq8Zx0Vb5Nm1C", "at": "2026-09-29T10:00:00.000Z", "delivered": false}Errors
Errors have a matching HTTP status and the same body. code is stable, so check it in your code; message is for people. See Errors and request ids.
| Status | Codes | When |
|---|---|---|
| 400 Bad Request | invalid_request, invalid_json, invalid_cursor, invalid_idempotency_key, invalid_extension, variables_with_extensions, terms_not_accepted, invalid_reset_token, invalid_confirmation_code, wrong_password, no_password, invalid_next, invalid_oauth_token | The request is not valid. |
| 401 Unauthorized | unauthorized | Missing or invalid API key. |
| 404 Not Found | not_found, invite_not_found, provider_unavailable | No such thing in this project (or organization), or no such route. |
| 409 Conflict | session_not_running, shell_disabled, browser_disabled, nothing_saved, not_resumable, invalid_state, conflict, email_taken, identity_in_use, provider_already_linked, last_sign_in_method, not_impersonating, machine_too_old, too_many_credential_values, limit_reached, terms_version_mismatch, no_project, last_owner, organization_not_empty, project_has_sessions, already_member, invite_pending, idempotency_in_progress | The current state does not allow it, or a request with this Idempotency-Key is still being answered. |
| 422 Unprocessable Content | idempotency_mismatch | This Idempotency-Key was already used for a different request. |
| 429 Too Many Requests | rate_limited, concurrency_limit | Too many requests, or the organization's concurrent sessions (its plan's) or the project's concurrencyCap are in use. |
{ "error": { "code": "not_found", "message": "session not found", "requestId": "req_4fJx0aQm2Lk9Pz7N" }}Learn more
These docs describe a beta API. Endpoints, fields and SDK methods may change before general availability; breaking changes will be listed in the changelog.