Onboarding

An onboarding session is Frame's hosted UI for collecting whatever a capability still needs to activate. Create the session for an account, redirect the account holder to the session URL, and Frame walks them through identity verification, document upload, and bank account setup — scoped to the capabilities that aren't yet active.

You don't build the forms. You don't store the documents. You hand off to a Frame-hosted flow and check the account when they come back.

When you need a session

Look at the capability's currently_due array. If it has entries, those are fields the account holder needs to supply, and an onboarding session is the easiest way to collect them.

Some common cases:

  • You created an account with kyc requested but no profile data. The KYC capability is pending and currently_due lists name, address, birthdate, ssn_last_four. Onboarding session collects all of it.
  • You're activating a payout flow. card_receive requires verified KYC plus an attached debit card. Session walks the user through both.
  • The account holder hasn't accepted your terms of service. Onboarding session can capture acceptance, IP, and user agent in the same flow as the rest.

If currently_due is empty across every capability, you don't need a session. The account is good.

How a session works

A session is a time-boxed handoff. The URL stays valid for the 30-minute window — the account holder can reopen it within that window if they need to — but expires after that and can't be revived.

  1. Create the session with account_id and (optionally) a return_url. The response contains a session url and an expires_at timestamp.
  2. Redirect the account holder to the session URL from your application. The URL is short-lived and tied to that specific session.
  3. Frame collects what's needed. The hosted flow scopes itself to exactly the requirements on file — KYC fields if kyc is pending, bank account verification if bank_account_receive is pending, terms-of-service capture if that's outstanding.
  4. Account holder completes (or exits) the flow. Frame redirects them to your return_url.
  5. Verify on your side. Retrieve the account and inspect the capability statuses. A redirect to return_url means the user clicked through — not that every requirement was met.

The steps array on the session tells you in advance which flows are bundled into this session (["kyc"], ["kyc", "bank_account_verification"], etc.) — useful if you want to surface progress or set expectations in your UI.

Expiry

Sessions expire 30 minutes after creation. If the account holder doesn't complete the flow in time, the session URL stops working — create a new session and redirect them again. The account itself is unaffected; only the session handoff is short-lived.

Don't share session URLs over email, SMS, or any external channel. Always redirect from within your authenticated application, since the URL grants access to the account holder's verification flow.

Incremental onboarding

You don't have to collect everything upfront. Common pattern:

  1. Account is created with just card_send (so they can pay).
  2. Months later they opt into a creator payout program. You request card_receive on the existing account.
  3. card_receive arrives pending with KYC and address verification in currently_due.
  4. Create a fresh onboarding session — Frame scopes it to only the new requirements, not what's already on file — and redirect.

Each session is a snapshot of "what's outstanding right now." Capabilities you've already activated stay activated.

Relationship to capabilities

Sessions are how requirements get satisfied; capabilities are what the account can do. The session itself doesn't "grant" anything. It collects data, runs verifications, and updates capability statuses as results come back. If you want a programmatic equivalent — supplying KYC fields via API instead of a hosted flow — you can update the account directly with the same fields, but you'll need to handle the document-upload and verification UX yourself.

Gotchas

Symptom: the account holder completed the session and was redirected back, but the account is still pending. Why: the redirect fires when the user clicks through, not when every check resolves. KYC and bank verification can take seconds to minutes to settle. Fix: poll the account, or listen for account.activated, capability.activated, and capability.disabled webhooks rather than acting on the redirect alone.

Symptom: you created a second session before the first one expired and now the account holder has two URLs. Why: sessions don't auto-invalidate each other — both URLs remain valid until they expire individually. Fix: harmless, but if it's a problem, just send the latest URL and let the older one expire.

Symptom: the session URL works in test mode but the account holder hits a "session expired" page in production. Why: clock drift on either side, or the URL was generated more than 30 minutes before the user clicked it. Fix: generate the session immediately before redirecting, not at account creation time.

Reference

For the full session lifecycle, see POST/v1/onboarding_sessions.