Semarize

API guide

Async Runs

How to create Semarize runs, poll for completion, handle sync fallback, and use webhooks for terminal run events.

Run lifecycle

A run executes a Kit against one conversation input. The default behavior is async: POST /v1/runs returns 202 with a run_id, then your client polls GET /v1/runs/{runId} until the run reaches a terminal state.

StatusMeaningClient action
queuedAccepted and waiting for execution.Poll again after the advised delay.
runningExecution has started.Keep polling with backoff.
succeededOutput is ready under output.bricks.Read, validate, and persist the structured output.
failedExecution ended with an error.Read error_code, error_message, and error_user_message when present.
cancelledExecution did not continue.Treat as terminal and decide whether a new run is appropriate.

Create an async run

Send conversation input plus a Kit identifier. Use kit_code for stable published Kit calls or kit_version_id when the integration must target a specific Kit version.

POST /v1/runs
curl -X POST https://api.semarize.com/v1/runs \
  -H "Authorization: Bearer smz_live_your_key" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: call-123-kit-A1B2C3D4" \
  -d '{
    "kit_code": "A1B2C3D4",
    "mode": "async",
    "input": {
      "transcript": "Rep: What drove the urgency? Prospect: ..."
    }
  }'
A 202 response can include Retry-After. Treat that as the earliest sensible next poll time.

Polling pattern

Poll conservatively. Start with the Retry-After header when present, then use bounded exponential backoff. Avoid tight loops because run execution depends on model, Kit, and input size.

Node.js polling loop
async function waitForRun(runId, apiKey) {
  let delayMs = 1000;

  while (true) {
    const response = await fetch(`https://api.semarize.com/v1/runs/${runId}`, {
      headers: { Authorization: `Bearer ${apiKey}` },
    });

    if (response.status === 429) {
      const retryAfter = Number(response.headers.get("Retry-After") || "5");
      await sleep(retryAfter * 1000);
      continue;
    }

    const run = await response.json();
    if (run.status === "succeeded") return run.output;
    if (run.status === "failed" || run.status === "cancelled") throw new Error(run.error_message || run.status);

    await sleep(delayMs);
    delayMs = Math.min(delayMs * 2, 10000);
  }
}

Sync mode fallback

mode: sync asks Semarize to wait for completion within the request cycle. A 200 response means the request cycle completed and the run detail is returned. Inspect the run status in the body to decide whether the run succeeded.

If the run does not complete in time, Semarize can return 202 with sync_fallback: true and waited_ms. Continue with the normal async polling flow using the returned run_id.

Webhooks

For push delivery, configure a workspace webhook. Semarize sends terminal events such as run.succeeded, run.failed, and run.cancelled. Webhook payload data uses the same public run detail boundary as GET /v1/runs/{runId}.

  • Verify Semarize-Signature before trusting a webhook payload.
  • Dedupe on Semarize-Delivery-Id or Semarize-Event-Id.
  • If a thin event omits output, fetch GET /v1/runs/{runId} before updating downstream systems.

Related guides