Skip to content

Trigger an automation through the API

On this page

An API automation lets a script or another service start an agent task by sending an HTTP request. For example, a monitoring service could ask an agent to investigate a failed check in your project.

Create and call the trigger

  1. In your project's Automations section in the desktop app, choose New automation, then choose the API trigger.
  2. Enter a name and prompt, review the agent and model settings, and choose Create. The automation will start paused.
  3. In API setup, review Request mode. Keep Configurable to let callers change the task for each run, or choose Fixed defaults to accept only the saved task.
  4. Choose Generate secret. Copy the secret and the Run endpoint into the calling service's secure configuration, and keep both private: anyone with the endpoint and secret can start work using the automation's project access and usage allowance.
  5. Choose Activate to allow API requests.
  6. Send a POST request to the run endpoint with a JSON body and an Authorization: Bearer <secret> header.

You can also ask an agent in your project to set up the API trigger. It will ask for permission to edit your automations, and it will receive the secret once, when it saves the trigger, so ask it where to keep the secret.

For an initial test, set AUTOMATION_RUN_URL to the automation's Run endpoint and AUTOMATION_SECRET to the secret you generated, storing both securely on the calling system, then run:

curl --request POST "$AUTOMATION_RUN_URL" \
  --header "Authorization: Bearer $AUTOMATION_SECRET" \
  --header 'Content-Type: application/json' \
  --header 'Idempotency-Key: test-run-001' \
  --data '{}'

The empty JSON object will use the saved prompt and agent settings in either request mode. You can also copy an example from Request examples in the automation's API setup section.

The optional Idempotency-Key header prevents retries from starting duplicate runs. Choose a new key for each intended run. If you don't know whether a request succeeded, retry with the same key and input to receive the original run. Reusing a key with different input will return a conflict.

Choose fixed or configurable input

Under Request mode, choose Fixed defaults when every call should use the saved task; this mode accepts only {}. Choose Configurable when the calling service needs to change the task or agent settings for each run. Configurable requests accept these optional fields:

FieldMeaning
promptReplaces the saved prompt for this run; it is not appended.
threadTitleNames the new thread without renaming the automation.
executionReplaces the agent, provider connection, model, reasoning, and speed settings.
targetStarts a new thread on a devbox created by this automation, or sends a follow-up to an existing thread you own in this project. Omit it to create a new devbox.

For example, send this body to change only the task and thread title:

{
  "prompt": "Investigate the failing billing tests and report what changed.",
  "threadTitle": "Billing test investigation"
}

Omitted top-level fields will keep their saved defaults. If you supply execution, include a complete selection with backend, model, and reasoningEffort; individual execution fields are not merged with the defaults. Use codex or claude for backend, and a model and reasoning combination offered in the product. For models without a reasoning control, use null for reasoningEffort. To copy a complete, valid execution example with current model options, use Request examples in API setup.

For Codex with OpenRouter, Vercel, or a custom endpoint, include the saved connection's codexProviderConnectionId in execution. Copy the editor's request example to get that ID and its model settings; never put the provider API key in the request. Within an explicit execution object, omitting the connection ID or setting it to null will select OpenAI. Omit the entire execution object to keep the automation's saved provider and model.

Codex and Claude also accept serviceTier. Omitting it will select standard. OpenAI models may also offer fast or ultrafast; other Codex providers use standard. For Claude, fast turns on fast mode and works only with models that support it. Unsupported combinations, unknown fields, incomplete selections, and raw agent CLI arguments will be rejected. An unavailable or disconnected provider connection will produce a failed run with repair guidance before creating a devbox.

Your Request mode choice is saved as soon as you select it. Switching from Fixed defaults to Configurable will rotate the secret, because the change widens what a caller can do: with the new secret, callers can give the agent arbitrary instructions and use anything the agent can access on the devbox. Copy the replacement secret into the calling service.

Start workflows on the same devbox

For one devbox per issue, start the first run without target. Wait for its status to reach thread_ready, then save the returned devboxId with the issue. Send later workflows to the same run endpoint with a new idempotency key and, for example, this body:

{
  "prompt": "Implement the plan saved in issue-plan.md.",
  "threadTitle": "Build the feature",
  "target": { "kind": "existing_devbox", "devboxId": "<saved devboxId>" }
}

