> ## Documentation Index
> Fetch the complete documentation index at: https://opentrain.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Update Job

> Edit a live (published) job. Edits are re-moderated.

Patches a **published, open** job — same field keys and types as [`PATCH /job-drafts/{jobId}`](/docs/developers/api-reference/job-drafts/update) (the authoritative key list is `draft.updateKeys` in [capabilities](/docs/developers/api-reference/job-drafts/capabilities)). For unpublished drafts use the draft endpoint instead; this one requires the job to be `OPEN`.

Every edit to a live job is **re-moderated**. If moderation rejects the edited content, the update is still applied but the job is **unpublished back to `DRAFT`** — fix the flagged content and [publish](/docs/developers/api-reference/jobs/publish) again.

**Requirements:** `jobs:write` scope + the `public_api_job_publishing` feature. The job must be yours and `OPEN`.

## Request

<ParamField path="id" type="string" required>
  The published job's ID.
</ParamField>

Body: a JSON object with one or more job fields — identical schema to the [draft update endpoint](/docs/developers/api-reference/job-drafts/update). Unknown keys → `400` with zod issue details.

## Response

<ResponseField name="ok" type="boolean">
  `true` on success.
</ResponseField>

<ResponseField name="jobId" type="string">
  The job ID.
</ResponseField>

<ResponseField name="status" type="string">
  `OPEN` — the job stayed live.
</ResponseField>

<ResponseField name="moderation" type="object">
  `{decision: "ALLOW", reasons: []}` when the edit passed moderation.
</ResponseField>

## Errors

| Status | `code`         | Meaning                                                                                                                                                                             |
| ------ | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `400`  | `BAD_REQUEST`  | Empty body, invalid JSON, unknown keys, or wrong types (`details` carries zod issues)                                                                                               |
| `401`  | `UNAUTHORIZED` | Missing or invalid token                                                                                                                                                            |
| `403`  | `FORBIDDEN`    | Missing `jobs:write` scope or feature disabled                                                                                                                                      |
| `404`  | `NOT_FOUND`    | No such job, or not yours                                                                                                                                                           |
| `409`  | `CONFLICT`     | Job is not `OPEN` — `details: {jobId, status, requiredStatus: "OPEN"}`; for `DRAFT` jobs the message points you to `PATCH /job-drafts/{jobId}`                                      |
| `409`  | `CONFLICT`     | Moderation rejected the edit — **the update was applied but the job was unpublished to `DRAFT`**; `details: {jobId, reason: "moderation_blocked", reasons: [...], status: "DRAFT"}` |

<RequestExample>
  ```bash curl theme={null}
  curl -sS -X PATCH https://app.opentrain.ai/api/public/v1/jobs/<JOB_ID> \
    -H "Authorization: Bearer $OT_API_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
      "headcount": 8,
      "pricePerHour": 14
    }'
  ```

  ```bash CLI theme={null}
  opentrain jobs update-published --job-id <JOB_ID> \
    --set headcount=8 \
    --set pricePerHour=14 --json
  ```

  ```json MCP: opentrain_update_published_job theme={null}
  {
    "jobId": "<JOB_ID>",
    "patch": {
      "headcount": 8,
      "pricePerHour": 14
    }
  }
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "ok": true,
    "jobId": "<JOB_ID>",
    "status": "OPEN",
    "moderation": {
      "decision": "ALLOW",
      "reasons": []
    }
  }
  ```

  ```json 409 (moderation blocked) theme={null}
  {
    "error": "Job update applied but failed moderation; job unpublished",
    "code": "CONFLICT",
    "requestId": "<REQUEST_ID>",
    "details": {
      "jobId": "<JOB_ID>",
      "reason": "moderation_blocked",
      "reasons": ["contact_information_in_description"],
      "status": "DRAFT"
    }
  }
  ```
</ResponseExample>
