KYC
Know Your Customer (KYC) verifies that an individual account holder is who they say they are. It's a regulatory and fraud-prevention primitive: collect a legal identity, match it against authoritative sources, confirm with a document and a selfie, and produce a binary outcome you can act on. Frame models KYC as a capability on an account — you request it, Frame runs the checks, and any downstream payment capability that depends on a verified identity activates automatically.
KYC is for individual accounts only. Businesses follow KYB (Know Your Business), which Frame runs against the legal entity while onboarding each owner or controller as a separate individual account in parallel.
When you need KYC
Request the kyc capability when your flow requires a verified identity. The two common cases:
- Paying funds out to an individual.
card_receiveandbank_account_receiveboth depend on completed KYC. Frame won't push money to an unverified person. - Running age-restricted flows.
age_verificationand other compliance capabilities build on top of KYC.
If you request card_receive, bank_account_receive, or creator_shield on an account, Frame includes kyc automatically — you don't have to ask for it separately. Request kyc directly when you need identity verification independent of any payment capability (e.g., for compliance threshold enforcement on your platform).
Buyers paying you through hosted checkout don't need KYC. The card_send capability activates on a payment method alone; verifying every buyer's identity would be excessive friction for the case where you only need to charge their card.
Required information
To complete KYC for an individual account, Frame needs:
| Field | Where it lives on the Account |
|---|---|
| Legal first name | profile.individual.name.first_name |
| Legal last name | profile.individual.name.last_name |
| Phone number | profile.individual.phone |
| Date of birth | profile.individual.birthdate |
| Residential address | profile.individual.address |
| Last 4 of SSN | Collected during the onboarding session and stored encrypted; only ssn_last_four is returned via the API |
Anything you have at account-creation time, prefill — Frame won't re-collect it during the hosted flow. Fields you don't have are surfaced in the capability's currently_due array; the onboarding session then collects them through Frame-hosted UI.
The flow
KYC is gated by a hosted onboarding session — Frame owns the UX, you own the redirect points. The shape:
- Create the account with
kycin thecapabilitiesarray and any identity fields you already have. - Create an onboarding session for the account. Frame returns a URL.
- Redirect the account holder to that URL. The hosted flow walks them through:
- Consenting to the identity verification process.
- Confirming any additional fields Frame couldn't prefill from your input (last 4 of SSN, address corrections, etc.).
- Handle the return. Frame redirects the account holder to your
return_urlwhen they finish. The redirect fires when the user clicks through — not when the verification has resolved. Document verification runs asynchronously and can take seconds to minutes. - Confirm activation. Subscribe to the
capability.activated(success) orcapability.disabled(failure) webhook, or poll the account'skyccapability status until it settles. Don't act on the redirect alone.
KYC resolves from data alone. Frame matches the identity fields against authoritative sources and returns a decision — no document, no selfie. Document capture is a separate step that runs only when the data checks cannot reach a decision.
Walk-through with code: Run KYC.
When KYC asks for a document
Some identities do not resolve from data. A thin credit file, a recent address change, or a name that authoritative sources hold differently all produce an inconclusive result rather than a pass or a fail. Frame does not decline these account holders. It asks them for a government ID instead.
When that happens, Frame requests the idv capability on the account and fires a capability.requested webhook. The kyc capability stays pending — it has not failed, it is waiting on the document.
An onboarding session picks the step up on its own. A session derives its steps from the account's outstanding requirements on every request, so an account holder still in the flow when the step-up fires sees an ID verification step appear. You don't create it, name it, or configure it.
That covers the common case, because KYC usually resolves while the holder is still in the session. Handle the other case explicitly:
- Handle the
capability.requestedwebhook. The payload names the account and theidvcapability. Treat it as "this account holder has more to do," not as an error. - Check whether their session is still live. Sessions carry an expiry. If the holder is still in an unexpired session, they are already looking at the new step and you need to do nothing.
- Create a new onboarding session only if the old one has expired — or if the holder left before the decision landed. Redirect them back to the new URL.
- Confirm activation the same way you do for KYC: wait for
capability.activatedonkyc. A passing document resolves the original KYC check, and the downstream payment capabilities activate behind it.
KYC resolves asynchronously, so the decision can land after the account holder has closed the tab or after the session has expired. That is what the webhook is for — it's your signal to bring them back, whether or not they were still on screen.
Budget for this branch before you go live. An integration that treats every non-active KYC as a failure strands the account holders who only needed to show an ID.
Outcomes
The kyc capability uses the standard capability lifecycle. The states that matter in practice for a KYC flow you've requested:
active— Frame matched the identity against authoritative sources, and any document it asked for passed. The account holder is verified. Any payment capabilities that depended on KYC activate automatically.disabled— verification failed. Look at the capability's associated error records for the failure category (document quality, identity mismatch, etc.) where shareable. Your application should surface a remediation path: retry, request manual review, or decline service per your platform's policy.pending— Frame is still waiting on something. Either a back-channel check has not resolved, or the identity did not resolve from data and Frame is waiting on a document. Check whether the account carries anidvcapability: if it does, the account holder has an outstanding step, not a stalled check. Stay subscribed to the capability webhook either way.
unrequested and ineligible are also valid states on a capability — see the capabilities concept — but for KYC the common path is pending → active or pending → disabled.
Outcomes are not predictive — a disabled KYC for one account holder doesn't say anything about a different one, even with similar fields. KYC is identity verification, not risk scoring.
Re-verification
KYC isn't a one-shot. If an account holder's information changes (legal name change, new address) or your platform's compliance policy mandates periodic refresh, update the profile fields. Frame re-evaluates the kyc capability against the new data automatically. If the update introduces fields Frame can't reconcile against the existing verified record (e.g., a substantially different document), the capability transitions back to pending and a fresh onboarding session collects what's needed.
The previous KYC result isn't "lost" — Frame tracks the verification history on the account. The capability surface reflects the current state.
Scope — what KYC checks
KYC verifies the legal identity claim:
- The name, SSN last 4, address, and date of birth reconcile against authoritative sources.
- The identity belongs to a real person, and that person is not deceased.
- The identity shows no signal of synthetic or stolen construction.
When those checks resolve the identity, KYC is done. When they cannot, the idv capability adds a document layer on top:
- The document is authentic (not forged, not visibly tampered).
- The selfie is a live person, not a static image.
- The selfie face matches the document photo within Frame's matching threshold.
KYC does not check:
- Whether the person is on a sanctions list (that's separate compliance work, run alongside).
- Whether the address is currently valid (that's
address_verification). - Whether the phone is reachable (that's
phone_verification). - Whether the person is of legal age for a regulated activity (that's
age_verification, which builds on KYC).
Treat KYC as the foundation: it verifies identity, and the other compliance capabilities verify specific attributes of that identity.
Platform scope
In V1, Frame's KYC flow is delivered through frame-js (the web SDK) plus a server-side onboarding session you create from your backend. The hosted verification UI loads on os.framepayments.com and walks the account holder through document capture in the browser or mobile browser. Native mobile SDK integration (React Native, iOS, Android) is on the roadmap — if you need KYC inside a native mobile app, talk to Frame support about the current options.
Gotchas
Symptom: the account holder completed the session and was redirected back, but the kyc capability is still pending. Why: Frame's redirect fires when the user clicks through, not when document analysis resolves. Verification can take seconds to minutes. Fix: listen for capability.activated / capability.disabled webhooks; treat the redirect as "they finished entering data," not "verification passed."
Symptom: you requested kyc plus card_receive on a new account and only kyc shows up pending in the response. Why: Frame stages dependent capabilities — card_receive won't be evaluated until kyc activates. The capability still exists on the account, just not surfaced until its prerequisites resolve. Fix: once kyc transitions to active, retrieve the account again and you'll see card_receive listed and being evaluated.
Symptom: the kyc capability sits pending indefinitely, and the account has grown an idv capability you never requested. Why: the identity didn't resolve from data, so Frame requested a government ID. The account holder has an outstanding step and nothing is going to move until they complete it. Fix: handle the capability.requested webhook, create a fresh onboarding session, and redirect the account holder back into it. See When KYC asks for a document.
Symptom: you sent the account holder back to their original onboarding session URL for the step-up and the link no longer works. Why: onboarding sessions expire, and KYC can resolve after the holder has left. The step itself is fine — a live session would have shown it — but the session is gone. Fix: create a new onboarding session for the account and redirect them to that URL.
Symptom: a KYC verification passes for one account holder and fails for a similar-looking one. Why: document quality, lighting, and the matching threshold are all stochastic. KYC is identity-level, not risk-level — small data differences yield different outcomes. Fix: surface a remediation path (re-submit with clearer photos, manual review) rather than treating the failure as final.
Reference
For the full API surface, see POST/v1/accounts and POST/v1/onboarding_sessions.