---
title: "Download KYC documents"
description: "List a customer's KYC documents and download one side of one document as a data URI, for a compliance review."
---
You can download an identity or company document a customer gave for KYC, for example to attach a passport to a compliance review file.

**A money example.** Before approving a contractor's first 3,000.00 USD monthly payout, your compliance team re-checks the passport on file. You list the contractor's documents, download the passport's front, and save it to the review file. No money moves.

## Before you start

- A scoped key needs `customer:update` to download. Listing needs no extra permission.
- The customer has uploaded documents, [through the API or on the hosted page](/getting-started/kyc).

## 1. List the documents

Call [`GET /v1/customers/{customer_id}/kyc/documents`](/api-reference/kyc/get-v1-customers-customer-id-kyc-documents) first. For documents captured on the hosted page, this call also fetches the images. You can download such a document only after you make this call.

```bash title="List a customer's documents"
curl --request GET \
     --url https://api.gravv.xyz/v1/customers/3f6b2a1e-8c4d-4e7f-9a2b-5c1d0e9f8a71/kyc/documents \
     --header 'Api-Key: <API_KEY>'
```

```json title="Response"
{
  "data": {
    "customer_id": "3f6b2a1e-8c4d-4e7f-9a2b-5c1d0e9f8a71",
    "documents": [
      {
        "id": "a7b8c9d0-e1f2-4a3b-8c4d-5e6f7a8b9c0d",
        "IDType": "PASSPORT",
        "IDSubType": "FRONT_SIDE",
        "IDNumber": "B04512398",
        "IssuingCountry": "NGA",
        "IssuedDate": "2020-02-11",
        "ExpiryDate": "2030-02-10",
        "has_front_image": true,
        "has_back_image": false,
        "OriginalFilename": "passport.jpg"
      }
    ],
    "count": 1
  },
  "error": null
}
```

Pick the document `id` and a side that has an image (`has_front_image` or `has_back_image`).

<Warning>
`IDNumber` is the full document number, in plain text. Do not log it, and show it only to people allowed to see identity data.
</Warning>

## 2. Download one side

Call [`GET /v1/customers/{customer_id}/kyc/documents/{document_id}/download`](/api-reference/kyc/get-v1-customers-customer-id-kyc-documents-document-id-download) with `side` `front` or `back`.

```bash title="Download the passport front"
curl --request GET \
     --url 'https://api.gravv.xyz/v1/customers/3f6b2a1e-8c4d-4e7f-9a2b-5c1d0e9f8a71/kyc/documents/a7b8c9d0-e1f2-4a3b-8c4d-5e6f7a8b9c0d/download?side=front' \
     --header 'Api-Key: <API_KEY>'
```

```json title="Response, content trimmed"
{
  "data": {
    "content": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBD...",
    "content_type": "image/jpeg",
    "document_id": "a7b8c9d0-e1f2-4a3b-8c4d-5e6f7a8b9c0d",
    "filename": "passport_front-side_60287353-bc08-482b-871c-98305b9a42dd.jpg",
    "side": "front",
    "size_bytes": 57134
  },
  "error": null
}
```

- The response is JSON, not the file. `content` is a **data URI**. Strip the `data:<type>;base64,` prefix, then decode the base64 to get the file. Uploads take raw base64 without the prefix.
- `filename` is a storage name. Use `OriginalFilename` from the list for the customer's own name.
- A response can be up to about 13 MB.
- A two-sided ID is **two documents**, one `FRONT_SIDE` and one `BACK_SIDE`. To read the back image, send `side=back` with the `id` of the `BACK_SIDE` document.
- This endpoint cannot download documents uploaded through the [card KYC](/platform/cards/card-kyc/overview) flow (`/v1/risk/upload-document`) yet. Keep one upload flow per customer.

## What can go wrong

| Response | Why | Fix |
| :-- | :-- | :-- |
| 400 `side is required (front or back)` or `side must be "front" or "back"` | `side` missing or wrong | Add `?side=front` or `?side=back` |
| 400 `invalid document_id format` | Not a UUID | Use `documents[].id` from the list |
| 404 `document not found` | The id belongs to another customer, or does not exist | List again for this customer |
| 404 `no back image available for this document` | This document has no image for that side | Use the `BACK_SIDE` document, or the other side |
| 404 `no KYC document data found for customer` (on the list) | The customer has no documents yet. The API returns 404, not an empty list | Treat it as "no documents" |
| 404 `CUSTOMER_NOT_FOUND: …` | Wrong customer id or environment | Check the id and the key's environment |
| 403 `{"reason": "forbidden", "required_any": ["customer:update"]}` | The key lacks `customer:update` | Use a key with that permission |
| 500 `failed to download document image`, or 503 `storage service not configured` | A storage problem | Retry later. Contact support if it persists |

Gravv sends no webhook for document downloads.

## Testing in sandbox

Downloads work in sandbox. [Upload a small JPEG](/getting-started/kyc#upload-documents) for a test customer, list the documents, then download it. The decoded `content` is the file you uploaded.
