> For the complete documentation index, see [llms.txt](https://docs.adaptria.locaria.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.adaptria.locaria.com/internal-api/reference/project-jobs.md).

# 🛠 Project Jobs

### Project Jobs

A project is broken into one or more **jobs** — discrete pieces of work assigned to talent (translation, editing, QA, video adaptation, etc.).

#### What this surface gives you

* List the jobs under a project with filters and pagination — useful for tracking pipeline status from an external dashboard.
* Get the full details of a single job, including delivery artefacts (file URLs, notes, timestamps) and the assigned talent (hydrated, not stale denormalised JSON).

#### Job Lifecycle

```
draft → requested → accepted_pending → assigned → in_progress → delivered → approved
                                                                                   ↘
                                                                                    rejected → in_progress
                                                                                   ↘
                                                                                    invoiced
```

A job can also be `cancelled` from any state.

#### Notes

* Endpoints are scoped to companies the API key owner can access. Calling for a project outside that scope returns 403.
* Job IDs are stable; surfaces and tools (Make.com, Zapier, n8n, the Adaptria MCP) can use them as automation keys.

## List jobs for a project

> Returns the project jobs under a given project that the API key owner has access to. Each job includes service, language/market context, assigned talent (hydrated), and timing/cost summary.

````json
{"openapi":"3.1.0","info":{"title":"Adaptria Public API: Connector","version":"1.0.0"},"tags":[{"name":"🛠 Project Jobs","description":"## Project Jobs\n\nA project is broken into one or more **jobs** — discrete pieces of work assigned to talent (translation, editing, QA, video adaptation, etc.).\n\n### What this surface gives you\n\n- List the jobs under a project with filters and pagination — useful for tracking pipeline status from an external dashboard.\n- Get the full details of a single job, including delivery artefacts (file URLs, notes, timestamps) and the assigned talent (hydrated, not stale denormalised JSON).\n\n### Job Lifecycle\n\n```\ndraft → requested → accepted_pending → assigned → in_progress → delivered → approved\n                                                                                   ↘\n                                                                                    rejected → in_progress\n                                                                                   ↘\n                                                                                    invoiced\n```\n\nA job can also be `cancelled` from any state.\n\n### Notes\n\n- Endpoints are scoped to companies the API key owner can access. Calling for a project outside that scope returns 403.\n- Job IDs are stable; surfaces and tools (Make.com, Zapier, n8n, the Adaptria MCP) can use them as automation keys.\n"}],"servers":[{"url":"https://api.adaptria.locaria.com","description":"Production Environment"}],"security":[{"apiKeyAuth":[]}],"components":{"securitySchemes":{"apiKeyAuth":{"type":"apiKey","in":"header","name":"Api-key","description":"## API Key Authentication\n\nStatic API key obtained from the Adaptria Portal or via `POST /api/credentials/api-keys`.\n\n**How to authenticate**:\n1. Generate an API key from the Adaptria Portal (Settings → API Keys) or ask your admin\n2. Include the key in all requests using the `Api-key` header\n\n**Key format**: `lla_live_<32-character-string>`\n\n**No token exchange needed** — the key is used directly in every request. Revoke or rotate keys from the portal."}},"schemas":{"ListProjectJobsResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"array","items":{"$ref":"#/components/schemas/ProjectJobListItem"}},"pagination":{"$ref":"#/components/schemas/Pagination"}},"required":["success","data","pagination"]},"ProjectJobListItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Universally Unique Identifier (UUID v4)"},"jobNumber":{"type":["string","null"]},"jobName":{"type":["string","null"]},"status":{"type":"string","enum":["draft","requested","accepted_pending","assigned","in_progress","delivered","approved","rejected","invoiced","cancelled"],"description":"Project Job lifecycle status:\n\n| Status | Description |\n|--------|-------------|\n| `draft` | Job created but not yet requested |\n| `requested` | Availability requested from talent |\n| `accepted_pending` | Talent accepted; awaiting admin assignment |\n| `assigned` | Talent assigned, work not yet started |\n| `in_progress` | Talent has started the work |\n| `delivered` | Talent has submitted deliverables |\n| `approved` | Delivery approved by client |\n| `rejected` | Delivery rejected — back to talent |\n| `invoiced` | Job has been billed |\n| `cancelled` | Job cancelled |\n"},"projectId":{"type":"string","format":"uuid","description":"Universally Unique Identifier (UUID v4)"},"service":{"$ref":"#/components/schemas/NamedRef"},"sourceLanguage":{"$ref":"#/components/schemas/NamedRef"},"targetLanguage":{"$ref":"#/components/schemas/NamedRef"},"targetMarket":{"$ref":"#/components/schemas/NamedRef"},"assignedTalent":{"$ref":"#/components/schemas/JobTalentSummary"},"dueDate":{"type":["string","null"],"format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Date in ISO 8601 format (YYYY-MM-DD)"},"plannedHours":{"type":["number","null"]},"loggedHours":{"type":["number","null"]},"totalCost":{"$ref":"#/components/schemas/Money"},"createdAt":{"type":"string","format":"date-time","description":"Date and time in ISO 8601 format"},"updatedAt":{"type":["string","null"],"format":"date-time","description":"Date and time in ISO 8601 format"}},"required":["id","status","projectId","createdAt"]},"NamedRef":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid","description":"Universally Unique Identifier (UUID v4)"},"name":{"type":"string"}},"required":["id","name"]},"JobTalentSummary":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid","description":"Universally Unique Identifier (UUID v4)"},"firstName":{"type":["string","null"]},"lastName":{"type":["string","null"]},"name":{"type":"string","description":"Full name or email fallback"},"email":{"type":["string","null"],"format":"email"}},"required":["id","name"]},"Money":{"type":["object","null"],"properties":{"amount":{"type":"number"},"currency":{"type":"string","minLength":3,"maxLength":3}},"required":["amount","currency"]},"Pagination":{"type":"object","properties":{"page":{"type":"integer","exclusiveMinimum":0,"description":"Current page number (1-indexed)"},"limit":{"type":"integer","exclusiveMinimum":0,"maximum":100,"description":"Number of items per page (max 100)"},"total":{"type":"integer","minimum":0,"description":"Total number of items across all pages"},"totalPages":{"type":"integer","minimum":0,"description":"Total number of pages"},"hasNextPage":{"type":"boolean","description":"Whether there are more pages after the current page"},"hasPrevPage":{"type":"boolean","description":"Whether there are pages before the current page"}},"required":["page","limit","total","totalPages","hasNextPage","hasPrevPage"]}}},"paths":{"/api/public/v1/projects/{projectId}/jobs":{"get":{"summary":"List jobs for a project","description":"Returns the project jobs under a given project that the API key owner has access to. Each job includes service, language/market context, assigned talent (hydrated), and timing/cost summary.","tags":["🛠 Project Jobs"],"parameters":[{"schema":{"type":"string","format":"uuid","description":"Project UUID"},"required":true,"description":"Project UUID","name":"projectId","in":"path"},{"schema":{"type":"string","pattern":"^\\d+$","default":"1","description":"Page number (starts at 1)"},"required":false,"description":"Page number (starts at 1)","name":"page","in":"query"},{"schema":{"type":"string","pattern":"^\\d+$","default":"20","description":"Items per page (max 100)"},"required":false,"description":"Items per page (max 100)","name":"limit","in":"query"},{"schema":{"type":"string","description":"Filter by job status. Available values: draft, requested, accepted_pending, assigned, in_progress, delivered, approved, rejected, invoiced, cancelled"},"required":false,"description":"Filter by job status. Available values: draft, requested, accepted_pending, assigned, in_progress, delivered, approved, rejected, invoiced, cancelled","name":"status","in":"query"},{"schema":{"type":"string","description":"Search by job number or job name"},"required":false,"description":"Search by job number or job name","name":"search","in":"query"}],"responses":{"200":{"description":"Jobs listed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListProjectJobsResponse"}}}},"401":{"description":"Authentication required"},"403":{"description":"Access denied to this project"},"404":{"description":"Project not found"}}}}}}
````

## Get project job details

> Get the full details of a specific job inside a project. Includes delivery artefacts, hydrated talent, and lifecycle timestamps.

````json
{"openapi":"3.1.0","info":{"title":"Adaptria Public API: Connector","version":"1.0.0"},"tags":[{"name":"🛠 Project Jobs","description":"## Project Jobs\n\nA project is broken into one or more **jobs** — discrete pieces of work assigned to talent (translation, editing, QA, video adaptation, etc.).\n\n### What this surface gives you\n\n- List the jobs under a project with filters and pagination — useful for tracking pipeline status from an external dashboard.\n- Get the full details of a single job, including delivery artefacts (file URLs, notes, timestamps) and the assigned talent (hydrated, not stale denormalised JSON).\n\n### Job Lifecycle\n\n```\ndraft → requested → accepted_pending → assigned → in_progress → delivered → approved\n                                                                                   ↘\n                                                                                    rejected → in_progress\n                                                                                   ↘\n                                                                                    invoiced\n```\n\nA job can also be `cancelled` from any state.\n\n### Notes\n\n- Endpoints are scoped to companies the API key owner can access. Calling for a project outside that scope returns 403.\n- Job IDs are stable; surfaces and tools (Make.com, Zapier, n8n, the Adaptria MCP) can use them as automation keys.\n"}],"servers":[{"url":"https://api.adaptria.locaria.com","description":"Production Environment"}],"security":[{"apiKeyAuth":[]}],"components":{"securitySchemes":{"apiKeyAuth":{"type":"apiKey","in":"header","name":"Api-key","description":"## API Key Authentication\n\nStatic API key obtained from the Adaptria Portal or via `POST /api/credentials/api-keys`.\n\n**How to authenticate**:\n1. Generate an API key from the Adaptria Portal (Settings → API Keys) or ask your admin\n2. Include the key in all requests using the `Api-key` header\n\n**Key format**: `lla_live_<32-character-string>`\n\n**No token exchange needed** — the key is used directly in every request. Revoke or rotate keys from the portal."}},"schemas":{"GetProjectJobDetailsResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/ProjectJobDetails"}},"required":["success","data"]},"ProjectJobDetails":{"allOf":[{"$ref":"#/components/schemas/ProjectJobListItem"},{"type":"object","properties":{"notes":{"type":["string","null"]},"startDate":{"type":["string","null"],"format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Date in ISO 8601 format (YYYY-MM-DD)"},"approvedAt":{"type":["string","null"],"format":"date-time","description":"Date and time in ISO 8601 format"},"rejectedAt":{"type":["string","null"],"format":"date-time","description":"Date and time in ISO 8601 format"},"deliveredAt":{"type":["string","null"],"format":"date-time","description":"Date and time in ISO 8601 format"},"rejectionReason":{"type":["string","null"]},"deliverables":{"type":"array","items":{"$ref":"#/components/schemas/ProjectJobDeliverable"}}}}]},"ProjectJobListItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Universally Unique Identifier (UUID v4)"},"jobNumber":{"type":["string","null"]},"jobName":{"type":["string","null"]},"status":{"type":"string","enum":["draft","requested","accepted_pending","assigned","in_progress","delivered","approved","rejected","invoiced","cancelled"],"description":"Project Job lifecycle status:\n\n| Status | Description |\n|--------|-------------|\n| `draft` | Job created but not yet requested |\n| `requested` | Availability requested from talent |\n| `accepted_pending` | Talent accepted; awaiting admin assignment |\n| `assigned` | Talent assigned, work not yet started |\n| `in_progress` | Talent has started the work |\n| `delivered` | Talent has submitted deliverables |\n| `approved` | Delivery approved by client |\n| `rejected` | Delivery rejected — back to talent |\n| `invoiced` | Job has been billed |\n| `cancelled` | Job cancelled |\n"},"projectId":{"type":"string","format":"uuid","description":"Universally Unique Identifier (UUID v4)"},"service":{"$ref":"#/components/schemas/NamedRef"},"sourceLanguage":{"$ref":"#/components/schemas/NamedRef"},"targetLanguage":{"$ref":"#/components/schemas/NamedRef"},"targetMarket":{"$ref":"#/components/schemas/NamedRef"},"assignedTalent":{"$ref":"#/components/schemas/JobTalentSummary"},"dueDate":{"type":["string","null"],"format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Date in ISO 8601 format (YYYY-MM-DD)"},"plannedHours":{"type":["number","null"]},"loggedHours":{"type":["number","null"]},"totalCost":{"$ref":"#/components/schemas/Money"},"createdAt":{"type":"string","format":"date-time","description":"Date and time in ISO 8601 format"},"updatedAt":{"type":["string","null"],"format":"date-time","description":"Date and time in ISO 8601 format"}},"required":["id","status","projectId","createdAt"]},"NamedRef":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid","description":"Universally Unique Identifier (UUID v4)"},"name":{"type":"string"}},"required":["id","name"]},"JobTalentSummary":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid","description":"Universally Unique Identifier (UUID v4)"},"firstName":{"type":["string","null"]},"lastName":{"type":["string","null"]},"name":{"type":"string","description":"Full name or email fallback"},"email":{"type":["string","null"],"format":"email"}},"required":["id","name"]},"Money":{"type":["object","null"],"properties":{"amount":{"type":"number"},"currency":{"type":"string","minLength":3,"maxLength":3}},"required":["amount","currency"]},"ProjectJobDeliverable":{"type":"object","properties":{"fileId":{"type":["string","null"],"format":"uuid","description":"Universally Unique Identifier (UUID v4)"},"fileName":{"type":"string"},"downloadUrl":{"type":["string","null"],"format":"uri"},"uploadedAt":{"type":["string","null"],"format":"date-time","description":"Date and time in ISO 8601 format"}},"required":["fileName"]}}},"paths":{"/api/public/v1/projects/{projectId}/jobs/{jobId}":{"get":{"summary":"Get project job details","description":"Get the full details of a specific job inside a project. Includes delivery artefacts, hydrated talent, and lifecycle timestamps.","tags":["🛠 Project Jobs"],"parameters":[{"schema":{"type":"string","format":"uuid","description":"Project UUID"},"required":true,"description":"Project UUID","name":"projectId","in":"path"},{"schema":{"type":"string","format":"uuid","description":"Job UUID"},"required":true,"description":"Job UUID","name":"jobId","in":"path"}],"responses":{"200":{"description":"Job details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetProjectJobDetailsResponse"}}}},"401":{"description":"Authentication required"},"403":{"description":"Access denied to this job"},"404":{"description":"Job or project not found"}}}}}}
````

