Skip to main content

Customers quickstart

Every end-customer must complete KYC in the customer vault. You get a stable customer_id (pcus_*) for quotes and accepts. Banking (IBAN, ledger, sends) is a separate optional product — see Accounts. KYC alone is enough for corridor ramps.
Inline customer on quote is deprecated (still supported during migration). Use customer_id once status=approved. See Quote and accept.

Two gates (do not confuse them)

Auth and environments

Production base: https://api.elementpay.net/api/v1 with is_live_… keys.
Live: after submit, Element Pay reviews and approves customers. Sandbox may auto-approve — still verify status via GET or webhooks.

Status model

Happy path

1

Requirements

GET /partner/customers/requirements
2

Create

POST /partner/customers with profile
3

Documents

Upload required categories
4

Submit

→ typically pending_review
5

Wait for approved

Prefer webhooks (customer.approved); poll GET /partner/customers/{customer_id} as backup until status=approved
6

Quote and accept

customer_id on POST /partner/orders/quote — required path for new integrations

1. Requirements

Collect the returned required_fields, required_documents, and any conditional_fields for the customer’s country.
Business nested fields: top-level required_fields lists "officers" only. Per-officer fields live under data.field_shapes.officers.item_shape. While the customer is incomplete, GET /partner/customers/{customer_id} returns missing[] with indexed paths (e.g. profile.officers[0].identity_document.number) — use that to drive your form.
Individual (always required before submit): besides name, contact, DOB, and gender, the vault package includes profile.address (line1, city, country), profile.id_number (government ID number), and profile.id_type (e.g. passport, national_id, drivers_license). Upload identity and address documents matching requirements. Business (required before submit): top-level company fields from required_fields, plus each profile.officers[] entry must include: Uploading officer identity and address document files is required, but does not replace the ID number and address in profile JSON. profile.industry must be plain language (e.g. Payment services, fintech) — not a numeric category code like 7372. Nigeria (country_of_residence: NG): also requires profile.additional_id_type (bvn) and profile.additional_id_number (11-digit BVN). Same rules apply on sandbox and live — call requirements on each environment; do not rely on copy-paste examples alone.

2. Create customer

Idempotent on partner_customer_ref per tenant. Call requirements first for the exact required_fields / required_documents for type=individual or type=business (and country when relevant).

Individual

Illustrative shape — GET /partner/customers/requirements?type=individual is source of truth. Include id_number and id_type before submit (omitting either returns 422 with profile.id_type or profile.id_number in missing[]).

Business

Illustrative shape — treat requirements and missing[] as source of truth. US-incorporated businesses also need tax_id (EIN). Each officer must be complete in profile JSON before submit (see table in Requirements). This is not a full UBO/shareholder program — at least one complete officer is required; if you send multiple officers, validate each. Quote / accept note: when you pass customer_id on quote for a business, we hydrate company fields only (legal_name → business_name, registration_number → business_id, email, country). Officer details are for vault KYC / deposit banking, not corridor quote party building.
Poll completeness while status is incomplete:
Example incomplete officer → missing includes profile.officers[0].identity_document.number until PATCHed. Save data.id (pcus_*). While incomplete: PATCH /partner/customers/{customer_id} with {"profile": { … }}. List: GET /partner/customers?status=incomplete&limit=50. Lookup by your ref: GET /partner/customers?partner_customer_ref=partner-cust-001.

3. Upload documents

JSON + Base64. category must match a requirements document key.

4. Submit

Incomplete package → 422 with data.code: package_incomplete and missing[] (e.g. profile.officers[0].identity_document.number, document.identity).

5. Wait until approved (webhooks + poll)

We send signed partner webhooks for vault lifecycle events (same key webhook_url / webhook_secret as orders). Typical events: Treat webhooks as the primary signal for review outcomes and banking readiness. Poll GET /partner/customers/{customer_id} as a backup if a webhook is delayed or missed. Full payload shapes: Webhooks.
Example:
Use customer_id on quote only when status == "approved".

6. Revoke (partner offboarding)

When an end-customer should no longer use Element Pay under your integration, call revoke. The vault case moves to suspended. There is no partner reinstate endpoint in v1 — create a new customer if the person returns later.

7. Quote and accept with customer_id

After status=approved, use customer_id on quote. Full response examples: Quote and accept. Discover network_id from catalog for the same country + order_type:
KE OnRamp (momo):
OnRamp quote ids are typically yc_receive_…. Use asset: { token, currency, network } — not a bare top-level "token".

Errors

Next