Skip to main content

Create business customers

This guide describes how to create and onboard your customers.

The onboarding flow is asynchronous: after you create a customer, BVNK processes the application and notifies you via webhooks when action is required or when verification is complete.

You can customize the customer creation and onboarding according to your own platform flow. The modular approach allows you to call endpoints for adding documents or sharing data in any order.

The data and documents you must submit depend on your use case and on the BVNK entity (US or EU) your account is assigned to. See the compliance requirements for the full list.

When onboarding a customer, they pass through the following stages:

StatusDescription
INFO_REQUIREDThe customer data is submitted partially. Provide other information or documents.
PENDINGThe customer data is submitted and waiting for the BVNK review.
VERIFIEDCustomer verification has been succesfully completed.
ACTIONS_REQUIREDAdditional actions are required from the partner/customer.
REJECTEDCustomer checks failed. Customer onboarding is not possible.
TERMINATEDThe customer is removed by BVNK or partner.

Prerequisites

Before you start, make sure you have:

Create business customers

Business customer creation and onboarding is only available for the embedded delivery model. This flow requires verification of the legal entity (KYB) and related individuals, including directors, UBOs, and authorised signatories (KYC). The specific data and document requirements depend on jurisdiction (US or EU) and onboarding model:

  • BVNK-Managed: You submit structured data and raw identity documents (ID front/back, selfie, proof of address) via BVNK's Onboarding API. BVNK performs identity verification (ID&V) via partner services. Recommended when you don't have an existing KYC/KYB programme or want BVNK to handle the full verification lifecycle.
  • Self-managed: Available to regulated partners with an appropriate AML programme.. You perform ID&V using your own processes and pass verification metadata (document type, number, expiry, liveness timestamp, address verification type) along with a customer risk score and EDD attestation to BVNK. Note that some features of the BVNK-Managed model are not available for the Self-managed model. To learn more, contact your BVNK account manager.
Deprecated: pre-creation agreement sessions

The previous integration pattern required creating and signing an agreement session before creating a customer via POST /platform/v1/customers/agreement/sessions. This flow still functions but is superseded by the post-creation agreement flow described below. New integrations should use the following flow.

The typical BVNK-Managed flow for a business customer follows these steps:

tip

