# DL Verify

`POST https://api.agilitycredit.net/v3/dlv`

Docs page: https://apidocs.agilitycredit.com/api/run-dlv · Tag: DL Verify

This endpoint allows for the validation of a driver's license, ID card, or military ID using Agility's  verification service. It accepts an image or scanned data of the license ID and returns validation results, including authenticity checks and extracted information.

A selfie can be included in the verification to match the applicant's face against the license photo and check liveness, in one of two ways:

- **Upload the selfie**: send it as a base64 encoded image with type `selfie`, together with the license images or in a later request of the same session.
- **Selfie URL**: send `return_selfie_url: true` with the license images. The response contains a `selfie_url` for the applicant to take their selfie. Once they have, send `end_session: true` with the same `session_id` to get the results. If the selfie is still being processed, the response is a `409` with a `Retry-After` header; retry the same request after that many seconds.

When the DL Verify Document Liveness add-on is enabled, every verification also checks that the front image is a live capture of a physical document, not a photo of a screen, a printed copy, or a document with an altered portrait. The result is returned under `details.document_liveness`. A failed check adds `document_liveness` to `failed_checks` and the decision becomes `refer`.

**Field comparison.** The fields read from the front of the license are compared with the barcode. They fall into two groups, each reported under `details.ocr_match`:

- **Primary fields** (`primary`): `issuer_name`, `document_number`, `name`, `address`, `dob`, `issue_date`, `expiration_date`. A field that doesn't match is listed in `mismatch_fields`, and one that can't be compared because it wasn't found is listed in `missing_fields`. Both count toward `failed_count`.
- **Secondary fields** (`secondary`): every other field, such as height, weight, eye color, sex and class. Only fields that were compared and didn't match count toward `failed_count`. Fields that can't be compared are listed in `missing_fields` and never count.

A group fails once its `failed_count` reaches its `fail_at`, and then `ocr_match` fails and the decision becomes `refer`. Agility Credit sets these limits per account and can change them on request.

**Expiry.** The license's expiry is read from the barcode and reported under `details.expiry`. An expired license, or one whose expiry the barcode doesn't establish, fails `expiry` and the decision becomes `refer`. A license that never expires passes. Agility Credit can set an account to not fail expired licenses; `expiry` is then listed in `warnings` instead of `failed_checks`.

**Best practices**

- On `refer`, `failed_checks` lists the checks that caused it. Each one is a key in `details`.
- `warnings` lists checks that didn't change the decision but have findings worth a look. For example, an `accept` with field mismatches below the limits has `ocr_match` in `warnings`, with the fields in `details.ocr_match.primary` and `details.ocr_match.secondary`.
- With the Document Liveness add-on, send the front with a margin of background around all four edges, about 5% of the card's size on each side. A front cropped tight to the card edge can fail `document_liveness`.
- Secondary fields such as height, weight and eye color can change after a license is issued, so they differ more often than primary fields.
- When the barcode couldn't be read, both `barcode` and `expiry` are in `failed_checks`, and `details.expiry.processed` is `false`.
- `expiration_date` is also one of the primary fields compared between the front and the barcode. It is separate from `expiry`: a date that doesn't match or can't be compared adds to `primary.failed_count` and only fails `ocr_match` once that reaches `primary.fail_at`.
- An `error` means no reliable decision could be made. `retakes` lists the images to submit again with the same `session_id`. When the front of the license isn't recognized for the third time in a session, the verification completes with `refer` instead and no retake is requested.

Authentication: `Authorization: Bearer <api key>`.

## Parameters

| Name | In | Required | Description |
| --- | --- | --- | --- |
| `Idempotency-Key` | header | yes | A unique, idempotent key. We recommend to use a guid |
| `Agc-Tenant-Id` | header | yes | The tenant ID provided by Agility Credit. |
| `Agc-User-Id` | header | yes | The requestor user ID. |
| `Agc-Applicant-Id` | header |  | If passed, will assign the report to that applicant. If not, will create a new applicant ID |

## Request body (`application/json`), required

Inquiry request payload

Schema: `DLVerify`

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `session_id` | string |  | The session ID returned from the DL Verify Endpoint. Pass it back to continue uploading images. |
| `end_session` | boolean |  | Set to true when its your last image upload. |
| `selfie` | boolean |  | Set to true in the first request of a session to include a selfie (facial match and liveness check) in the verification, when the selfie image is uploaded in a later request. Implied when a `selfie` image or `return_selfie_url` is sent. Re… |
| `return_selfie_url` | boolean |  | Set to true to receive a `selfie_url` the applicant can open to take their selfie. Cannot be combined with `end_session` or a `selfie` image in the same request. Once the applicant has taken the selfie, send `end_session` with the same `se… |
| `images` | array of object |  |  |
| `images[].data` | string | yes | Base64 encoded image of the driver's license or selfie. For `barcode`, the base64 encoded barcode data. |
| `images[].type` | any: `front`, `back`, `barcode`, `selfie` | yes |  |

## Responses

| Status | Description | Body |
| --- | --- | --- |
| 200 | Inquiry processed successfully | one of: DLResponse, DLResponseWithError |
| 400 | Bad Request | BadRequestResponse |
| 401 | Unauthorized | UnauthorizedResponse |
| 403 | Product Not Enabled | object |
| 404 | Session Not Found. The `session_id` does not exist or has expired; start a new session and submit all images again. | DLResponse |
| 409 | Selfie Processing. The selfie taken on the `selfie_url` is still being processed. Retry the same request with the same `session_id` after the number of seconds in the `Retry-After` header. | DLResponse |
| 429 | Too Many Requests | TooManyRequestsResponse |
| 500 | Internal Server Error | AgilityServerErrorResponse |
| 502 | Verification Error. The verification could not be processed; `errors` describes what failed. Retry with the same `session_id`. | DLResponse |
The 200 body is one of: `DLResponse`, `DLResponseWithError`.

### Error bodies

400:

```json
{
  "status": "Bad Request - Invalid Parameters",
  "error": "Failed schema validation. Error: data.pull_type must be one of ['prequal', 'hard'], Path: ['data', 'pull_type'], Data: prequalification"
}
```

401:

```json
{
  "message": "Unauthorized"
}
```

429:

```json
{
  "error": "Too Many Requests"
}
```

500:

```json
{
  "message": "Agility Server Error"
}
```
