Pay on behalf of (POBO)
Use POBO to create and onboard a distinct business customer that your approved merchant represents. The API covers business creation, agreement acceptance, KYB, and international payments in the entity's own name. POBO entities use on-chain funding; Naira funding is not available for them.
Keep POBO data server-side
All POBO API routes use your merchant API key, sent from your server in x-api-key, except the returned agreement URL. Keep keys and document data on your server; do not call these endpoints directly from a browser.
Integration flow
accepted.entityId.Every write requires an Idempotency-Key. Generate a new key for each logical
operation and reuse it only to retry the exact same request. The key must be
16–255 characters matching [A-Za-z0-9._:-]. Concurrent duplicates return
423 with Retry-After; using a completed key with changed data returns 409.
1. Create the business
curl -X POST "https://api.example.com/api/merchant/pobo/users" \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_MERCHANT_API_KEY" \
-H "Idempotency-Key: pobo-create-acme-20260922" \
-d '{
"businessName": "Acme US Inc",
"email": "ops@acme.us",
"phoneNumber": "2025550100",
"country": "US"
}'businessName and a valid email are required. When supplied, country is
an uppercase ISO 3166-1 alpha-2 code.
The 201 response includes a stable poboUserId, the business's public EVM
and SVM wallet addresses, and agreement.url:
{
"message": "POBO business created",
"response": {
"poboUserId": "pobou_3a2b1c0d4e5f",
"businessName": "Acme US Inc",
"country": "US",
"wallets": {
"evm": { "address": "0x…" },
"svm": { "address": "…" }
},
"agreement": {
"status": "pending",
"url": "https://api.example.com/api/merchant/pobo/agreements/<token>"
},
"kyb": {
"status": "agreement_pending",
"pendingRequirements": [],
"lastSyncedAt": null
}
}
}2. Accept and sync the agreement
Give agreement.url to the business representative so they can sign the agreement, then return to your app or webview. It is a protected redirect that expires after seven days and intentionally does not require an API key.
After it is accepted, refresh the status from your server:
curl -X POST "https://api.example.com/api/merchant/pobo/users/pobou_3a2b1c0d4e5f/agreement/sync" \
-H "x-api-key: YOUR_MERCHANT_API_KEY" \
-H "Idempotency-Key: pobo-agreement-sync-20260922"Continue only when response.agreement.status is accepted. If the original
link expires while it is pending, request a new one:
POST /api/merchant/pobo/users/:poboUserId/agreement/linkThat route returns a new agreement.url; it returns 409 if the agreement is
already accepted or no longer available.
You can list your businesses with GET /api/merchant/pobo/users or fetch one
with GET /api/merchant/pobo/users/:poboUserId. A POBO business belongs only
to the merchant that created it.
3. Build the KYB form
Do not hard-code company type, industry, title, identity document, or subdivision values. Fetch the current values and preserve their returned identifiers in your submitted payload:
GET /api/merchant/pobo/reference/company-types
GET /api/merchant/pobo/reference/industries/:country
GET /api/merchant/pobo/reference/job-titles
GET /api/merchant/pobo/reference/identity-documents/:country
GET /api/merchant/pobo/reference/subdivisions/:countryFor the country routes, pass an uppercase ISO alpha-2 code such as US.
Each response is { "message": "…", "response": [ … ] }.
Use returned values exactly: company.type, company.industry, person
position, address subdivisions, and identity-file type are validated
enumerations. The identity-document response also determines which parts are
valid for a person in that country. Submit one approved document-storage URL
for every required part (for example, FRONT and BACK) in identity_files.
4. Submit KYB
Submit a complete application only after agreement acceptance:
POST /api/merchant/pobo/users/:poboUserId/onboardingThe payload must include:
company: registration, address, activity, ownership, and funding details.associated_persons: exactly onerepresentativeand at least oneapplicant. Include their contact, address, identity information, andidentity_files.company_files: all six file groups listed below.
{
"company": {
"name": "Acme US Inc",
"business_name": "Acme",
"registration_number": "REG123456",
"country": "US",
"incorporation_date": "2020-01-01",
"type": "corporation",
"description": "Software publishers",
"industry": "software_publishers",
"register_address": {
"street": "100 Market St",
"city": "Richmond",
"state": "VA",
"postal_code": "23218"
},
"business_address": {
"street": "100 Market St",
"city": "Richmond",
"state": "VA",
"country": "US",
"postal_code": "23218"
},
"phone_country_code": "US",
"phone_number": "2025550100",
"email": "ops@acme.us",
"url": "https://acme.us",
"has_bearer_shares": false,
"purpose_of_registration": "receiptAndPayment",
"estimated_number_of_transactions": 100,
"estimated_amount_of_transactions": 50000,
"country_of_operation": ["US"],
"has_vasp_relationship": false,
"source_of_funds": "BUSINESS_INCOME",
"transfers_funds_for_clients": true,
"compliance_screening_explanation": "Funds are settlement proceeds from merchant sales.",
"tax_id": "123456789"
},
"associated_persons": [
{
"type": "representative",
"first_name": "Ada",
"last_name": "Smith",
"id_type": "PASSPORT",
"id_number": "A1234567",
"birthday": "1990-01-01",
"gender": "F",
"nationality": "US",
"position": "<value from /reference/job-titles>",
"residential_address": {
"street": "200 Pine St",
"city": "Richmond",
"state": "VA",
"country": "US",
"postal_code": "23219"
},
"permanent_address": {
"street": "200 Pine St",
"city": "Richmond",
"state": "VA",
"country": "US",
"postal_code": "23219"
},
"phone": { "country": "US", "number": "4155550101" },
"email": "ada@acme.us",
"identity_files": [
{
"file_type": "<value from /reference/identity-documents/US>",
"part": "FRONT",
"country": "US",
"file": "https://<your-convex-deployment>.convex.cloud/api/storage/<document>"
}
]
}
],
"company_files": [
{
"file_type": "corporate_registration_documents",
"files": [
"https://<your-convex-deployment>.convex.cloud/api/storage/<document>"
]
}
]
}The example abbreviates required company file groups. A complete submission
must include all of these file_type values:
corporate_registration_documentsdocuments_of_corporate_governance_and_amendmentcertificate_of_incumbencyproof_of_residential_address_of_the_uboproof_of_business_operating_addressorganization_chart
Send each document as an approved document-storage URL. Each document must be a
supported PDF or image between 100 KB and 8 MB. All documents in one request
may total up to 50 MB. A successful submission returns 202.
Use a POBO contact email that can receive verification updates.
5. Fetch and correct KYB
GET /api/merchant/pobo/users/:poboUserId/onboardingFetch or poll while response.kyb.status is processing. Status values are
agreement_pending, not_started, processing, action_required,
verified, and declined.
When the status is action_required, send only the requested corrections using:
PATCH /api/merchant/pobo/users/:poboUserId/onboardingIf a correction includes company, send only the changed company fields. Do
not send blank placeholders for fields that have not changed.
You may omit associated_persons when no person details are changing. Any
supplied associated_persons array must still include exactly one
representative and at least one applicant. You may also omit company_files
when no documents are changing; for a document correction, send only the
replacement file group(s). Each replacement must be a supported PDF or image
between 100 KB and 8 MB. Corrections submitted in another KYB state return
409.
6. Create an international payment in the entity's name
Use the standard quote endpoint. When creating the intent, add the POBO
business ID as entityId; the payment is then sent in that entity's name.
{
"quoteId": "quote_...",
"quoteOptionId": "option_...",
"entityId": "pobou_...",
"fundingMethod": "onchain",
"fundingNetwork": "arbitrum",
"fundingAsset": "USDC",
"invoiceUrl": "https://merchant.example/invoices/INV-1042.pdf",
"paymentInstructionsUrl": "https://merchant.example/instructions/INV-1042",
"destinationPayload": {}
}Only supported funding networks can be used. The currently
compatible pairs are Arbitrum (USDC or USDT), and Base, Polygon, Arc, or
Solana (USDC). Funding begins after three minutes. Check the intent while its
status is processing.
If a response requests retry_funding, top up the selected entity wallet and
call POST /api/merchant/international-payment-intents/:intentId/retry-funding
with a new Idempotency-Key.