Run KYC
This guide covers running KYC for one of your customers — a buyer, a seller, or any platform user whose identity you need verified. KYC is one of Frame's capabilities, so the shape is: request the kyc capability on the customer's Account, run them through an onboarding session, check the capability status when they return.
Prerequisites
| Requirement | Details |
|---|---|
| Frame API key | Secret key for server-side calls. |
| Customer profile data | At minimum: name and email. KYC additionally collects address, date of birth, and last 4 of SSN — you can prefill these if known, or let the onboarding session collect them. |
| Return URL | A URL on your application where Frame redirects after the session. |
When to run KYC
Request the kyc capability when you need to know the person is who they claim to be — typically before:
- Paying them out (
card_receive,bank_account_receiveboth depend on completed KYC). - Running age-restricted flows (
age_verificationbuilds onkyc). - Hitting a compliance threshold in your platform's rules.
Buyers paying you through hosted checkout don't need KYC by default — card_send activates without it. Don't request KYC unless the flow needs it.
1. Create the account or attach KYC to an existing one
If the customer doesn't have a Frame account yet, create one with kyc in the capabilities array. If they already have an account (because they've paid you before), add the kyc capability via POST /v1/accounts/:id/capabilities.
New customer. Pass kyc alongside whatever else the customer needs. Prefill name, email, phone — these aren't enough to complete KYC on their own, but they speed up the hosted flow and reduce drop-off.
curl --request POST \
--url https://api.framepayments.com/v1/accounts \
--header 'Authorization: Bearer SECRET_KEY' \
--header 'Content-Type: application/json' \
--data '{
"type": "individual",
"capabilities": ["kyc"],
"external_id": "user_42",
"profile": {
"individual": {
"email": "alex@example.com",
"name": {
"first_name": "Alex",
"last_name": "Chen"
},
"phone": {
"number": "4155551234",
"country_code": "1"
}
}
}
}'
Existing account. Request the new capability against the capabilities sub-resource. Frame evaluates the requirements against whatever data is already on file — if everything's there, KYC activates immediately. If anything is missing, currently_due lists it.
Note: capabilities are not added by patching the account itself — there's a dedicated POST /v1/accounts/:id/capabilities endpoint for this. Profile updates use PATCH /v1/accounts/:id; capability requests use the sub-resource.
curl --request POST \
--url https://api.framepayments.com/v1/accounts/99c6b0da-.../capabilities \
--header 'Authorization: Bearer SECRET_KEY' \
--header 'Content-Type: application/json' \
--data '{
"capabilities": ["kyc"]
}'
2. Check the kyc capability status
Look at the capabilities array on the response. If kyc is active, you're done — the customer is verified and you can move on. If it's pending, inspect currently_due to see what's left.
{
"name": "kyc",
"status": "pending",
"currently_due": [
"profile.individual.address",
"profile.individual.birthdate",
"profile.individual.ssn_last_four"
]
}
For KYC, expect at least address, birthdate, and last 4 of SSN to be outstanding — Frame doesn't accept those on the create call by default (SSN especially is encrypted and only collected through the hosted flow).
3. Create an onboarding session
The session is scoped automatically to whatever currently_due reports across all pending capabilities. If the only outstanding capability is kyc, the session collects only KYC fields.
Pass account_id and return_url. The session is valid for 30 minutes after creation — the URL can be reopened within that window if the customer bounces off mid-flow — so create it immediately before redirecting.
The response steps array confirms which flows the session covers (e.g. ["kyc"]). Useful if you want to show progress in your UI.
curl --request POST \
--url https://api.framepayments.com/v1/onboarding_sessions \
--header 'Authorization: Bearer SECRET_KEY' \
--header 'Content-Type: application/json' \
--data '{
"account_id": "99c6b0da-...",
"return_url": "https://yourapp.com/kyc/complete"
}'
4. Redirect and let Frame run the flow
Redirect the customer to session.url. Frame's hosted UI collects identity fields, runs document verification, and updates the kyc capability as results come back. The customer is redirected to your return_url when they finish or exit.
window.location.href = session.url;
5. Confirm KYC activated
The redirect doesn't guarantee KYC passed. Verify by retrieving the account and inspecting the kyc capability's status.
For production, subscribe to capability.activated and capability.disabled webhooks rather than polling. Frame fires capability.activated when KYC transitions to active, and capability.disabled if verification fails. The webhook payload includes which capability changed and its new status.
A KYC failure is rare but real. If the capability transitions to disabled with a populated disabled_reason, the verification did not pass — surface a remediation path in your UI (re-collect data, contact support).
curl --request GET \
--url https://api.framepayments.com/v1/accounts/99c6b0da-... \
--header 'Authorization: Bearer SECRET_KEY'
async function waitForKyc(accountId) {
for (let i = 0; i < 10; i++) {
const account = await getAccount(accountId);
const kyc = account.capabilities.find(c => c.name === 'kyc');
if (kyc.status !== 'pending') return kyc;
await sleep(2000);
}
throw new Error('kyc still pending after timeout');
}
Re-verification
KYC isn't a one-shot. If a customer's information changes (legal name change, new address) or your platform's compliance policy demands periodic refresh, update the profile fields and the kyc capability re-evaluates automatically. If the update introduces fields Frame can't verify against the existing record, the capability transitions back to pending and a fresh onboarding session collects what's needed.
Next steps
- For the payout-recipient pattern (where KYC is a prerequisite to
card_receive/bank_account_receive), see Pay out to an account. - For the full identity verification model — what KYC checks against, what document types are accepted, how failures surface — see KYC concept.