Skip to main content
Customers must complete identity verification before processing conversions. The required information varies based on your platform’s regulatory status.
Regulated platforms have lighter KYC requirements since they handle compliance verification internally.
The KYC/KYB flow allows you to onboard customers through direct API calls.Regulated financial institutions can:
  • Direct API Onboarding: Create customers directly via API calls with minimal verification
  • Internal KYC/KYB: Handle identity verification through your own compliance systems
  • Reduced Documentation: Only provide essential customer information required by your payment counterparty or service provider.
  • Faster Onboarding: Streamlined process for known, verified customers

Creating Customers via Direct API

For regulated platforms, you can create customers directly through the API without requiring external KYC verification:To register a new customer in the system, use the POST /customers endpoint:
The examples below show a more comprehensive set of data. Not all fields are strictly required by the API for customer creation itself, but become necessary based on currency and UMA provider requirements if using UMA.
Unregulated platforms rely on Grid to run KYC for individuals and KYB for businesses. You can onboard customers either through the hosted KYC/KYB link flow below, or by submitting customer data directly through the API. Both paths cover KYC and KYB, produce the same status transitions — on kycStatus for individuals, kybStatus for businesses — and emit the same CUSTOMER.KYC_* / CUSTOMER.KYB_* webhooks. You can also mix them: supply what you already hold through the API, then let the hosted flow collect the rest.
Either path works for unregulated platforms:
  • Hosted flow: Redirect customers to a Grid-hosted link (or embed the provider SDK). Covers individuals and businesses alike. Best when you want Grid to handle the entire collection UX.
  • Direct API onboarding: Collect customer information in your own UI and submit it via the API. For INDIVIDUAL customers (KYC), personal information goes through POST /customers. For BUSINESS customers (KYB), you also register beneficial owners via POST /beneficial-owners. Submit for review with POST /verifications.
The hosted flow provides a secure, hosted interface where customers complete verification. It serves both customer types — there is no separate KYB link endpoint. POST /customers/{customerId}/kyc-link generates the link, and customerType selects which flow the provider runs:
  • INDIVIDUAL — identity verification (KYC), tracked on kycStatus.
  • BUSINESS — business verification (KYB), tracked on kybStatus. The applicant confirms the company details, uploads the formation, ownership, and proof-of-address documents, and declares the control person and every beneficial owner holding 25% or more.
The flow is two steps: create the customer with the information you have, then generate the link. The status starts at UNVERIFIED and moves to PENDING once the customer completes the flow and review begins.

1. Create the customer

Supply at least customerType and any fields you already have.
Persist the returned id (the Grid customer ID) — you’ll need it for the next step.
Business information you supply is prefilled into the hosted flow, so send as much as you have — via POST /customers or a later PATCH /customers/{customerId}before generating the link. Every field you pass is one the applicant doesn’t retype, and one fewer chance for their answer to diverge from your record.
Response:
The response field is named kycUrl for both customer types; for a BUSINESS customer it opens the KYB flow. For providers that support direct SDK integration (currently SUMSUB), a token is also returned — pass it to the provider’s web SDK to embed verification in your own UI instead of redirecting. Both update the customer’s status identically.

The flow end to end

1

Create the customer

Call POST /customers with customerType and any pre-fill fields you have. The returned id is the customer’s Grid ID. Their status — kycStatus for an individual, kybStatus for a business — starts at UNVERIFIED, becomes PENDING while under review, and lands on APPROVED or REJECTED when the decision is made. (HOLD means the customer may be asked to supply more information.)
2

Verify contact channels (only where required)

Some regions (for example, the EU) require the customer’s email and/or phone to be verified before verification can begin. For a business customer, these are the primary contact’s details. When this applies, the customer carries a contactVerification object listing only the channels that are required — for example { "email": "PENDING", "phone": "PENDING" }, or just { "email": "PENDING" } if a provider requires email alone. When the object is absent, no contact verification is required and you can skip this step.For each channel that’s present, drive a send-then-confirm pair (the provider delivers a one-time code by email/SMS):
  • POST /customers/{customerId}/verify-email, then POST /customers/{customerId}/verify-email/confirm with { "code": "..." }
  • POST /customers/{customerId}/verify-phone, then POST /customers/{customerId}/verify-phone/confirm with { "code": "..." }
Re-POST the send endpoint to resend a code. Each channel moves PENDINGVERIFIED. (verify-email/verify-phone return 409 for a channel the provider doesn’t require.)
Generating the link before every present channel is VERIFIED returns 409.
3

Generate the link

Call POST /customers/{customerId}/kyc-link. Each call returns a fresh single-use kycUrl and expiresAt; previously-issued links remain single-use but aren’t invalidated.
The redirectUri you pass is embedded in the generated kycUrl and is used to automatically return the customer to your application after they complete verification.
4

Send the customer through verification

Redirect the customer to kycUrl, or — if you want to embed the flow directly — initialize the provider’s SDK with the returned token. A business applicant completes the company details, uploads the company documents, and declares the beneficial owners here.
The hosted URL is single-use and expires at expiresAt. If a customer needs to retry, call the endpoint again to generate a new link.
5

Track the decision

Reaching your redirectUri only means the customer finished the hosted flow — not that they were approved. Wait for the final decision in one of two ways:
  • Webhook (recommended): Subscribe to CUSTOMER.KYC_APPROVED / CUSTOMER.KYC_REJECTED (and CUSTOMER.KYB_APPROVED / CUSTOMER.KYB_REJECTED for business customers) to be notified when the customer reaches a terminal status. CUSTOMER.KYC_PENDING (and the KYB_PENDING sibling) also fires when the customer is submitted for review — subscribe to it as well if you want to surface an “under review” state to the customer.
  • Polling: Call GET /customers/{customerId} and inspect kycStatus (individuals) or kybStatus (businesses).
