AI Jobs API
REST API endpoints for dispatching and monitoring AI worker jobs.
Overview
The AI Jobs API lets you programmatically dispatch AI worker jobs, monitor their status, and retrieve their results. All endpoints require the ai-jobs:write scope to dispatch jobs and ai-jobs:read (or any read scope) to query status.
AI jobs are executed asynchronously by the Python FastAPI worker fleet. After dispatch, poll the job status endpoint until the job reaches a terminal state (completed or failed).
Job Types
| Job Type | Description | Typical Duration |
|---|---|---|
pricing_recalculate | Recompute optimal prices for SKUs | 10–60 seconds |
review_sentiment | Run NLP sentiment on new reviews | 30–120 seconds |
return_classify | Classify return reasons + detect anomalies | 20–90 seconds |
llm_visibility_score | Query LLM assistants for visibility scoring | 60–300 seconds |
competitor_scan | Fetch competitor prices for SKUs | 15–60 seconds |
listing_optimize | Generate listing improvement proposals | 30–120 seconds |
Endpoints
Dispatch Job
POST /api/ai-jobsRequired scope: ai-jobs:write
Request Body:
{
"type": "pricing_recalculate",
"params": {
"skus": ["SKU-001", "SKU-002"],
"marketplace": "amazon_us",
"apply": false
},
"priority": "normal"
}Priority levels: low, normal, high. High-priority jobs are processed first in the queue.
Response:
{
"data": {
"id": "job_01HXK9MZPQ3B8C7D2E5F6G",
"type": "pricing_recalculate",
"status": "queued",
"priority": "normal",
"params": {
"skus": ["SKU-001", "SKU-002"],
"marketplace": "amazon_us",
"apply": false
},
"created_at": "2026-03-12T14:32:01.123Z",
"estimated_completion_at": "2026-03-12T14:32:31.123Z"
}
}Get Job Status
GET /api/ai-jobs/:jobIdPoll this endpoint after dispatching a job to check progress.
Job Statuses:
| Status | Description |
|---|---|
queued | Job is waiting in the queue |
running | Worker is processing the job |
completed | Job finished successfully |
failed | Job failed after all retries |
cancelled | Job was cancelled before processing |
Example Response (completed):
{
"data": {
"id": "job_01HXK9MZPQ3B8C7D2E5F6G",
"type": "pricing_recalculate",
"status": "completed",
"started_at": "2026-03-12T14:32:05.000Z",
"completed_at": "2026-03-12T14:32:32.000Z",
"duration_seconds": 27,
"result": {
"processed_count": 2,
"updated_count": 1,
"recommendations": [
{
"sku": "SKU-001",
"current_price": 14.99,
"recommended_price": 13.49,
"confidence": 0.87,
"applied": false
},
{
"sku": "SKU-002",
"current_price": 8.99,
"recommended_price": 8.99,
"confidence": 0.92,
"reasoning": "Current price is already optimal",
"applied": false
}
]
}
}
}Example Response (failed):
{
"data": {
"id": "job_01HX...",
"type": "pricing_recalculate",
"status": "failed",
"error": {
"code": "WORKER_TIMEOUT",
"message": "Worker did not respond within the timeout window",
"retry_count": 2
}
}
}List Jobs
GET /api/ai-jobsQuery Parameters:
| Parameter | Type | Description |
|---|---|---|
| type | string | Filter by job type |
| status | string | Filter by status |
| start_date | string | Jobs created on or after |
| end_date | string | Jobs created on or before |
| limit | integer | Results per page |
Cancel Job
DELETE /api/ai-jobs/:jobIdCancels a queued job. Jobs that are already running cannot be cancelled.
Response: HTTP 204 No Content.
Batch Dispatch
POST /api/ai-jobs/batchDispatch multiple jobs at once. Maximum 20 jobs per batch.
Request Body:
{
"jobs": [
{
"type": "competitor_scan",
"params": {"skus": ["SKU-001"], "marketplace": "amazon_us"}
},
{
"type": "pricing_recalculate",
"params": {"skus": ["SKU-001"], "marketplace": "amazon_us", "apply": true}
}
],
"sequential": true
}Set "sequential": true to run jobs in order (job 2 starts after job 1 completes). Set to false (default) to run in parallel.
Response:
{
"data": {
"batch_id": "batch_01HX...",
"jobs": [
{"id": "job_01HX...", "type": "competitor_scan", "status": "queued"},
{"id": "job_01HY...", "type": "pricing_recalculate", "status": "queued"}
]
}
}Polling Pattern
Recommended polling pattern for job completion:
async function waitForJob(jobId, intervalMs = 2000, timeoutMs = 300000) {
const startTime = Date.now()
while (Date.now() - startTime < timeoutMs) {
const response = await fetch(`/api/ai-jobs/${jobId}`, {
headers: {
'Authorization': `Bearer ${apiKey}`,
'X-Tenant-ID': tenantId
}
})
const { data } = await response.json()
if (data.status === 'completed') return data.result
if (data.status === 'failed') throw new Error(data.error.message)
await new Promise(resolve => setTimeout(resolve, intervalMs))
}
throw new Error('Job polling timeout')
}Error Codes
| Code | HTTP Status | Description |
|---|---|---|
JOB_NOT_FOUND | 404 | Job ID does not exist |
INVALID_JOB_TYPE | 422 | Unknown job type |
QUEUE_FULL | 429 | Job queue is at capacity; retry later |
INSUFFICIENT_SCOPE | 403 | API key lacks ai-jobs:write scope |
JOB_NOT_CANCELLABLE | 409 | Job is running and cannot be cancelled |