# Errors

Error responses use this structure:

```json
{
  "code": 422,
  "status": "failed",
  "message": "empty selfie"
}
```

## HTTP status codes

| HTTP status | Meaning | Common messages |
| --- | --- | --- |
| `400` | Request processing or service-usage update timed out. | `access timeout` |
| `401` | Credentials, content type, token, or signature could not be authenticated. | `invalid authorization`, `invalid merchant key`, `authentication failed`, `invalid content type`, `invalid signature` |
| `403` | The integration cannot use the service or has insufficient balance. | `forbidden`, `insufficient balance` |
| `422` | The JSON body or one of its fields is invalid. | See validation messages below. |
| `500` | Biometric scoring could not be completed. | `something went wrong` |
| `503` | The service is under maintenance. | `service is currently under maintenance` |

## Validation messages

| Field | Messages |
| --- | --- |
| Request body | `invalid payload` |
| `transaction_id` | `empty transaction_id`; `transaction_id length must be between 1 and 255 characters`; `invalid transaction_id` |
| `nik` | `empty nik`; `nik length must be exactly 16 digits`; `invalid nik` |
| `selfie` | `empty selfie`; `invalid selfie`; `invalid base64 selfie`; `invalid size selfie`; `invalid image type selfie` |
| `channel` | `empty channel`; `channel length must be between 1 and 100`; `invalid channel` |

Correct validation errors before retrying. For server errors, keep both
`client_transaction_id` and Privy's `transaction_id` when available and contact
Privy support if the problem persists.
