---
title: "One open role's detail"
method: GET
path: "/v1/jobs/role"
---

# One open role's detail

`GET /v1/jobs/role`

## Request

- Base URL: `https://api.reqbeat.com`
- URL: `https://api.reqbeat.com/v1/jobs/role`
- Auth: one of:
  - API key in header `X-API-Key`
  - HTTP bearer

One open role, addressed by the `(company_id, req_key)` pair every
`/v1/jobs/search` row carries -- the follow-up call for a role you already
hold an identifier for, instead of re-pulling the whole company through
`/v1/companies/{company_id}/open-reqs`.

Scoped exactly as `/v1/jobs/search` is: LinkedIn-excluded (ATS tenants plus public job boards and aggregators) and freshness-floored, one
row per logical req. The body adds `raw_title` (the posting's own title) and
`boards` -- the full, deduped list of boards reporting this req, which a
search page cannot afford per row.

A req that does not exist, is closed, or has not reached the freshness floor
is a 404, never an empty 200 -- and a 404 is not metered.

Requires the `read` scope.

## Query parameters

- `company_id` integer, required: The plane's company id -- returned as `company_id` by /v1/reqs/search and by every company motion response.
- `req_key` string, required: The req's own identity, as returned by `/v1/jobs/search`. Only unique WITHIN a company, so it is always spent together with `company_id`. A query parameter rather than a path segment because a board-native req id is an arbitrary string that may contain '/' or ':'.

## Headers

- `Idempotency-Key` string, nullable

## Response `200`

Successful Response

- RoleResponse
  - `role` RoleOut, required: One role's detail: the `JobOut` row `/jobs/search` serves, plus the two facts a page deliberately withholds (signalsapi-4836).
    - `req_key` string, required
    - `company_id` integer, required
    - `company_name` string, nullable
    - `company_domain` string, nullable
    - `title` string, nullable, required
    - `function` string, nullable, required
    - `country` string, nullable, required
    - `first_seen` string, date-time, required: Our first observation of this req (not the employer's posting date). The `since` parameter filters on this value.
    - `source_posted_at` string, date-time, nullable: The posting date the source itself published for this req. Null when the source gave no date, or none has been recorded yet -- `first_seen` is then the only date we hold, and it is our observation time.
    - `board` string, required
    - `source_type` 'ats_tenant' | 'board', nullable: What kind of source this req was most recently read from: 'ats_tenant' (the employer's own applicant tracking system) or 'board' (a job board or aggregator). Most served reqs are 'board'; pass `source_type=ats_tenant` to keep only the ones read from the employer's own system.
    - `relevance` number, nullable
    - `raw_title` string, nullable, required
    - `boards` string[], required
    - `country_code` string, nullable, required: The posting country's ISO-3166-1 alpha-2 code, uppercase (`DE`, `US`), derived from `country` and never stored. `null` when `country` is absent or is not a country this corpus names — never a guess. Note this is an output only: the `geo`/`country` filter still takes the name, because a bare two-letter code is ambiguous on input (`CA` is Canada to ISO and California to this column).
    - `function_name` string, nullable, required: The job function's human-readable name (`Software & IT`, `Healthcare`), derived from `function` and never stored. The `?function=` filter accepts this name as well as the opaque taxonomy id in `function`. `null` when the req carries no function attribution (`unspecified`, 10.2% of served reqs), or when it was classified from its skills alone, so its id is outside the named title-family vocabulary (16.7%) — never a guess and never the raw id. Named on 73.1% of served reqs (309,251 of 422,826, measured 2026-10-07).
  - `as_of` string, date-time, required

## Other responses

- `401`: No API key was sent.
- `402`: The key is over its plan's rolling call quota, or the account is past its spend cap. `upgrade_url` and `purchase_url` are the ways out.
- `403`: The presented key is invalid or revoked, or (see `x-required-scope` on this operation) it does not carry the scope this operation requires.
- `422`: Validation Error
- `429`: Too many calls in the current 60-second window. The limit is per API key, set by the key's plan, and shared by every metered REST route and MCP tool; the shared demo key is limited per IP address instead. Wait `Retry-After` seconds and retry. The `RateLimit-*` headers are absent when `reason` is `key_throttled`.

---

[API](https://skmtc.dev/reqbeat/apis/reqbeat-api.md) · [All operations](https://skmtc.dev/reqbeat/apis/reqbeat-api/llms.txt) · [OpenAPI document](https://skmtc.dev/reqbeat/apis/reqbeat-api/revisions/4758e5957e8c?raw)
