Check the requirements
Endpoint:GET /crypto/onramp/{serviceProvider}/requirements
Returns everything standing between this customer and an accepted order with that provider: agreements to sign, contacts to verify, and KYC still outstanding.
What comes back, and what to do
Four things, independent of each other. A customer can be through KYC and still be blocked on an unaccepted agreement. Work through them in the order below, then re-check.Legal agreements
Terms this provider wants the customer to see before it will take the order.url in your own UI and gate your own flow on the customer accepting. An empty array means there is nothing to show.
Some providers, Coinbase for one, also need the acceptance on record. Then verificationRequirements.agreement lists the codes the customer must accept and how long an acceptance counts, and customerStatus.agreement shows what is unmet:
-
One receipt per code. Call
POST /accounts/terms-of-service/acceptancesfor each code:ipAddressis the IP the customer accepted from, and it is required. Use theexternalCustomerIdof the customer you will order for: Meld creates a new customer for a value it has not seen. A customer without anexternalCustomerIdcan’t hold receipts, and its agreement readsUNRECORDABLE. -
An acceptance time on the order. Send
verification.agreementAcceptedAton the create request: the ISO-8601 instant the customer accepted. Keep your own record of who accepted what, and when.
agreementAcceptedAt. An acceptance counts for maxAgeDays; after that, show the documents again.
Contact verification
Whether the provider wants the customer’s email or phone confirmed by a one-time code. Two keys work together:verificationRequirements is what the provider asks for, customerStatus is how far this customer has got.
satisfied is about verification, not about whether the value is on the customer. MISSING means never verified — the customer may well have an email on record. A customer with no value at all has to have one set on the customer before there is anything to verify.
Verify only the channels that are required and not yet satisfied:
POST /accounts/customers/{customerId}/verifications, then POST /accounts/customers/{customerId}/verifications/{verificationId}/confirm
See Email and phone verification.
When verificationRequirements.verifyWith names a serviceProvider, send that serviceProvider on the verification request. A code verified without it doesn’t count for that provider.
STALE and VOIP both describe a customer who has verified before. A bare “verify your phone” reads as a bug to them unless you explain it.
On VOIP. A phone number has a line type — mobile, landline, or a virtual number from an internet calling service. A provider that sets requireLineType: "MOBILE" will not accept the last two, because a number anyone can mint for free is weak evidence of who the customer is. The reason is named after the common case rather than the rule: it means “not the line type this provider requires”, so it would also cover a landline.
It only fires when the line type is actually known. An unscreened number is left alone instead of being refused; otherwise a requireLineType policy would fail every customer. That makes VOIP rare in practice, and a provider that cares usually enforces its own rule on its side instead, so a number can still be refused later without this ever appearing. Expect MISSING and STALE.
KYC requirements
One entry per KYC step this provider needs, each reported independently.
Collect everything in
missingFields across all requirements in one pass, then send it as serviceProviderDetails on:
PATCH /accounts/customers/{customerId}/kyc/initiate
PATCH, not POST. The customer already has a KYC session by this point — POST starts one. This adds the provider’s own extra details to the session that exists. See Unified KYC for the modes and the payload.
Reading status
Two of these are easy to get wrong.
PENDING is not failure. Treating it as REQUIRED sends the customer back through a form they have already filled in, and some providers review asynchronously, so it can last minutes.
BLOCKED is not retryable. Re-submitting will not clear it. It is provider-specific, so the other providers in the quote are usually still open.
Provider processes
Some requirements are cleared by a process the provider runs, such as Coinbase’slimitUpgrade, which raises a customer’s limit. The requirement names the process, and the order is refused with 422 CUSTOMER_NOT_PAYMENT_READY until it completes.
Run it from your backend, with the customer and the same order intent you checked:
Endpoint: POST /crypto/onramp/{serviceProvider}/processes/{process}
READ returns the process status and the inputSources it accepts. Send operation: START with one of them as inputSource:
HOSTED_FORMreturnshostedForm.url, a provider page for the customer to complete beforehostedForm.expiresAt. Never log or store it.CUSTOMER_KYCsends the provider details from the customer’s Unified KYC. It is refused with403 KYC_NOT_COMPLETEDif those details are missing.
READ every process.pollIntervalMs while pollable is true, and resend the order once status is SATISFIED. PENDING means the provider is still reviewing: stop polling after process.pollTimeoutMs and check eligibility later. BLOCKED and UNAVAILABLE mean the provider won’t proceed: offer another provider. Never retry START automatically.
Re-check before you create the order
Call the endpoint again with the same five order parameters. Submitting is not the same as satisfied: a provider may still be reviewing, andPENDING will not accept an order.