# Upload CVs for screening

Upload CV files to screen against a role, creating a batch. Scope: cv-screening:write.

Uploads one or more CV files to be screened against a role, creating a **screening batch**. **Scope:** `cv-screening:write`. The upload runs security scanning, de-duplication, multi-CV-PDF splitting, potential-candidate creation, async parsing, and usage metering.

This endpoint accepts **`multipart/form-data`** (not JSON).

## Form fields

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `roleId` | string | Yes | The role to screen the CVs against. |
| `files` | file[] | Yes | One or more CV files (PDF / DOCX / …). Repeat the `files` field per file. |
| `employerConsentAttested` | string | No | `"true"` to attest the employer holds the candidates' processing consent (KVKK/GDPR). |

## Example request

```bash
curl -X POST https://app.talent-ray.com/api/v1/cv-screening/batches \
  -H "Authorization: Bearer tr_YOUR_KEY" \
  -F "roleId=role_eng_be" \
  -F "files=@/path/to/cv1.pdf" \
  -F "files=@/path/to/cv2.pdf"
```

## Response

`201 Created`

```json
{ "batchId": "batch_2026_06_05", "received": 12, "processed": 11, "duplicates": 1 }
```

Then poll [Get a CV-screening batch](/docs/api/pipeline/cv-screening-batch/) with the returned `batchId` to track processing and read the screened results.

## Status codes

| Status | Meaning |
| --- | --- |
| `201` | Batch created; files queued for screening. |
| `400` | `bad_request` — missing `roleId` or no files. |
| `401` | No valid API key. |
| `403` | `insufficient_scope` (missing `cv-screening:write`) or `forbidden`. |
| `404` | Role not found. |
| `429` | Rate / usage limit exceeded. |