> ## 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.

# Get Job

> Retrieve a single public job by ID.

Fetches one public marketplace job by ID. Same job object shape as [search](/docs/developers/api-reference/jobs/search). Tokenless, CORS-enabled, edge-cached.

A job that exists but is no longer publicly listed (closed, archived, or otherwise unlisted) returns `404` with a minimal `{id, status: "closed"}` body — distinct from the standard error envelope you get for a nonexistent ID.

**Requirements:** none — no token, no scope, no feature flag. Rate limited to 120 requests/minute per IP.

## Request

<ParamField path="id" type="string" required>
  Job ID (from search, the changes feed, or your own job list). Empty or longer than 64 characters → `400`.
</ParamField>

## Response

A single job object — see the [search page](/docs/developers/api-reference/jobs/search) for every field: `id`, `slug`, `title`, `companyName`, `descriptionText`, `descriptionHtml`, `seoTitle`, `summary`, `status`, `datePosted`, `validThrough`, `updatedAt`, `employmentTypes`, `countries`, `languages`, `category`, `dataType`, `labelTypes`, `labelingSoftware`, `experienceLevel`, `skills`, `pay`, `url`, `applyUrl`.

## Errors

| Status | `code`         | Meaning                                                                         |
| ------ | -------------- | ------------------------------------------------------------------------------- |
| `400`  | `BAD_REQUEST`  | Invalid ID (empty or over 64 characters)                                        |
| `404`  | `NOT_FOUND`    | No such job (standard error envelope)                                           |
| `404`  | —              | Job exists but is closed/unlisted — body is `{"id": "...", "status": "closed"}` |
| `429`  | `RATE_LIMITED` | Over 120 requests/minute from one IP                                            |

<RequestExample>
  ```bash curl theme={null}
  curl -sS https://app.opentrain.ai/api/public/v1/jobs/<JOB_ID>
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "id": "<JOB_ID>",
    "slug": "spanish-audio-annotation",
    "title": "Spanish Audio Annotation",
    "companyName": "Acme AI",
    "descriptionText": "Transcribe and annotate Spanish call-center audio...",
    "descriptionHtml": "<p>Transcribe and annotate Spanish call-center audio...</p>",
    "seoTitle": null,
    "summary": null,
    "status": "OPEN",
    "datePosted": "2026-06-01T12:00:00.000Z",
    "validThrough": "2026-07-27T12:00:00.000Z",
    "updatedAt": "2026-06-10T09:30:00.000Z",
    "employmentTypes": ["CONTRACTOR"],
    "countries": [],
    "languages": ["Spanish"],
    "category": "Audio Annotation",
    "dataType": "Audio",
    "labelTypes": ["Transcription"],
    "labelingSoftware": null,
    "experienceLevel": "Intermediate",
    "skills": ["Transcription"],
    "pay": {
      "paymentType": "PAY_PER_HOUR",
      "currency": "USD",
      "hourlyRate": 12,
      "hourlyMin": null,
      "hourlyMax": null,
      "fixedPrice": null,
      "perLabelRate": null
    },
    "url": "https://app.opentrain.ai/jobs/spanish-audio-annotation-<JOB_ID>",
    "applyUrl": "https://app.opentrain.ai/api/out?job=<JOB_ID>&src=www_seo"
  }
  ```

  ```json 404 (closed job) theme={null}
  {
    "id": "<JOB_ID>",
    "status": "closed"
  }
  ```
</ResponseExample>