## 🔁 Update Job Status

> Change a job to a target status, or run a delivery action (\`delivery\_approved\` to approve a delivery, \`rejected\` to reject one — \`reason\` required). Internal staff only — client API keys receive \`403\`. Returns 404 if the job does not exist or does not belong to the given project, 409 if the requested transition is not allowed for the job's current state.

````json
{"openapi":"3.1.0","info":{"title":"Adaptria Public API: Connector","version":"1.0.0"},"tags":[{"name":"🛠 Project Jobs","description":"## Project Jobs\n\nA project is broken into one or more **jobs** — discrete pieces of work assigned to talent (translation, editing, QA, video adaptation, etc.).\n\n### What this surface gives you\n\n- List the jobs under a project with filters and pagination — useful for tracking pipeline status from an external dashboard.\n- Get the full details of a single job, including delivery artefacts (file URLs, notes, timestamps) and the assigned talent (hydrated, not stale denormalised JSON).\n\n### Job Lifecycle\n\n```\ndraft → requested → accepted_pending → assigned → in_progress → delivered → approved\n                                                                                   ↘\n                                                                                    rejected → in_progress\n                                                                                   ↘\n                                                                                    invoiced\n```\n\nA job can also be `cancelled` from any state.\n\n### Notes\n\n- Endpoints are scoped to companies the API key owner can access. Calling for a project outside that scope returns 403.\n- Job IDs are stable; surfaces and tools (Make.com, Zapier, n8n, the Adaptria MCP) can use them as automation keys.\n"}],"servers":[{"url":"https://api.adaptria.locaria.com","description":"Production Environment"}],"security":[{"apiKeyAuth":[]},{"bearerAuth":[]}],"components":{"securitySchemes":{"apiKeyAuth":{"type":"apiKey","in":"header","name":"Api-key","description":"## API Key Authentication\n\nStatic API key obtained from the Adaptria Portal or via `POST /api/credentials/api-keys`.\n\n**How to authenticate**:\n1. Generate an API key from the Adaptria Portal (Settings → API Keys) or ask your admin\n2. Include the key in all requests using the `Api-key` header\n\n**Key format**: `lla_live_<32-character-string>`\n\n**No token exchange needed** — the key is used directly in every request. Revoke or rotate keys from the portal."},"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"## Auth0 Bearer Token\n\nFor first-party clients that already authenticate against Auth0, send the JWT in\nthe `Authorisation` header as `Bearer <token>`."}},"schemas":{"UpdateJobStatusBody":{"type":"object","properties":{"status":{"type":"string","enum":["in_progress","delivered","delivery_approved","approved","rejected","cancelled"],"description":"Target job status, or a delivery action. Supported values:\n- `in_progress` — start an `assigned` job.\n- `delivered` — submit the delivery for an `in_progress` job.\n- `delivery_approved` — approve a `delivered` job's delivery. The job stays `delivered` (its `isApproved` flag flips); status does not change.\n- `approved` — approve a `delivered` job for invoicing. Not allowed for internal-talent assignees.\n- `rejected` — reject the delivery of a `delivered` job. Requires `reason`.\n- `cancelled` — cancel the job."},"reason":{"type":"string","minLength":1,"maxLength":250,"description":"Rejection reason. Required only when `status` is `rejected`; ignored otherwise."}},"required":["status"]},"UpdateJobStatusResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"jobId":{"type":"string","format":"uuid"},"projectId":{"type":"string","format":"uuid"},"status":{"type":"string"},"updatedAt":{"type":"string","format":"date-time"}},"required":["jobId","projectId","status","updatedAt"]}},"required":["success","data"]}}},"paths":{"/api/public/v1/projects/{projectId}/jobs/{jobId}/status":{"put":{"summary":"🔁 Update Job Status","description":"Change a job to a target status, or run a delivery action (`delivery_approved` to approve a delivery, `rejected` to reject one — `reason` required). Internal staff only — client API keys receive `403`. Returns 404 if the job does not exist or does not belong to the given project, 409 if the requested transition is not allowed for the job's current state.","tags":["🛠 Project Jobs"],"parameters":[{"schema":{"type":"string","format":"uuid","description":"Project UUID"},"required":true,"description":"Project UUID","name":"projectId","in":"path"},{"schema":{"type":"string","format":"uuid","description":"Job UUID"},"required":true,"description":"Job UUID","name":"jobId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateJobStatusBody"}}}},"responses":{"200":{"description":"Job status updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateJobStatusResponse"}}}},"400":{"description":"Validation error"},"403":{"description":"Forbidden — client users cannot change job status (internal staff only)"},"404":{"description":"Job not found"},"409":{"description":"Requested transition not allowed for the job's current state"}}}}}}
````
