# Hire a candidate

Hire a candidate at the given step. Scope: pipeline:write.

Hires the candidate at the given step, marking the candidate role **Hired**. **Scope:** `pipeline:write`. The `{id}` is a **CandidateRoleStep** id. Requires authority to manage the candidate's steps (HR rep, moderator, owner, or admin).

<Notice type="info" title="No email; full hire flow still runs">
A v1 hire sends **no email**. The rest of the hire flow still runs: role-status / capacity checks and the configured HRIS integration trigger (e.g. SAP SuccessFactors / M-Files). If the role's positions are already filled, or a required external position id is missing, the call returns `400`.
</Notice>

## Path parameters

| Parameter | Type | Description |
| --- | --- | --- |
| `id` | string | The CandidateRoleStep id. |

## Request body (optional)

| Field | Type | Description |
| --- | --- | --- |
| `notes` / `outcomeNotes` | string | Hire note. |
| `hiredDate` | string (ISO 8601) | Hire date. Defaults to now. |
| `offerAcceptedDate` | string (ISO 8601) | When the offer was accepted. |
| `externalPositionId` | string | HRIS position/seat code (may be required per-org). |

## Example request

```bash
curl -X POST https://app.talent-ray.com/api/v1/candidate-steps/crs_9/hire \
  -H "Authorization: Bearer tr_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "externalPositionId": "POS-4471", "hiredDate": "2026-06-15T00:00:00Z" }'
```

## Response

`200 OK`

```json
{
  "success": true,
  "step": { "id": "crs_9", "roleId": "role_eng_be", "roleStepId": "step_offer", "name": "Offer", "order": 5, "stepType": "offer", "status": "validated", "validatedAt": "2026-06-15T09:00:00Z" }
}
```

## Status codes

| Status | Meaning |
| --- | --- |
| `200` | Hired; `step` is the validated final step. |
| `400` | `bad_request` — capacity filled, missing required external position id, or invalid date. |
| `401` | No valid API key. |
| `403` | `insufficient_scope` (missing `pipeline:write`) or `forbidden` (cannot manage this candidate's steps). |
| `404` | Step not found, or not visible to the key. |
| `409` | `conflict` — the candidate is already hired or rejected for this role. |
| `429` | Rate limit exceeded. |