HomeGuidesAPI ReferenceChangelog
Home
Guides

Universal KYC

Purpose: Onboard individual cardholders into the Reap platform using one canonical workflow that consolidates entity identification, identity attributes, residential address, liveness outcome, provider verification result, jurisdiction-specific data where required, and supporting documentation against typed requirement slugs.


When to Use This

Use this guide when you need to:

  • Onboard a new individual cardholder to Reap as an INDIVIDUAL entity
  • Submit a canonical KYC Pack covering identity, identification document, residential address, liveness result, and the configured KYC provider's verification outcome
  • Submit jurisdiction-specific data for cardholders issued under a MEX BIN (binCountry = MEX)
  • Upload supporting KYC documents (ID Document, Proof of Address, and the CURP Document for MEX) against typed requirement slugs
  • Retrieve the signed KYC payload after approval for downstream card issuance under Reap's non-BIN sponsorship model
  • Correct or update an earlier KYC submission by appending a new full payload

Overview

Universal KYC brings the full cardholder onboarding journey into a single structured workflow under the Reap Compliance API. Instead of managing multiple independent requirement submissions, integrators submit one canonical payload for the case. This payload, known as the KYC Pack includes identity information, identification documents, residential address details, and liveness results. Integrators also upload supporting documents using KYC specific requirement slugs. The payload is then completed with the verification outcome from the configured provider.

Every submission must be linked to a single individual entity created through the existing Entity resource with type: INDIVIDUAL. Each submission is stored as a typed record and serves as the authoritative audit ready source of truth throughout the entire case lifecycle.

The submission payload also powers Reap’s jurisdiction specific rule engine orchestration, enabling conditional compliance flows such as:

  • MEX specific CURP validation requirements
  • mandatory jurisdictionData handling for applicable regions
  • country dependent onboarding and verification flows

The signed payload becomes a portable and tamper evident authorisation artefact that supports downstream card issuance and related provisioning workflows for non BIN sponsorship programs after approval.


Prerequisites

  1. Compliance approval from Reap for the use of Universal KYC for the program
  2. An established KYC provider already in place
  3. Agreement that Reap retains the final approval authority for card issuance under its non-reliance model
  4. A valid Reap API key is required to authenticate all Universal KYC requests
  5. The externalId value to be used as the integrator's correlation reference for the cardholder
💬

Please contact your account manager if you have any questions about the Universal KYC approval process.

⚠️

This guide contains two post-approval paths:

  • Non-BIN sponsorship clients: must complete Step 5 (Fetch the Signed Payload) and Step 6 (Create Card).
  • BIN sponsorship clients (e.g. Bybit): do not need to complete Steps 5 and 6. They may use the verified KYC information directly in their own downstream card issuance flow after KYC is approved.

Key Concepts

Individual Entity

  • The anchor record for all Universal KYC submissions
  • Created via POST /entity with type: INDIVIDUAL
  • Returns an id (used as entityId in all subsequent calls) and echoes back the integrator-supplied externalId

KYC Pack

  • Canonical typed payload capturing the cardholder's identity, identification document, residential address, liveness result, and the configured KYC provider's verification outcome
  • Submitted via POST /entity/entityId/ukyc

BIN Country and Jurisdiction Data

  • binCountry declares the ISO 3166-1 alpha-3 country code of the issuing BIN
  • binCountry determines the jurisdiction-specific KYC flow applied to the cardholder (verification rules and the structure of jurisdictionData)
  • binCountry and a matching jurisdictionData.<COUNTRY> block are required when the issuing BIN belongs to a jurisdiction with jurisdiction-specific requirements currently MEX and both fields are excluded for all other BIN countries
  • binCountry is independent of the cardholder's identity.nationality. Document requirements that are tied to nationality (such as the CURP document for Mexican nationals) are driven by identity.nationality, not by binCountry.

Nationality-driven Requirements

  • identity.nationality declares the ISO 3166-1 alpha-3 nationality of the cardholder
  • Some supporting documents are required by nationality rather than by BIN and currently ukyc-curp-document is required when identity.nationality = "MEX" for Mexican nationals
  • These requirements are independent of binCountry where a Mexican national issued on a non-MEX BIN still uploads the CURP document and a non-Mexican national issued on a MEX BIN does not

