emit.run

Authentication

How to authenticate with the emit.run API

Authentication

All API requests authenticate with an API key passed via request header.

API Keys

API keys authenticate all job-related operations. Pass the key via either header:

x-api-key: emit_YOUR_KEY
Authorization: Bearer emit_YOUR_KEY

Keys are scoped to a single space — a key created for space A cannot access jobs in space B.

Keys are prefixed with emit_ and the full key is only shown once at creation time.

Rate Limits

API keys are rate-limited to 1000 requests per second. If you exceed this, you'll receive a 429 response.

Scopes Reference

Each API key has one or more scopes that control what it can do. Scopes are checked on every request — if your key is missing a required scope, you'll get a 403 with the message Missing required scope: <scope>.

Granular Scopes

ScopeDescriptionUsed by
jobs:createCreate new jobs in a spacePOST /spaces/:id/jobs
jobs:readList jobs, get job details and eventsGET /spaces/:id/jobs, GET /jobs/:id
jobs:pollClaim pending jobs from the dispatch queuePOST /spaces/:id/jobs/poll
jobs:ackAcknowledge receipt of a polled jobPOST /jobs/:id/ack
jobs:progressSend in-progress updates for a running jobPOST /jobs/:id/progress
jobs:eventPublish checkpoint events (for resumable work)POST /jobs/:id/event
jobs:completeMark a job as successfully completedPOST /jobs/:id/complete
jobs:failMark a job as failedPOST /jobs/:id/fail
jobs:keepaliveExtend a running job's timeoutPOST /jobs/:id/keepalive
jobs:read:progressSubscribe to a single job's WebSocket stream (no space-wide feed)GET /realtime/:id

Shorthand Scopes

These expand to multiple granular scopes for convenience. You can use them when creating tokens, and they'll be recognized during authorization.

ShorthandExpands to
jobs:workerjobs:read, jobs:poll, jobs:ack, jobs:progress, jobs:event, jobs:complete, jobs:fail, jobs:keepalive
jobs:writejobs:ack, jobs:progress, jobs:event, jobs:complete, jobs:fail, jobs:keepalive

jobs:worker is the most common — it includes everything a worker needs to poll, process, and report results.

RoleScopesWhy
Producerjobs:createCan only submit jobs, nothing else
Workerjobs:workerFull worker lifecycle: poll → ack → progress → complete/fail
Dashboard / monitorjobs:readREST read + both WS streams (job and space-wide)
Producer + monitorjobs:create, jobs:readSubmit jobs and watch them complete
Third-party clientjobs:read:progressSingle-job stream only — progress bar without space-level access
Minimal workerjobs:poll, jobs:ack, jobs:complete, jobs:failWorker without progress/event/keepalive

WebSocket Auth

WebSocket connections authenticate via ?token= query parameter — required on all realtime endpoints:

wss://emit.run/api/v1/realtime/:jobId?token=emit_YOUR_KEY
EndpointMinimum scope
GET /realtime/:jobIdjobs:read:progress
GET /realtime/spaces/:spaceIdjobs:read

jobs:read:progress only grants access to single-job streams — it cannot connect to the space-wide stream. This makes it safe to embed in frontend code for client-facing progress bars.

Space scoping is enforced on both endpoints: a space-scoped token can only subscribe to its own space's stream and to jobs within that space. Connecting to a job in a different space returns 403.

Your scope also controls what data you receive. With jobs:read:progress, progress and init events are delivered in full, but the data field is stripped from every other event type — this covers result payloads (completed), error details (dead), checkpoint payloads (checkpoint), and retry information including the error and attempt number (retried). Clients still receive the event type and status for every event, so they always know what happened. With jobs:read, you receive full event data for every event type. See WebSockets for details.

On this page