Endpoints · 01

Trigger a webhook.

Send a JSON event scoped to an agent. Conversational agents receive it as a new message; workflow agents start a new run.

POST /api/agents/webhook/{agent_id}

Request

Path parameters

NameTypeDescription
agent_id string The agent that should receive the event. Copy it from the agent detail page in Studio.

Headers

HeaderRequiredDescription
AuthorizationYes Bearer ak_<your-access-key>
Content-TypeYes application/json for ordinary JSON triggers

Body

Any JSON body up to 1 MiB. Your agent interprets the body according to its configuration in Studio. The response shape depends on the agent type — shown below as request / response pairs.

If you need to send files larger than the inline JSON cap, upload them first via the upload endpoint and reference the returned fi_* id from your JSON body.

Conversational agent

The body lands as a new message in the agent's activity feed. The response returns the agent's reply inline, plus identifiers you can use to retrieve the full message record from Session management.

Request bodyJSON
{
  "message": "Order #4421 placed for Acme Corp",
  "session_id": "sess_01JV...",
  "metadata": {
    "source": "shopify-orders-create",
    "order_id": "4421"
  }
}
FieldRequiredDescription
messageYesThe user input for this turn.
session_idNo Continue an existing conversation so the agent keeps prior context. Omit it to start a new session — the response returns the freshly minted session_id for you to store and send back on later turns. A session_id you pass must already exist; an unknown one returns 404 session_not_found.
metadataNoArbitrary JSON your agent can read; echoed into the message record.
Response  200JSON
{
  "success": true,
  "session_id": "sess_01JV...",
  "message_id": "msg_01JV...",
  "agent_id": "agt_01HAKZ...",
  "organization_id": "org_01GZ...",
  "project_id": "proj_01HB...",
  "response": "Order received — I'll start processing right away.",
  "files": [],
  "token_usage": {
    "prompt_tokens": 412,
    "completion_tokens": 18,
    "total_tokens": 430
  },
  "processing_time": 1.24,
  "timestamp": "2026-05-27T08:14:22.381Z"
}
FieldDescription
session_idIdentifies the conversation session. Stable across messages in the same thread.
message_idUnique ID for this agent message. Use it to fetch the full record from Session management.
agent_idThe agent that processed the request.
organization_idThe org the agent belongs to.
project_idThe project the agent belongs to.
responseThe agent's reply text.
filesFiles the agent generated during this turn (currently PDFs from the pdf_generator tool). Always an array — empty when the agent didn't produce a file. See Generated files.
token_usagePrompt, completion, and total token counts for this message.
processing_timeWall-clock seconds from request receipt to response.

Generated files

When the agent runs a tool that produces a file (today, only the pdf_generator tool configured in Studio), the rendered file is uploaded to Firebase Storage and surfaced under files. Each entry is independently fetchable — the download token is baked into the URL, so no auth header is required.

Response  200 with a generated PDFJSON
{
  "success": true,
  "session_id": "sess_01JV...",
  "message_id": "msg_01JV...",
  "agent_id": "agt_01HAKZ...",
  "organization_id": "org_01GZ...",
  "project_id": "proj_01HB...",
  "response": "Here's your receipt — let me know if anything looks off.",
  "files": [
    {
      "file_url": "https://firebasestorage.googleapis.com/v0/b/.../o/agents%2Fagt_01HAKZ...%2Fgenerated_pdfs%2Fpdfgen-xyz.pdf?alt=media&token=...",
      "filename": "Order_Receipt.pdf",
      "size_bytes": 18342,
      "kind": "generated_pdf"
    }
  ],
  "token_usage": { "prompt_tokens": 612, "completion_tokens": 84, "total_tokens": 696 },
  "processing_time": 2.61,
  "timestamp": "2026-05-27T08:14:24.902Z"
}
Per-entry fieldDescription
file_urlDirect, tokenised Firebase Storage URL. Fetch with a plain GET — no auth.
filenameSlugified filename derived from the tool's title argument.
size_bytesSize of the generated file in bytes.
kindSource of the file. Currently always "generated_pdf"; new kinds may appear as more file-producing tools land.

Workflow agent

A new workflow run is created. Poll Run management with the returned run_id to track progress and retrieve outputs.

The body is a flat JSON object whose top-level keys are the workflow's input-schema field names (shown on the agent's Triggers tab). Pass a file input as a { "file_id": "fi_..." } object — or an array of them for a file-list input — placed directly under its field. Each field is referenced downstream as {{trigger.<field>}}. Do not wrap the fields in an inputs object; the whole body is stored as the trigger payload verbatim, so a wrapper would make the fields resolve as {{trigger.inputs.<field>}}.

Request bodyJSON
{
  "customer_email": "buyer@example.com",
  "amount_inr": 1499,
  "contract": { "file_id": "fi_a1b2c3d4e5f6..." }
}
Response  200JSON
{
  "run_id": "abfcbeef-6d3a-4ab3-aca7-516cbff72d01",
  "status": "triggered"
}
Agent type is transparent

You don't specify the agent type in your request — it's configured in Studio. Changing the type later does not break existing webhook URLs.

Errors

Errors specific to this endpoint:

StatusWhen
401Missing or malformed Bearer; key not found, revoked, or expired.
404Agent doesn't exist, or belongs to a different org than the key.
404 session_not_foundA session_id in the body doesn't exist. Omit it to start a new session.
413Body exceeded the 1 MiB limit.
502Upstream failure. Retry with backoff.

For the full list, see Errors.

Retries & idempotency

Retry on 502, 503, and 504 with exponential backoff — start at 1 s, cap at 60 s, give up after roughly 10 minutes. Do not retry on 4xx.

If a retry could produce a duplicate side effect, include an Idempotency-Key field inside your JSON body. Your agent or workflow can dedupe against it.