Skip to main content
Export a customer’s verified KYC data to another system, with their consent, so they don’t have to verify again elsewhere.

Prerequisites

  • Customer export enabled on your partner account. Contact your MoonPay account team.
  • A customer with an approved KYC record with MoonPay.
  • A server that can call the export endpoint with your secret key.
  • The customer’s consent, captured by rendering a MoonPay-hosted consent frame on their device. See Capture consent.
Render the consent frame with client.setupCustomerExport(), the same way you’d render the Auth frame. The customer reviews what’s being shared and authorizes the export inside the MoonPay-hosted frame.
Capture consent
import {
  createClient,
  type CustomerExportEvent,
} from "@moonpay/platform-sdk-web";

const client = createClient({ sessionToken: "c3N0XzAwMQ==" });

const exportResult = await client.setupCustomerExport({
  container: document.querySelector("#exportContainer"),
  onEvent: (event: CustomerExportEvent) => {
    switch (event.kind) {
      case "ready":
        // The consent UI is rendered. Reveal the container if you hide it while loading.
        break;
      case "complete":
        // Forward event.payload.token to your backend now. It expires at event.payload.tokenExpiresAt.
        console.log(event.payload.token, event.payload.tokenExpiresAt);
        break;
      case "error":
        console.error(event.payload);
        break;
    }
  },
});

if (!exportResult.ok) {
  console.error(exportResult.error.kind, exportResult.error.message);
} else {
  // Remove the frame from the DOM now that the flow has completed:
  exportResult.value.dispose();
}

Export the data

The frame delivers the consent token on its complete event. Forward it to your backend and call the export endpoint within its 5-minute validity window.
Export customer data
const res = await fetch(
  "https://api.moonpay.com/platform/v1/customers/export",
  {
    method: "POST",
    headers: {
      "X-Api-Key": "sk_test_123",
      Authorization: `Bearer ${consentToken}`,
    },
  },
);

const { data: customerData } = await res.json();
Result
{
  "data": {
    "basicDetails": {
      "firstName": "Jane",
      "lastName": "Doe",
      "dateOfBirth": "1990-01-15",
      "nationality": "USA"
    },
    "residentialAddress": {
      "country": "USA",
      "administrativeArea": "NY",
      "locality": "New York",
      "street": "350 Fifth Avenue",
      "postalCode": "10118"
    },
    "phoneNumber": { "number": "+14155551234" },
    "taxIdentifiers": [{ "type": "ssn", "value": "123-45-6789" }],
    "files": [
      {
        "id": "file_abc123",
        "type": "passport",
        "uploadedAt": "2026-06-01T12:00:00Z",
        "downloadUrl": "https://files.moonpay.com/..."
      }
    ]
  }
}
Fields you don’t hold data for are null or omitted. taxIdentifiers is included when the customer has one on file; each entry’s type is tin, ssn, or cpf, with country present only for tin. residentialAddress.subStreet and each file’s side (front or back) are included only when applicable, for example a two-sided ID document. Each file’s downloadUrl is pre-signed and expires after 60 minutes; if it expires before you fetch the file, get a fresh consent token and call the export endpoint again. The consent token is consumed on the first call, whether it succeeds or not. Notable responses: 403 if the token isn’t bound to a customer, 409 if the customer has no approved KYC to export, and 429 (with a Retry-After header) if you’ve exceeded the rate limit.

Next steps

Onboarding via API

Bring a customer to an approved KYC record before you export their data.

API and SDK credentials

Understand the secret key the export endpoint accepts.