Provider Verification

  • Verification result block submitted alongside the KYC Pack capturing the configured KYC provider's overall outcome
  • Carries the provider name, an overall verification status, and a free-form data payload that retains the provider's own correlation evidence

Signed Payload

  • Portable, tamper-proof representation of an approved KYC application
  • Retrieved via GET /entity/entityId/signed-payload once the case is approved
  • Serves as the authorisation evidence for proceeding with card issuance under Reap's non-BIN sponsorship model

Requirement Slug

  • Typed identifier for each supporting document category (ukyc-id-document, ukyc-proof-of-address-document, ukyc-curp-document)
  • Drives document association and compliance review routing

External ID

  • Unique identifier for the cardholder within the integrator's system
  • Used to correlate the Reap entity with the integrator's internal record

Flow Overview

  1. Create the individual entity via POST /entity with type: INDIVIDUAL
  2. Submit the KYC Pack via POST /entity/entityId/ukyc and include binCountry and jurisdictionData only when binCountry = MEX
  3. Upload supporting KYC documents via POST /entity/entityId/requirement-slug/requirementSlug/upload:
    • ukyc-id-document: required for all cardholders
    • ukyc-proof-of-address-document: required for all cardholders
    • ukyc-curp-document: required only when identity.nationality = "MEX" for Mexican nationals and independent of binCountry
  4. Receive the KYC decision via webhook notification (APPROVED or REJECTED)
  5. Fetch the signed payload via GET /entity/entityId/signed-payload only for non-BIN sponsorship programs
  6. Create the card via POST /cards using the signed payload only for non-BIN sponsorship programs

API Summary

ActionEndpointMethodUse Case
Create individual entity/entityPOSTRegister an individual-type entity to anchor all subsequent KYC submissions
Submit KYC Pack/entity/entityId/ukycPOSTSubmit the canonical identity, document, address, liveness, provider verification result, and (for MEX) jurisdiction data
Upload KYC supporting documents/entity/entityId/requirement-slug/requirementSlug/uploadPOSTUpload the ID Document, Proof of Address, and (for MEX) the CURP Document to a typed slug
Fetch signed payload/entity/entityId/signed-payloadGETRetrieve the portable, signed authorisation payload after KYC approval (non-BIN sponsorship)
Create card/cardsPOSTCreate a card by passing the signed KYC payload to the card issuance API (non-BIN sponsorship)

Universal KYC Onboarding

Step 1: Register and Create Individual Entity

Create an individual-type entity to anchor the subsequent KYC submissions. The id returned by this call is used as entityId in all subsequent Universal KYC requests.


Call the Create Entity Endpoint

Use POST /entity to register the cardholder and obtain the anchor entity record.


Sample Request (cURL)

curl --request POST \
  --url https://sandbox-compliance.api.reap.global/entity \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/json' \
  --header 'x-reap-api-key: ********' \
  --data '
{
  "externalId": "CUSTOMER-DEMO-10001",
  "type": "INDIVIDUAL"
}
'

Key Input

Parameter NameTypeDescription
typestringSet the entity type to INDIVIDUAL for KYC verification

Sample Response

{
  "id": "5f54bcf9-5a21-4f76-a819-6a65a8c238b8",
  "externalId": "CUSTOMER-DEMO-10001",
  "businessId": "e10e9f95-f256-4c47-bcf6-a6029e09c3aa",
  "type": "INDIVIDUAL"
}

Key Output

Parameter NameTypeDescription
idstringUnique identifier generated by Reap for the created entity. Used as entityId in all subsequent calls
externalIdstringThe external reference ID provided during entity creation
businessIdstringUnique identifier for the associated Reap business account
typestringType of entity created

Step 2: Submit the KYC Pack

Submit the canonical KYC payload containing identity, identification document, residential address, liveness result, and the configured provider's verification outcome in a structured, typed JSON body. The request must additionally include binCountry: MEX and jurisdictionData.MEX for cardholders issued under a MEX BIN. Both fields are excluded for all other countries.


