emit.run

Query Jobs

List jobs, get details, progress, and logs

Query Jobs

Endpoints for reading job data. All require an API key with jobs:read scope (except Get Progress which also accepts jobs:read:progress).


List Jobs

GET /api/v1/spaces/:spaceId/jobs

Scope: jobs:read

Query params:

ParamRequiredDefaultDescription
statusNoFilter: pending, delivered, running, completed, dead, killed
limitNo50Max results (max: 100)
offsetNo0Pagination offset
curl "https://emit.run/api/v1/spaces/$SPACE_ID/jobs?status=running&limit=20" \
  -H "x-api-key: $EMIT_KEY"
const res = await fetch(
  `${API}/spaces/${spaceId}/jobs?status=running&limit=20`,
  { headers: { "x-api-key": key } }
);
const jobs = await res.json();
res = requests.get(
    f"{API}/spaces/{space_id}/jobs",
    headers={"x-api-key": key},
    params={"status": "running", "limit": 20},
)
jobs = res.json()

Response:

[
  {
    "id": "01JLQX...",
    "spaceId": "01JLQ...",
    "name": "process-video",
    "payload": { "url": "s3://bucket/video.mp4", "format": "720p" },
    "status": "running",
    "maxRetries": 5,
    "attemptNumber": 1,
    "timeoutSeconds": 600,
    "deliveredAt": "2025-02-24T10:31:00.000Z",
    "startedAt": "2025-02-24T10:31:05.000Z",
    "completedAt": null,
    "result": null,
    "createdAt": "2025-02-24T10:30:00.000Z",
    "updatedAt": "2025-02-24T10:31:05.000Z"
  }
]

Ordered by creation time (newest first). Returns an empty array if no jobs match.


Get Job

GET /api/v1/jobs/:jobId

Scope: jobs:read

Fetch a job's full details including its event history. Log lines are stored separately and queried via Get Job Logs.

curl https://emit.run/api/v1/jobs/$JOB_ID \
  -H "x-api-key: $EMIT_KEY"
const res = await fetch(`${API}/jobs/${jobId}`, {
  headers: { "x-api-key": key },
});
const job = await res.json();

Response:

{
  "id": "01JLQX...",
  "spaceId": "01JLQ...",
  "name": "process-video",
  "payload": { "url": "s3://bucket/video.mp4", "format": "720p" },
  "status": "completed",
  "maxRetries": 5,
  "attemptNumber": 0,
  "timeoutSeconds": 600,
  "callbackUrl": "https://example.com/webhooks/jobs",
  "callbackHeaders": { "Authorization": "Bearer your-secret" },
  "deliveredAt": "2025-02-24T10:31:00.000Z",
  "startedAt": "2025-02-24T10:31:05.000Z",
  "completedAt": "2025-02-24T10:34:20.000Z",
  "result": { "output_url": "s3://bucket/output.mp4", "duration_ms": 12340 },
  "createdAt": "2025-02-24T10:30:00.000Z",
  "updatedAt": "2025-02-24T10:34:20.000Z",
  "events": [
    {
      "id": "01JLQY...",
      "jobId": "01JLQX...",
      "spaceId": "01JLQ...",
      "type": "created",
      "data": null,
      "createdAt": "2025-02-24T10:30:00.000Z"
    },
    {
      "id": "01JLR0...",
      "jobId": "01JLQX...",
      "spaceId": "01JLQ...",
      "type": "completed",
      "data": { "output_url": "s3://bucket/output.mp4", "duration_ms": 12340 },
      "createdAt": "2025-02-24T10:34:20.000Z"
    }
  ]
}
{ "error": "Job not found" }

Get Job Progress

GET /api/v1/jobs/:jobId/progress

Scope: jobs:read:progress or jobs:read

Return the most recent progress update (if any). This endpoint only exposes progress data.

curl https://emit.run/api/v1/jobs/$JOB_ID/progress \
  -H "x-api-key: $EMIT_KEY"
const res = await fetch(`${API}/jobs/${jobId}/progress`, {
  headers: { "x-api-key": key },
});
const progress = await res.json();

Response:

{
  "jobId": "01JLQX...",
  "progress": {
    "percent": 65,
    "message": "Encoding video",
    "subProgress": {
      "download": { "percent": 100, "message": "Source fetched" },
      "transcode": { "percent": 42, "message": "Pass 1/2" }
    }
  },
  "timestamp": "2025-02-24T10:32:00.000Z"
}

If no progress has been reported yet, progress and timestamp are null.


Get Job Logs

GET /api/v1/jobs/:jobId/logs

Scope: jobs:read

Query logs for one job. Optimized for tailing (after) and infinite-scroll history (before).

Query params:

ParamRequiredDefaultDescription
limitNo200Max logs to return (max: 500)
afterNoReturn logs with seq greater than this value (tail mode)
beforeNoReturn logs with seq lower than this value (history mode)
qNoFull-text query on message
levelNoFilter by one or more levels (trace, debug, info, warn, error, fatal)

Use either after or before (not both).

curl "https://emit.run/api/v1/jobs/$JOB_ID/logs?after=1200&limit=100" \
  -H "x-api-key: $EMIT_KEY"
const res = await fetch(`${API}/jobs/${jobId}/logs?after=${lastSeq}&limit=100`, {
  headers: { "x-api-key": key },
});
const page = await res.json();

Response:

{
  "logs": [
    {
      "id": "01JLOG...",
      "seq": 1201,
      "level": "info",
      "message": "downloaded source chunk",
      "source": "worker-a",
      "metadata": { "chunk": 12 },
      "loggedAt": "2026-03-01T09:21:01.120Z",
      "createdAt": "2026-03-01T09:21:01.125Z"
    }
  ],
  "cursor": {
    "mode": "after",
    "oldestSeq": 1201,
    "newestSeq": 1201,
    "hasMore": false
  }
}

On this page