Each request creates a separate run and conversation on the same filesystem. The new thread does not inherit another thread's conversation; save plans and handoffs in files or include them in the prompt. Threads can run concurrently, so coordinate workflows that edit the same files or change branches.

Only devboxes created by this automation can be targeted. A missing, still starting, archived, destroying, or inaccessible target returns 409 devbox_unavailable; the request will not create a replacement devbox. If the target becomes unavailable after acceptance, the run can fail during startup. Check its status URL for details.

A sleeping target will wake if capacity is available. Reusing an awake devbox does not need another awake slot. The option to sleep an idle devbox applies to new-devbox requests; a blocked wake will instead appear as a failed run with startup_active_fork_limit_reached.

Choose Never under Devbox cleanup to retain an issue's devbox between workflows. Cleanup follows the first run's setting, and automatic cleanup keeps a devbox once another thread has started on it. Runs sharing a devbox appear in one sidebar group; each run remains available in run history.

Send requests to one standing thread

For a shared to-do list or another ongoing conversation, send each request to the same thread. Copy its boxes.dev thread ID from dvb threads list, or save the clientThreadId returned by an earlier API run. Send a new idempotency key for each task and a body such as:

{
  "prompt": "Add reviewing the forwarded invoice to my to-do list.",
  "target": { "kind": "existing_thread", "threadId": "<threadId>" }
}

The thread must belong to you and to the automation's project. It can be a thread you started yourself or through Slack; it does not need to come from this automation. The prompt will start a turn if the agent is idle, or queue after its current turn if it is busy. Both Codex and Claude Code are supported. A Claude follow-up can run once its response has ended, even if a background command is still running. The command will continue running. A sleeping box will wake if capacity is available; an awake target needs no additional awake slot.

The thread will keep its title, conversation, agent settings, location, and notification behavior. Omit threadTitle and execution; the API rejects these fields for an existing thread. Omit prompt to send the automation's saved prompt. The request will add a run to automation history without creating a thread or devbox. The automation's devbox cleanup and Slack output destinations do not apply to these follow-ups.

An unavailable, archived, deleted, or history-only thread returns 409 thread_unavailable. The API also rejects threads owned by someone else or in another project. If the thread becomes unavailable after acceptance, check the status URL for the delivery error. A retried request with the same idempotency key and input will return the original run without another message.

Follow the accepted run

An accepted request returns HTTP 202 with JSON describing the launch. These are the main fields:

FieldMeaning
runPublicIdThe ID of the run that was created.
statusUrlThe URL to check the run's launch status.
statusstarting, thread_ready, failed, or skipped.
effectiveThe threadTitle, backend, model, reasoningEffort, serviceTier, and promptSource selected for this run, plus codexProviderConnectionId when recorded.
clientThreadIdThe new or targeted thread's ID, or null before the thread exists.
followUpFor an existing-thread request, its send operation and disposition: started or queued after acceptance by the agent. Otherwise null.
devboxIdThe devbox ID once assigned, otherwise null. Wait for thread_ready before using it as a target.
statusReasonCode, statusReasonMessageDetail about the status when available, otherwise null.
idempotentReplaytrue when the response returns the original run for a retried idempotency key.
requestIdAn identifier for this request.

The status endpoint reports launch progress. It does not return the prompt, agent completion status, or final answer. Open the run's thread from the automation in boxes.dev to read the agent's work.

To check launch progress, set AUTOMATION_STATUS_URL to the response's statusUrl value, then send a GET request with the same secret:

curl "$AUTOMATION_STATUS_URL" \
  --header "Authorization: Bearer $AUTOMATION_SECRET"

The thread_ready status means the run's new thread exists, or its follow-up was accepted as started or queued in the existing thread. The agent may still be working. Independent requests can start runs in parallel, subject to your awake devbox limit; an idempotency key only groups retries of the same request.

If a request is rejected, check that the automation is active and has no reported error, then check your awake devbox capacity. Draft and paused automations do not accept API runs. For the option to sleep an idle devbox to make room, see capacity behavior.

Rotate access and test changes

If the secret is exposed, choose Rotate secret in API setup and update the calling service with the replacement. Keep secrets out of documents, tickets, repositories, agent prompts, and public URLs.

After changing the saved prompt, agent settings, or capacity options, choose Save changes. Then send a representative request with a new idempotency key, check the settings returned in the response, and inspect the resulting thread.