GET /verifications?customerId=... gives the finer-grained verificationStatus and errors array. That detail drives direct API onboarding; in the hosted flow the customer resolves it inside the flow, so integrate against kycStatus / kybStatus.
6

Handle completion

On APPROVED, the customer is ready to transact — proceed with account setup and unlock funding. On REJECTED, surface the appropriate next step (for example, regenerate the link or request manual review). While the status is PENDING, let the customer finish account setup but block funding and money movement.
Testing the business flow in sandbox: a businessInfo.registrationNumber not ending in 001, 002, or 003 auto-approves the customer on the spot, leaving the hosted flow nothing to verify — so it asks for no documents and no beneficial owners. Use a 003 suffix to exercise document and UBO collection. See Sandbox testing.

Direct API Onboarding

Prefer to collect identity information in your own UI and submit it to Grid yourself? Use the API directly instead of redirecting to a hosted link. The customer’s kycStatus transitions the same way and you receive the same CUSTOMER.KYC_APPROVED / CUSTOMER.KYC_REJECTED / CUSTOMER.KYC_PENDING (and CUSTOMER.KYB_* equivalents) webhooks.The shape of the flow depends on the customer type:
  • KYC (INDIVIDUAL customers) — supply the customer’s personal information through the customer endpoint. No beneficial owners are involved.
  • KYB (BUSINESS customers) — create the business customer, then register its beneficial owners, directors, and officers individually.
1

Create the customer with personal information

Call POST /customers with customerType: INDIVIDUAL and the personal information collected from the customer (legal name, date of birth, address, nationality, etc.). The returned id is the customer’s Grid ID; kycStatus starts at UNVERIFIED and moves to PENDING once you submit for verification.
fullName must contain both a given name and a family name (for example, "Jane Doe"). The name is split into first/last for the verification provider, and a single-word name is rejected at submission.
Where the customer’s provider requires it (for example, EU customers), the customer carries a contactVerification object and their email and phone must be VERIFIED before you submit for verification. Drive each channel with the send-then-confirm pairs (verify-email / verify-email/confirm and verify-phone / verify-phone/confirm) described in the Hosted flow’s “Verify email and phone” step. When contactVerification is absent, no contact verification is required.
2

Upload the identity document

Individual verification requires an identity document — a PASSPORT (single image), or a DRIVERS_LICENSE / NATIONAL_ID (uploaded as separate FRONT and BACK images via the side field). Some jurisdictions or currencies also request additional documents such as proof of address. Upload each one with POST /documents using multipart/form-data; identity documents also require documentNumber and issuingAuthority.
3

Submit for verification

Call POST /verifications to submit the customer for review. The response includes a verificationStatus. If anything is missing, verificationStatus is RESOLVE_ERRORS and the errors array describes exactly what to collect before retrying.
Submitted successfully:
Blocked by missing data:
4

Track the decision

Track terminal kycStatus transitions via the CUSTOMER.KYC_APPROVED / CUSTOMER.KYC_REJECTED webhook (recommended) or by polling GET /customers/{customerId}. CUSTOMER.KYC_PENDING also fires when the customer is submitted for review — subscribe to it if you want to surface an “under review” state. On APPROVED, unlock funding and money movement.

Monitor verification status

After a customer completes the KYC/KYB verification process, you’ll receive webhook notifications about their KYC status. These notifications are sent to your configured webhook endpoint.
For regulated platforms, customers are created with APPROVED KYC status by default.
Webhook Payload (sent to your endpoint):
Webhook Headers:
  • Content-Type: application/json
  • X-Grid-Signature: {"v": "1", "s": "base64_signature..."}
string
required
Unique identifier for this webhook delivery. Use this for idempotency to prevent processing duplicate webhooks.
string
required
Status-specific event type. KYC/KYB webhooks use CUSTOMER.* types:
  • CUSTOMER.KYC_APPROVED: Individual customer verification completed successfully
  • CUSTOMER.KYC_REJECTED: Individual customer verification was rejected
  • CUSTOMER.KYC_PENDING: Individual customer is awaiting review
  • CUSTOMER.KYB_APPROVED / CUSTOMER.KYB_REJECTED / CUSTOMER.KYB_PENDING: business equivalents (only fires for customerType: BUSINESS)
object
required
The full customer resource object, same as the corresponding GET /customers/{id} endpoint would return. Includes all customer fields such as id, kycStatus, fullName, birthDate, nationality, address, etc.
CUSTOMER.KYC_PENDING (or CUSTOMER.KYB_PENDING) fires when a customer enters kycStatus: PENDING (for example, after they are submitted for review). Final outcomes use CUSTOMER.KYC_APPROVED / CUSTOMER.KYC_REJECTED (and the CUSTOMER.KYB_* siblings for business customers).
Only customers with APPROVED status can create quotes and process conversions.

Customer types

For personal conversions and consumer wallets.Required fields: fullName, birthDate, addressConditionally required: email and phoneNumber are required in regions that verify contact information before identity verification (e.g., the EU).
For corporate conversions and business accounts.Required fields: customerType, plus businessInfo.legalName, businessInfo.country, businessInfo.taxId, and businessInfo.incorporatedOn. Most providers also require address for KYB.

Next steps