Call the Submit KYC Pack Endpoint

Use POST /entity/entityId/ukyc to submit the KYC Pack against the individual entity created in the previous step.


⚠️

cardProcessorPublicToken is only required when the client is under BIN sponsorship.

Sample Request (cURL) — MEX BIN Country (MEX national)

The payload must include jurisdictionData.MEX when binCountry = MEX.

curl --request POST \
  --url https://sandbox-compliance.api.reap.global/entity/entityId/ukyc \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/json' \
  --header 'X-UKYC-Version: 1' \
  --header 'x-reap-api-key: ********' \
  --data '{
    "externalUserId": "user_12345",
    "cardProcessorPublicToken": "processor_public_token_123",
    "binCountry": "MEX",
    "provider": {
      "name": "SUMSUB",
      "status": "APPROVED",
      "data": [
        { "key": "sumsubApplicantId", "value": "65b1f3e1c4d2b5a6f7e8d9c0" }
      ]
    },
    "identity": {
      "firstName": "Jorge",
      "middleName": "Luis",
      "lastName": "Hernández",
      "fullName": "Jorge Luis Hernández",
      "dob": "1990-04-12",
      "nationality": "MEX"
    },
    "document": [
      {
        "documentCategory": "IDV",
        "type": "PASSPORT",
        "number": "A12345678",
        "country": "MEX",
        "issuingDate": "2020-01-01",
        "expiryDate": "2030-01-01"
      },
      {
        "documentCategory": "POA",
        "type": "UTILITY_BILL",
        "number": "UB-2024-987654",
        "country": "MEX",
        "issuingDate": "2024-09-15"
      }
    ],
    "address": {
      "street": "Av. Paseo de la Reforma 123",
      "town": "Ciudad de México",
      "state": "CDMX",
      "postCode": "06600",
      "country": "MEX"
    },
    "liveness": {
      "result": "APPROVED",
      "checkedAt": "2026-05-09T10:00:00Z"
    },
    "jurisdictionData": {
      "MEX": {
        "countryOfBirth": "MEX",
        "economicActivity": "Retail trade",
        "phone": "+525512345678",
        "email": "[email protected]",
        "authorityIdIssuer": "INE",
        "taxId": "XAXX010101000",
        "curp": "XAXX010101HDFXXX00",
        "uboAttestation": true
      }
    }
  }'
ℹ️

When binCountry = "MEX" and identity.nationality = "MEX", a CURP document upload requirement is automatically created in PENDING status and must be fulfilled via POST /entity/entityId/requirement-slug/ukyc-curp-document/upload.

⚠️

Inside jurisdictionData.MEX, the fields phone, email, taxId, and curp are required only when identity.nationality = "MEX" and should be excluded for non-Mexican nationals issued under a MEX BIN.


Sample Request (cURL) (Other Country)

The binCountry field is not required and jurisdictionData is not required when binCountry is not MEX. Both fields are excluded from the payload.

curl --request POST \
  --url https://sandbox-compliance.api.reap.global/entity/entityId/ukyc \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/json' \
  --header 'X-UKYC-Version: 1' \
  --header 'x-reap-api-key: ********' \
  --data '{
    "externalUserId": "user_12345",
    "cardProcessorPublicToken": "processor_public_token_123",
    "provider": {
      "name": "SUMSUB",
      "status": "APPROVED",
      "data": [
        { "key": "sumsubApplicantId", "value": "65b1f3e1c4d2b5a6f7e8d9c0" }
      ]
    },
    "identity": {
      "firstName": "Jack",
      "middleName": "Sam",
      "lastName": "Ong",
      "fullName": "Jack Sam Ong",
      "dob": "1994-06-18",
      "nationality": "USA"
    },
    "document": [
      {
        "documentCategory": "IDV",
        "type": "PASSPORT",
        "number": "123456789",
        "country": "USA",
        "issuingDate": "2020-01-01",
        "expiryDate": "2030-01-01"
      },
      {
        "documentCategory": "POA",
        "type": "UTILITY_BILL",
        "number": "UB-2024-123456",
        "country": "USA",
        "issuingDate": "2024-09-15"
      }
    ],
    "address": {
      "street": "123 Main Street",
      "town": "New York",
      "state": "NY",
      "postCode": "10001",
      "country": "USA"
    },
    "liveness": {
      "result": "APPROVED",
      "checkedAt": "2026-05-09T10:00:00Z"
    }
  }'