You can perform steps 3-6 in any order.

  1. Create a customer by sending the POST platform/v2/customers request with the minimum required fields. In practice you should still send a complete businessProfile and jurisdiction-specific associates fields so onboarding is not stalled.

    {
    "useCase": "FIAT",
    "reference": "partner-ref-001",
    "company": {
    "name": "Acme Ltd",
    "entityType": "CORPORATION",
    "taxIdentification": {
    "number": "GB123456789",
    "taxResidenceCountryCode": "GB"
    },
    "registrationNumber": "12345678",
    "businessProfile": {
    "description": "Online retailer of consumer electronics",
    "naicsCode": "5411",
    "monthlyExpectedVolumes": "UNDER_100K",
    "website": "https://acme.test",
    "customerTypes": "Individuals",
    "prohibitedJurisdictionsExposure": false,
    "annualIncomingTransactionValue": "500000",
    "annualOutgoingTransactionValue": "250000",
    "jurisdictionalPortfolioDistribution": [
    {
    "country": "GB",
    "percentage": 75
    },
    {
    "country": "FR",
    "percentage": 25
    }
    ],
    "isRegulated": true,
    "regulatorInformation": {
    "regulatorName": "Financial Conduct Authority",
    "regulatorJurisdiction": "GB"
    },
    "isPubliclyListed": false,
    "publicInformation": {
    "listedExchange": "LSE",
    "tickerSymbol": "ACME"
    },
    "sourceOfFunds": "COMMERCIAL_ACTIVITIES",
    "intendedUseOfAccount": "SUPPLIER_VENDOR_PAYMENTS"
    },
    "address": {
    "addressLine1": "1 Main St",
    "addressLine2": "Suite 400",
    "city": "London",
    "postalCode": "E1 6AN",
    "countryCode": "GB"
    },
    "isOperationalAddressDifferent": true,
    "operationalAddress": {
    "addressLine1": "25 Commerce Way",
    "addressLine2": "Floor 3",
    "city": "London",
    "postalCode": "EC2A 4NE",
    "countryCode": "GB"
    },
    "incorporationDate": "2018-05-12",
    "businessOperationsStartDate": "2018-06-01",
    "associates": [
    {
    "person": {
    "firstName": "Jane",
    "lastName": "Smith",
    "dateOfBirth": "1985-09-23",
    "nationality": "GB",
    "secondNationality": "IE",
    "birthCountryCode": "GB",
    "address": {
    "addressLine1": "12 Baker Street",
    "addressLine2": "Apt 5B",
    "city": "London",
    "postalCode": "NW1 6XE",
    "countryCode": "GB"
    },
    "contactInfo": {
    "emailAddress": "jane.smith@acme.test",
    "phoneNumber": "+442071234567"
    },
    "taxIdentification": {
    "number": "AB123456C",
    "taxResidenceCountryCode": "GB"
    },
    "position": "Managing Director"
    },
    "titles": [
    "UBO",
    "DIRECTOR",
    "SIGNATORY"
    ],
    "ownership": {
    "type": "DIRECT",
    "percentage": "100"
    }
    }
    ]
    }
    }

    The response includes the customer's id and initial status (for example NOT_STARTED). Save the returned associate, agreement, and customer IDs, and your external references for later steps.

  2. Retrieve the customer's status and the list of documents required for compliance by sending the GET platform/v2/customers/{id} request with the customer's ID you received in the response from step 1.

    In the response, you will receive the ID and the status of the customer.

    {
    "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "reference": "partner-ref-001",
    "status": "PENDING",
    "type": "COMPANY",
    "model": "EMBEDDED_BVNK_MANAGED",
    "useCase": "FIAT",
    "name": "Acme Ltd",
    "createdAt": "2026-04-28T11:39:12.788Z",
    "updatedAt": "2026-04-28T11:39:12.788Z",
    "authenticatedLink": {
    "link": "https://onboarding.bvnk.com/link/eyJhbGciOi...",
    "expiresAt": "2026-04-28T12:39:12.788Z"
    },
    "requiredActions": [
    {
    "type": "DATA",
    "code": "PROOF_OF_DIRECTORSHIP",
    "category": "DOCUMENT_REQUIREMENTS",
    "description": "Proof of directorship/trustees dated within the past 6 months"
    },
    {
    "type": "DATA",
    "code": "CERTIFICATE_OF_INCORPORATION",
    "category": "DOCUMENT_REQUIREMENTS",
    "description": "Business Formation Document"
    },
    {
    "type": "DATA",
    "code": "PROOF_OF_OPERATIONAL_ADDRESS",
    "category": "DOCUMENT_REQUIREMENTS",
    "description": "Proof of Operational Address"
    },
    {
    "type": "DATA",
    "code": "CORPORATE_STRUCTURE",
    "category": "DOCUMENT_REQUIREMENTS",
    "description": "Capitalization Table / Ownership Structure"
    },
    {
    "type": "DATA",
    "code": "ARTICLE_OF_ASSOCIATION",
    "category": "DOCUMENT_REQUIREMENTS",
    "description": "Article of association"
    },
    {
    "type": "DATA",
    "code": "MEMORANDUM",
    "category": "DOCUMENT_REQUIREMENTS",
    "description": "Memorandum"
    },
    {
    "type": "DATA",
    "code": "REQUIRED_ALL_ASSOCIATES_VALID",
    "category": "ASSOCIATES",
    "description": "All associates must have valid status prior to submission."
    }
    ],
    "company": {
    "name": "Acme Ltd",
    "entityType": "CORPORATION",
    "registrationNumber": "12345678",
    "taxIdentification": {
    "number": "GB123456789",
    "taxResidenceCountryCode": "GB"
    },
    "incorporationDate": "2018-05-12",
    "businessOperationsStartDate": "2018-06-01",
    "address": {
    "addressLine1": "1 Main St",
    "addressLine2": "Suite 400",
    "city": "London",
    "postalCode": "E1 6AN",
    "countryCode": "GB"
    },
    "associates": [
    {
    "person": {
    "firstName": "Jane",
    "lastName": "Smith",
    "dateOfBirth": "1985-09-23",
    "nationality": "GB",
    "birthCountryCode": "GB"
    },
    "titles": [
    "UBO",
    "DIRECTOR",
    "SIGNATORY"
    ],
    "ownership": {
    "type": "DIRECT",
    "percentage": "100"
    }
    }
    ]
    }
    }
  3. Upload the required company documents by sending the POST platform/v2/customers/{customerId}/documents request with the customer's ID you received in the response from step 1.

    Upload documents sequentially. You can add up to three documents in a batch. Add a one-second delay between uploads to stay within rate limits. For the list of the required documents, see Business documents (KYB) in the Compliance requirements reference.

    tip

    For documents in unsupported languages, a professionally notarised English translation is permitted.

    In the response, you will see the documents accepted for processing.

    {
    "id": "9b0c4f1d-7aa2-4c7e-8d55-f8b4a1d6c210",
    "customerId": "0a184641-30e2-4414-871f-3db1c683900e",
    "totalDocuments": 3,
    "successCount": 3,
    "failureCount": 0,
    "documents": [
    {
    "documentId": "b8f8a6b5-8f44-4b7c-8d1e-4a6a5a9b4a21",
    "type": "CERTIFICATE_OF_INCORPORATION",
    "filename": "certificate.pdf",
    "description": "Certificate of Incorporation",
    "status": "STORED",
    "uploadedAt": "2026-04-22T10:58:35.056865Z"
    }
    ],
    "createdAt": "2026-04-22T10:58:35.056865Z"
    }
  4. Upload associate ID documents by sending the POST platform/v2/customers/{customerId}/associates/{associateId}/identification-documents request with the associate ID you received in the response from step 2.

    For the list of the required documents, see Identity verification (associates) in the Compliance requirements reference.

    {
    "metadata": [
    {
    "type": "PASSPORT",
    "name": "passport.pdf",
    "countryCode": "GB"
    }
    ]
    }

    In the response, you will receive the associate ID and the number of documents accepted for processing.

    {
    "id": "4b0b8e2e-2f4e-4bfa-86d2-95aed0512c5f",
    "associateId": "07b099fa-e1ee-4ad4-9cc4-6f2513a5a240",
    "acceptedDocumentCount": 1,
    "createdAt": "2026-04-22T11:00:35.056865Z"
    }
  5. Retrieve assigned agreements by sending the GET platform/v2/customers/{customerId}/agreements request with the customer ID you received in the response from step 1. You must share the agreements with your customers and request that they sign them.

    To fetch a specific assigned agreement by id, call GET platform/v2/customers/{customerId}/agreements/{assignedAgreementId}. To download the agreement document, call GET platform/v2/customers/{customerId}/agreements/{assignedAgreementId}/content to receive a short-TTL presigned URL.

    The response is a paginated list of assigned agreements:

    {
    "content": [
    {
    "id": "06d119bc-64f6-46b2-aea2-3ff94c4c616f",
    "agreement": {
    "version": "1.0",
    "title": "Partner Platform Agreement (Non-US)",
    "locale": "en-GB"
    },
    "status": "PENDING",
    "createdAt": "2026-03-25T10:57:38.145505Z",
    "updatedAt": "2026-03-25T10:57:38.145505Z"
    }
    ],
    "totalElements": 1,
    "totalPages": 1,
    "hasNext": false
    }
  6. Accept an assigned agreement for a specific customer by sending the POST platform/v2/customers/{customerId}/agreements/{assignedAgreementId}/actions request with the action.

    {
    "type": "ACCEPT"
    }

    To accept or reject up several agreements in the single request, call the POST platform/v2/customers/{customerId}/agreements/actions endpoint with a similar payload.

    {
    "actions": [
    {
    "assignedAgreementId": "06d119bc-64f6-46b2-aea2-3ff94c4c616f",
    "type": "ACCEPT"
    },
    {
    "assignedAgreementId": "6b4f0f2a-5c7d-4f1e-9c2a-1a9e2e1b3f48",
    "type": "ACCEPT"
    }
    ]
    }
  7. Wait for the webhook or poll the status by sending the GET platform/v2/customers/{id} request. The response includes onboarding ID, status, timestamps, associates (including requiredDocuments and validationErrors), and agreements.

