# CPF Validation

Validates a CPF number by checking the format and check digits using the Modulo 11 algorithm.

## Endpoint

```
POST /api/external/cpf/validate
```

## Headers

| Header | Type | Required | Description |
|--------|------|----------|-------------|
| `Authorization` | String | Yes | `ApiKey {client_id}:{client_secret}` (`Basic` format with base64 also accepted -- see [Authentication](/en/auth-token#layer-1-api-key-secret)) |
| `Content-Type` | String | Yes | `application/json` |
| `hmac` | String | Yes | HMAC-SHA512 signature of the body in lowercase hexadecimal ([learn more](/en/hmac)) |
| `X-Key-Case` | String | No | `camelCase` -- converts params/response snake_case ↔ camelCase. If sending `camelCase`, sign the body already in camelCase (see [HMAC-SHA512](/en/hmac)) |
| `Idempotency-Key` | String | No | Unique key to prevent duplicate processing (up to 256 chars). When present, the server echoes it in the `Idempotency-Key` response header and adds `X-Idempotent-Replay: true` on replay |

Required permission on the API Key: `account:read`. Without it, the request is rejected with `403 API key lacks permission: account:read` before executing the validation.

## Request Body

| Field | Type | Required | Description | Example |
|-------|------|----------|-------------|---------|
| `cpf` | String | Yes | CPF number (with or without formatting) | `"12345678909"` or `"123.456.789-09"` |

::: tip Alias
The `document_number` field is also accepted as an alias.
:::

## Example

::: warning HMAC required
This endpoint requires the `hmac` header even though it has a single body field. Requests without the header return `401 Missing HMAC header` before reaching the controller.
:::

```bash
# Body with only 1 field - already trivially "alphabetized"
BODY='{"cpf":"12345678909"}'

# Compute HMAC-SHA512 using the client_secret as the key
HMAC=$(echo -n "$BODY" | openssl dgst -sha512 -hmac "$CLIENT_SECRET" | awk '{print $2}')

curl -X POST https://api.monetarie.com/api/external/cpf/validate \
  -H "Authorization: ApiKey $CLIENT_ID:$CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -H "hmac: $HMAC" \
  -d "$BODY"
```

## Success Response -- Valid CPF (200)

```json
{
  "worked": true,
  "valid": true,
  "formatted": "123.456.789-09"
}
```

## Success Response -- Invalid CPF (200)

```json
{
  "worked": true,
  "valid": false,
  "detail": "CPF inválido"
}
```

Possible messages in `detail` when `valid: false`:

| `detail` | Cause |
|----------|-------|
| `"CPF deve ter 11 digitos"` | After removing non-digits, the number does not have exactly 11 digits |
| `"CPF invalido"` | All 11 digits are the same (e.g., `111.111.111-11`) |
| `"CPF invalido (digito verificador)"` | Check digits failed the Modulo 11 algorithm |

| Field | Type | Description |
|-------|------|-------------|
| `worked` | Boolean | `true` indicates validation was executed (not a guarantee that the CPF is valid) |
| `valid` | Boolean | `true` if the CPF is valid per Modulo 11, `false` otherwise |
| `formatted` | String | Formatted CPF (XXX.XXX.XXX-XX). Present only when `valid: true` |
| `detail` | String | Message explaining the failure. Present only when `valid: false` |

::: tip Why 200 OK with `valid: false` and not 400?
An invalid CPF **is a valid validation result** -- it is not a request error. The API processed the request successfully and is informing you that the number does not pass Modulo 11. The client should always inspect the `valid` field (not just the HTTP status) to decide the next step. The same pattern `{worked: true, ...}` appears in `GET /balance` (returns `worked: true, balance: N`) and `POST /webhooks` (returns `worked: true, id: "..."`).
:::

## Validations Performed

1. Verifies that the CPF has exactly 11 digits
2. Rejects CPFs with all identical digits (e.g., `111.111.111-11`)
3. Computes and verifies the 2 check digits using the Modulo 11 algorithm

## Error Responses

### 400 -- Missing `cpf` field

When the body does not contain the `cpf` field (nor the alias `document_number`), the API rejects the request before executing the Modulo 11 validation:

```json
{
  "errors": {
    "bad_request": {
      "cpf": ["is required"]
    }
  }
}
```

::: tip Invalid CPF returns HTTP 200, not 400
CPFs that reach the controller but fail Modulo 11 (wrong check digits, all digits the same, or fewer than 11 digits) return **HTTP 200** with `{"worked": true, "valid": false, "detail": "CPF inválido"}`. Do not confuse with the 400 above -- the 400 is exclusive to the case of the `cpf` field being missing from the body.
:::

### 401 -- Missing or Invalid HMAC (HMAC plug)

```json
{
  "worked": false,
  "detail": "Missing HMAC header"
}
```

```json
{
  "worked": false,
  "detail": "Invalid HMAC signature"
}
```

::: warning 401 has two distinct formats
The 401 returned by the HMAC validation layer (above) has a different shape from the 401 returned by the API Key layer (`{"error": {status, message}}`). See [Authentication -- Error Responses](/en/auth-token#error-responses) for the detailing of the three layers.
:::

::: tip Usage
This endpoint only performs mathematical CPF validation (Modulo 11). It does not query the Federal Revenue Service nor verify the document's registration status.
:::