Key Input

Parameter NameTypeDescription
cardProcessorPublicTokenstringCard processor public token required only for clients operating under BIN sponsorship.
This is the 9-digit numeric public token for the card processor account and not the 16-digit tokenised PAN.
binCountrystringISO 3166-1 alpha-3 BIN country code required only when issuing under a Mexico BIN (MEX) and excluded for all other BIN countries to drive jurisdiction-specific rule engine branching
providerobjectConfigured KYC provider verification outcome based on the selected provider below
jurisdictionDataobjectJurisdiction-specific block keyed by ISO 3166-1 alpha-3 country code that is required when binCountry is set (currently MEX) and should be excluded for all other countries

provider (object)

Parameter NameTypeDescription
namestringConfigured KYC provider name such as SUMSUB or JUMIO
statusstringOverall verification status with enum values APPROVED, REJECTED, WARNING, and NOT_EXECUTED

jurisdictionData (object)

Parameter NameTypeDescription
MEXobjectJurisdiction block required when binCountry is MEX and reserved for jurisdiction-specific extensions with support for an empty object () submission today

Sample Response

{}

Step 3: Upload KYC Documents

Upload supporting documents for KYC requirement slugs using the shared file upload endpoint to retain verifiable evidence for audit and compliance reviews.


Call the File Upload Endpoint

Use POST /entity/entityId/requirement-slug/requirementSlug/upload to upload a file for a KYC document slug.


Sample Request (cURL) (ID Document)

curl --request POST \
  --url https://sandbox-compliance.api.reap.global/entity/entityId/requirement-slug/ukyc-id-document/upload \
  --header 'Accept: application/json' \
  --header 'Content-Type: multipart/form-data' \
  --header 'x-reap-api-key: ********' \
  --form 'file=@"passport.jpg"'

Sample Request (cURL) (Optional memberId)

curl --request POST \
  --url 'https://sandbox-compliance.api.reap.global/entity/entityId/requirement-slug/ukyc-id-document/upload?memberId=member_456' \
  --header 'Accept: application/json' \
  --header 'Content-Type: multipart/form-data' \
  --header 'x-reap-api-key: ********' \
  --form 'file=@"passport.jpg"'

Key Input

Parameter NameTypeDescription
requirementSlugstringPath parameter specifying the KYC document type the file is uploaded against: ukyc-id-document and ukyc-proof-of-address-document for all cardholders, and ukyc-curp-document only when identity.nationality = "MEX"
memberIdstringOptional query parameter specifying the member record to associate the uploaded document with
filefileThe file to upload as multipart/form-data
ℹ️

Use repeated POST calls with the appropriate requirementSlug:

  • ukyc-id-document and ukyc-proof-of-address-document for every cardholder
  • ukyc-curp-document only when the cardholder's identity.nationality is "MEX"
  • This requirement is driven by nationality and not by binCountry

Sample Response

{}

KYC Document Slugs

The requirementSlug path parameter accepts the values listed below. Each slug routes the uploaded file to a specific document category for compliance review.

