Documentation

Jobs API

Poll the status of asynchronous AI builds for widgets and agents.

When you create a widget or agent with a build prompt, the API returns a jobId. Use the Jobs endpoint to poll for completion.

GET /v1/jobs/:jobId

Response

{
  "jobId": "job_1776081418601_b5049f7fd47c",
  "status": "completed",
  "progress": {
    "step": "complete",
    "message": "Build complete"
  },
  "result": {
    "buildId": "EmbeddableAppBuilder:557c1aeb-...",
    "widgetId": "Wbk5MPTfzx"
  },
  "error": null,
  "buildStatus": {
    "buildId": "EmbeddableAppBuilder:...",
    "status": "SUCCEEDED",
    "phase": "COMPLETED",
    "startTime": "..."
  },
  "createdAt": "...",
  "updatedAt": "..."
}

Status values

ValueMeaning
pendingJob created, build hasn't started yet
buildingAI is generating files, or compile is running
completedAI build finished successfully
failedBuild crashed — see error

Build status (widgets only)

For widgets, after the AI finishes generating files, an AWS CodeBuild compile is triggered. The job's status becomes completed once the AI is done, but the widget isn't safe to publish until buildStatus.status is SUCCEEDED.

buildStatus.statusMeaning
IN_PROGRESSCompile is running (phase shows what stage)
SUCCEEDEDCompile finished — safe to publish
FAILEDCompile errored — failureDetails has the cause

Agents skip CodeBuild entirely, so result.buildId is null and there is no buildStatus.

while true; do
  STATUS=$(curl -s https://api.embeddable.co/v1/jobs/$JOB_ID \
    -H "Authorization: Bearer emb_live_..." | jq -r .status)
  if [ "$STATUS" = "completed" ] || [ "$STATUS" = "failed" ]; then
    break
  fi
  sleep 5
done

Recommended interval: 5 seconds. Builds typically complete in 30–120 seconds.

async function waitForBuild(jobId, apiKey) {
  while (true) {
    const res = await fetch(`https://api.embeddable.co/v1/jobs/${jobId}`, {
      headers: { Authorization: `Bearer ${apiKey}` },
    });
    const job = await res.json();
    if (job.status === "completed") return job;
    if (job.status === "failed") throw new Error(job.error);
    await new Promise((r) => setTimeout(r, 5000));
  }
}

Token cost: 0 — polling is free.

On this page