Jobs API
The Jobs API lets you trigger DAIV agents programmatically — outside of the usual git webhook flow. Submit a prompt, get a job ID, and poll for the result.
This is useful when you want to:
- Run agents on a schedule — e.g., a GitLab CI pipeline that runs nightly
- Chain agent tasks — e.g., triage tickets, then create issues from the report
- Trigger from external tools — Slack bots, scripts, or custom integrations
- Run ad-hoc tasks — quick one-off agent executions via curl
Authentication
The Jobs API uses API key authentication via Bearer tokens — the same mechanism used by the chat completions API.
Creating an API key
| Bash | |
|---|---|
This outputs a key in the format prefix.secret. Store it securely — it cannot be retrieved later.
Managing API keys
You can also self-service your API keys from the dashboard at /accounts/api-keys/. There you can:
- Create a key by giving it a name — the full secret is shown only once, right after creation, so copy it immediately.
- List your keys (admins see every user's keys).
- Revoke a key you no longer need; revoked keys stop authenticating immediately.
The create_api_key management command remains available for headless/automated provisioning.
Using the key
Pass the key in the Authorization header:
| Bash | |
|---|---|
Rate limiting
Job submissions are rate-limited per authenticated user. The default limit is 20 requests per hour. When exceeded, the API returns 429 Too Many Requests.
The rate is configured via the jobs_throttle_rate field in Site Configuration (default 20/hour). Set it to a value like:
| Text Only | |
|---|---|
Valid formats: N/sec, N/min, N/hour, N/day (or single-letter short forms: N/s, N/m, N/h, N/d).
Note
The same rate can also be set with the DAIV_JOBS_THROTTLE_RATE environment variable (or Docker secret). When set, it is a hard override that wins over the database value and locks the field in the Site Configuration UI.
Endpoints
Submit a job
| Text Only | |
|---|---|
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
repos |
array of objects | yes | 1–20 repositories to run against. Each item: { "repo_id": "group/project", "ref": "branch" } — ref is optional, must be a branch that exists on the remote, and defaults to the repository's default branch. A new MR/PR targets it, and is assigned to the API key's owner when their DAIV account is OAuth-linked to the git platform. |
prompt |
string | yes | The prompt to send to the agent. The same prompt runs as an independent job against each repository in repos. |
agent_model |
string | no | Override the model used for this batch. Invalid model / thinking-level combinations are rejected with 400. |
agent_thinking_level |
string | no | Override the agent's reasoning effort. One of minimal, low, medium, high, xhigh. Invalid combinations are rejected with 400. |
muted |
boolean | no | Mute notifications for every job in this batch. Default false. |
environment |
string | no | Select a sandbox environment (by name or id) applied to every job in the batch. An unresolvable environment is rejected with 400. |
thread_id |
string (UUID) | no | Continue an existing thread. Requires exactly one repo in repos, and the most recent run on that thread must belong to you (otherwise 400). If a prior run on the thread is still in flight, the new job is created in QUEUED state and released FIFO when that run finishes. |
references |
array of objects | no | Up to 20 external work-item references (Jira/Sentry/RT tickets, git-platform issues, …) that DAIV links into the MR/PR it creates. Each item: { "key": "PROJ-123", "url": "https://…", "provider": "jira", "relation": "relates" } — only key is required. |
references is the same schema the MCP submit_job tool takes, validated by the same code; see references on the MCP endpoint for the per-field rules, the provider list, the closes auto-close semantics, the continuation merge, and the v1 limitation on existing MRs. An invalid reference (bad key charset, non-http(s) URL, more than 20 entries) is rejected with 422 and nothing is stored.
Note
The request body is validated strictly: unknown fields (including the removed use_max toggle and the removed notify_on field) are rejected with 422. Use muted to silence notifications; use agent_model and agent_thinking_level to control the model.
Example:
| Bash | |
|---|---|
Response (202 Accepted):
| JSON | |
|---|---|
Each entry in jobs is an independent run — poll each job_id separately. The status is READY for an immediately-runnable job, or QUEUED if another run is already in flight on the same thread_id (see Job lifecycle). Pre-enqueue rejections (e.g. unknown repo_id) are reported in failed as {repo_id, ref, error}; the rest of the batch still runs.
Poll job status
| Text Only | |
|---|---|
Response (200 OK):
merge_request_url is populated when the agent produced code changes that were committed and pushed; null otherwise (e.g. read-only triage runs). thread_id identifies the thread this job ran on — pass it back as the thread_id field on a new submission to continue the conversation.
artifacts lists the files the agent published with its publish_artifact tool (reports, datasets, charts) — see Artifacts. Each entry carries the viewer page (url), a direct download (download_url), and a kind (markdown, html, image, text, or other) describing how the viewer renders it. Both url and download_url require a signed-in DAIV user who can see the run. The list is empty for runs that published nothing, and it is populated as the run progresses, so it can be read while the job is still RUNNING. If DAIV cannot list the artifacts, artifacts is empty and artifacts_error explains why; the rest of the status is unaffected.
Status values:
| Status | Meaning |
|---|---|
QUEUED |
Job is waiting for an earlier run on the same thread to finish; released FIFO. Only occurs for thread continuations (thread_id supplied). |
READY |
Job is queued, waiting for a worker |
RUNNING |
Agent is executing |
SUCCESSFUL |
Completed — result contains the agent's response summary |
WAITING_INPUT |
The agent stopped to ask you a question instead of guessing — a terminal state, not a step towards SUCCESSFUL. question holds the questions asked, and result their rendered text |
FAILED |
Agent encountered an error — error contains a message |
Answering a question
When a job comes back WAITING_INPUT, submit a new job with the same thread_id and your answer as prompt:
| Bash | |
|---|---|
This starts a new run that continues the agent's work from where it stopped. As with any thread_id continuation, repos must have exactly one entry, and the thread's most recent run must belong to you.
You don't have to poll for it: when a job ends in WAITING_INPUT, DAIV also sends you a notification listing the questions, unless you've muted it. In a multi-repo job, the run is counted in the batch rollup (and listed, in email and Rocket Chat) once every repository's run has settled.
Error responses:
For GET /api/jobs/{job_id}:
| Code | When |
|---|---|
404 |
Job ID not found or invalid |
401 |
Missing or invalid API key |
For POST /api/jobs:
| Code | When |
|---|---|
400 |
Invalid request — bad agent_model / agent_thinking_level override, unresolvable environment, or invalid thread_id continuation (unknown/unowned thread, or more than one repo). |
422 |
Malformed body or unknown fields (e.g. the removed use_max or notify_on). |
429 |
Rate limit exceeded (see Rate limiting). |
401 |
Missing or invalid API key |
Job lifecycle
stateDiagram-v2
[*] --> READY: POST /api/jobs
[*] --> QUEUED: POST /api/jobs (thread continuation, prior run in flight)
QUEUED --> READY: Prior run on the thread finishes (FIFO)
READY --> RUNNING: Worker picks up job
RUNNING --> SUCCESSFUL: Agent completes
RUNNING --> WAITING_INPUT: Agent asks a question
RUNNING --> FAILED: Agent errors
WAITING_INPUT --> READY: POST /api/jobs (same thread_id, answer as prompt)
A job only starts in QUEUED when you supply a thread_id and an earlier run on that thread is still in flight; it is released to READY (FIFO) when that run terminates. Every other submission starts at READY.
Once a job reaches SUCCESSFUL, WAITING_INPUT, or FAILED, the status is final for that job — WAITING_INPUT doesn't progress to SUCCESSFUL on its own, it waits for a new job on the same thread (see Answering a question). The result field contains the agent's text response summary (its last response, truncated to 2000 characters) — not necessarily the complete output.
Examples
Simple script
GitLab CI — Scheduled pipeline with chaining
Use the Jobs API from a scheduled GitLab CI pipeline to chain two agent tasks: triage support tickets, then create issues from the report.
Tip
Store DAIV_URL and DAIV_API_KEY as CI/CD variables in your GitLab project settings. Mark the API key as masked and protected.
Related pages
- Request Tracker Triage — an end-to-end example of using the Jobs API from an RT Scrip to triage new support tickets automatically.