SlugCategoryDescription
ukyc-id-documentMandatory KYCGovernment-issued identification document (e.g. passport, ID card, or driver's licence)
ukyc-proof-of-address-documentMandatory KYCProof of residential address (e.g. utility bill or bank statement)
ukyc-curp-documentConditional (nationality)CURP (Clave Única de Registro de Población) document required only when identity.nationality = "MEX" for Mexican nationals and independent of binCountry

File Upload Constraints

ConstraintLimit
Allowed extensionsSupported file formats are .jpg, .jpeg, .png and .pdf while all other extensions are rejected with HTTP 400
Maximum file sizeUp to 10 MB per file is accepted and uploads exceeding this limit are rejected

Step 4: KYC Decision

The application enters final KYC review after the KYC Pack and required documents are submitted with the decision result sent asynchronously via webhook.

⚠️

Only applications with an APPROVED status can proceed to Step 5 (Signed Payload Retrieval) and Step 6 (Create Card).


Sample Decision Webhook

The KYC decision is communicated via webhook notification.

{
  "eventName": "card_issuance_api_access_updated",
  "eventType": "account_status_change",
  "data": {
    "eventId": "938c65f7-2aad-494d-b488-5256c4cfc370",
    "message": "User profile approved - card generation enabled",
    "entityId": "6ac28264-c21b-4757-b141-1efce00adce6",
    "timestamp": "2026-01-27T13:27:51.027Z",
    "status": "APPROVED"
  }
}
{
  "eventName": "card_issuance_api_access_updated",
  "eventType": "account_status_change",
  "data": {
    "eventId": "fc7b8d1d-9e08-4c61-bef2-3ce4e6162dcf",
    "message": "Universal KYC requirement rejected",
    "entityId": "6c539925-f00c-4b11-bbc8-7edec5bb69b1",
    "status": "REJECTED",
    "moderationComment": "Country of residence (IND) is prohibited",
    "rejectLabels": ["PROHIBITED_RESIDENCE"],
    "reviewRejectType": "FINAL",
    "timestamp": "2026-01-27T13:29:58.336Z"
  }
}

Webhook Outcomes

Webhook DecisionNotes
APPROVEDCardholder has passed KYC checks and can proceed to create a card
REJECTEDCardholder failed KYC checks and is not eligible to create a card but requirements and documents may be resubmitted for future review

Step 5: Fetch the Signed Payload

The signed payload is a portable and tamper-proof representation of an approved KYC application. It serves as the authorisation evidence for proceeding with card issuance under Reap's non-BIN sponsorship model.

ℹ️

BIN sponsorship clients (e.g. Bybit) are not required to complete this step. Verified KYC information can be used directly in the downstream card issuance flow once KYC approval is obtained.


Call the Fetch Signed Payload Endpoint

Use GET /entity/entityId/signed-payload to retrieve the signed payload associated with the approved KYC application.


Sample Request (cURL)

curl --request GET \
  --url 'https://sandbox-compliance.api.reap.global/entity/entityId/signed-payload?featureSlug=universal-kyc-card-issuance-kyc-api' \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/json' \
  --header 'x-reap-api-key: ********'

Key Input

Parameter NameTypeDescription
featureSlugstringQuery parameter specifying the featureSlug value universal-kyc-card-issuance-kyc-api

Sample Response

{
  "firstName": "Jack",
  "lastName": "Sam Ong",
  "dob": "1994-06-18",
  "idDocumentType": "Passport",
  "idDocumentNumber": "K1234567",
  "residentialAddress": {
    "line1": "Flat 1208, 350, TIFF Bell Lightbox, King Street West",
    "line2": "Downtown",
    "city": "Toronto",
    "country": "CAN",
    "postalCode": "M5V 3L9"
  },
  "expiresAt": "2026-03-10T09:18:51.998Z",
  "signature": "bd6565bfb621f6321095e7dc574ea52b3829e29a732440170794fabfc8dec..."
}

Key Output

Parameter NameTypeDescription
firstNamestringVerified first name from the approved KYC record
lastNamestringVerified last name from the approved KYC record
dobstringDate of birth (Format: YYYY-MM-DD)
idDocumentTypestringType of government-issued ID used for verification
idDocumentNumberstringVerified ID document number
residentialAddressobjectVerified residential address (line1, line2, city, country, postalCode)
expiresAtstringExpiry timestamp of the signed payload (Format: ISO 8601)
signaturestringCryptographic signature ensuring payload integrity and authenticity

residentialAddress (object)

Parameter NameTypeDescription
line1stringPrimary address line
line2stringSecondary address line
citystringCity of residence
countrystringISO 3166-1 alpha-3 country code
postalCodestringPostal or ZIP code

Step 6: Create Card

The signed payload returned in Step 5 must be passed into the Create Card endpoint when creating a card.

ℹ️

BIN sponsorship clients (e.g. Bybit) do not need to complete this step and may use the verified KYC information directly in the downstream card issuance flow after KYC approval.


Call the Create Card Endpoint

Use POST /cards to create the card and include the signed payload in the request body.


Sample Request (cURL)

curl --request POST \
  --url https://sandbox-compliance.api.reap.global/cards \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/json' \
  --header 'Accept-Version: v2.0' \
  --header 'x-reap-api-key: ********' \
  --data '{
    "...": "...",
    "kyc": {
      "firstName": "Jack",
      "lastName": "Sam Ong",
      "dob": "1994-06-18",
      "idDocumentType": "Passport",
      "idDocumentNumber": "K1234567",
      "residentialAddress": {
        "line1": "Flat 1208, 350, TIFF Bell Lightbox, King Street West",
        "line2": "Downtown",
        "city": "Toronto",
        "country": "CAN",
        "postalCode": "M5V 3L9"
      },
      "expiresAt": "2026-03-10T09:18:51.998Z",
      "signature": "bd6565bfb621f6321095e7dc574ea52b3829e29a732440170794fabfc8dec..."
    },
    "...": "..."
  }'