Customer review

Onboarding completes automatically once all of the conditions are met:

  • You uploaded company documents, and they are accepted for processing.
  • You uploaded associate identity documents, and they are accepted for processing.
  • All assigned agreements accepted.

There is no separate "complete" or "submit" API call. Once all conditions are met, BVNK triggers verification for all associates and the company entity. The customer transitions through processing states, and you receive the final outcome via webhook.

Onboarding statuses

Customer status flow

Agreement status

StatusDescription
PENDINGAgreement assigned to the customer and awaiting a response.
ACCEPTEDCustomer accepted the agreement.
REJECTEDCustomer rejected the agreement.

Customer verification status

StatusDescription
VERIFIEDCustomer verified and approved. Wallets and products can be provisioned.
REJECTEDVerification failed. The EPC cannot proceed.
SUSPENDEDAccount suspended (post-onboarding).

Document rejection and resubmission

When a document is rejected, the status response includes rejection details:

{
"docSetType": "SELFIE",
"types": ["SELFIE"],
"status": "REJECTED",
"rejectLabels": ["BAD_SELFIE"],
"clientComment": "A new liveness check has been requested."
}

Handle rejections programmatically. Parse rejectLabels to determine whether to resubmit or surface a failure to your user. To resubmit, upload the corrected document to the same endpoint. The rejected document is replaced.

Webhooks

Webhooks must be used as the primary mechanism for tracking status changes. Use polling only as a fallback.

To receive updates on each step of the onboarding process, configure your webhook endpoint in the BVNK Portal. BVNK sends notifications for key lifecycle events.

EventTrigger
CUSTOMER_STATUS_CHANGECustomer status transitions.
CUSTOMER_DOCUMENT_STATUS_CHANGEDocument status transitions.
CUSTOMER_UPDATECustomer data updated, for example, after verification, or KYC data populated.
AGREEMENT_SESSION_STATUS_CHANGEAgreement signed or declined.

Use CUSTOMER_STATUS_CHANGE as the primary driver for your onboarding flow. When you receive a status change, call the status endpoint to retrieve the current requirements.

Error handling

ScenarioResponse status codeResolution
Missing required field400Check the error message for the specific missing field.
Invalid industry / volume value400Use accepted enum values from the API definitions.
No associates provided400Include at least one associate with a valid title.
Associate missing required role400At least one associate must hold BUSINESS_OWNER or DIRECTOR title.
Documents not yet synced400: DOCUMENTS_NOT_READYWait for all documents to reach PENDING status.
Was this page helpful?