Key Input

kyc (object)

Parameter NameTypeDescription
kyc.signaturestringSigned JWT returned from the signed-payload endpoint ensuring payload integrity and KYC approval

Sample Response

{
  "id": "fa1bcdae-c101-4986-b385-8083fb43a7ab"
}

Key Output

Parameter NameTypeDescription
idstringUnique identifier of the successfully created card

Scenarios

Scenario: Standard Onboarding

  • Create the individual entity with POST /entity using type: INDIVIDUAL
  • Submit the KYC Pack via POST /entity/entityId/ukyc without including binCountry or jurisdictionData
  • Upload the ID Document (ukyc-id-document) and Proof of Address (ukyc-proof-of-address-document)
  • Fetch the signed payload via GET /entity/entityId/signed-payload on the APPROVED webhook
  • Pass the signed payload to POST /cards to create the card

Scenario: BIN Sponsorship Onboarding (MEX BIN, MEX National)

  • Create the individual entity with POST /entity using type: INDIVIDUAL
  • Submit the KYC Pack via POST /entity/entityId/ukyc including the cardProcessorPublicToken, binCountry = "MEX", jurisdictionData.MEX, and identity.nationality = "MEX"
  • Upload ukyc-id-document and ukyc-proof-of-address-document (required for every cardholder)
  • Upload ukyc-curp-document (required because identity.nationality = "MEX")
  • Use the verified KYC information directly in the BIN sponsor's downstream card issuance flow without requiring steps 5 and 6

Common Errors

ErrorCauseResolution
401 UnauthorizedMissing or invalid API keyCheck x-reap-api-key
Entity not foundentityId is unknown, deleted, or belongs to a different businessConfirm the entityId returned from POST /entity and re-issue the request
Unsupported file extensionUploaded file extension is not .jpg, .jpeg, .png, or .pdfRe-upload using a supported file format

TL;DR

  • Universal KYC is a single canonical workflow for end-to-end cardholder onboarding under the Reap Compliance API
  • Create the individual entity first with POST /entity and type: INDIVIDUAL and use the returned id as the entityId for all subsequent calls
  • Submit the KYC Pack via POST /entity/entityId/ukyc (identity, document, address, liveness, and provider verification result)
  • Additionally include binCountry: "MEX" and jurisdictionData.MEX for MEX BIN cardholders while excluding both fields for all other countries
  • Upload supporting documents via POST /entity/entityId/requirement-slug/requirementSlug/upload: ukyc-id-document and ukyc-proof-of-address-document for all cardholders plus ukyc-curp-document only when identity.nationality = "MEX"
  • Non-BIN sponsorship clients fetch the signed payload via GET /entity/entityId/signed-payload on the APPROVED webhook and pass it into POST /cards while BIN sponsorship clients use the verified KYC information directly in the downstream card issuance flow

Demo

For a fully interactive demo, see below: