Embedded Onboarding Integration Guide
Create a sub-merchant, mint an embed session from your backend, embed Coinflow’s onboarding in an iframe, follow progress and handle information requests.
This guide walks through a complete embedded onboarding integration, in the order you’ll build it. Complete Partner Setup first, and read the security rules and rules for handling future changes before you start.
The examples use sandbox URLs. In production, use the production equivalents:
Values such as acme-store, owner@acme.example.com and
https://app.example.com are examples only. Replace them with your own.
The curl examples read your API key from the COINFLOW_ADMIN_API_KEY or
COINFLOW_API_KEY environment variable.
Create and pre-fill a sub-merchant
Call Create Submerchant from your backend when a business signs up for payments on your platform.
merchantIdis your identifier for the sub-merchant: 3 to 50 letters, numbers and hyphens, unique across Coinflow. It’s stored in lowercase, so on every later call for this sub-merchant, send themerchantIdreturned in the response as thex-coinflow-submerchant-idheader. Later lookups match the exact case.emailbecomes the sub-merchant’s account owner. Use a real inbox the business can open: Coinflow emails the account owner, for example a one-time code during settlement setup.- Every other field is optional. Anything you send is shown to the sub-merchant pre-filled, and they can change it. Some fields don’t apply to every sub-merchant; those are accepted and kept but not shown.
- Don’t send the
x-coinflow-submerchant-idheader on this call. It fails with a400.
Pre-fill fields
Unknown fields are rejected with a 400. The response returns the URLs as
separate fields (websiteUrl, websiteUrl2, …) and adds products,
derived from the pay-in and payout methods you sent.
Updating pre-filled details
Call Update Submerchant with only the fields you want to change:
- Fields you leave out keep their current values.
websiteUrlsanddevelopmentUrlsreplace the whole list. - Once the sub-merchant submits its application, updates fail with a
409.
Sub-merchant creation is limited to 30 per hour per API key. Past that,
requests fail with a 429 and "error": "CREATE_SUBMERCHANT_RATE_LIMITED".
Mint an embed session from your backend
When a signed-in user opens onboarding in your product, your backend mints an embed session for their sub-merchant with Create Embed Session and returns the token to your page.
parentOriginis the origin of the page that frames the iframe. It must be covered by an approved Whitelist URL. The iframe only posts events to this origin.expiresAtis in Unix seconds.
A minimal token endpoint in Node.js with Express:
Session lifetime and renewal
- Each token is valid for 15 minutes. The iframe renews its own token about 2 minutes before it expires, so you mint once per visit.
- A session can’t be renewed past 8 hours after it was minted. After that the iframe posts an
onboarding.errorevent with codesession_expired; mint a new token and reload the iframe. - A session stops working immediately if the sub-merchant is moved out of your account, either account is suspended, or the API key that minted it is disabled, deleted or downgraded below Admin.
If you call embed-session APIs directly, renew a token with Refresh Embed Session.
Embed the onboarding iframe
Load the onboarding page with the token in the URL fragment:
- The
allowattribute is required. Identity verification runs in a frame inside the iframe and uses the camera to capture ID documents and a selfie. A nested frame only gets the permissions every frame above it grants, so withoutcamerathe sub-merchant can’t verify. Includemicrophoneas well, since verification may request it.clipboard-writepowers the Copy link buttons used to share verification links with business owners. - Use the fragment, not a query string. The fragment is never sent to a server or leaked in
Refererheaders, and the iframe removes it from its address bar as soon as it loads. - Size it for one column. Onboarding shows one step at a time and works down to about 320px wide. Set the iframe’s height from
onboarding.heightChangedevents (next step) so it never shows its own scrollbar. - Don’t sandbox it unless the
sandboxattribute includesallow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox. Documents and terms open in a new tab, and withoutallow-popups-to-escape-sandboxthat tab inherits the sandbox and can’t display them.
The iframe only renders on approved sites. On any other site, or when the token is missing or invalid, it shows a “Not allowed” message instead.
Follow progress
You have three ways to follow a sub-merchant’s progress. Most integrations use all three.
Listen for embed events from your page:
Read the current status from your backend:
Onboarding statuses
Steps
steps lists only the steps that apply to this sub-merchant, in order. Each
step has a status of blocked (waiting on the steps in blockedBy),
action_required, in_review or complete.
While requirementsStatus is pending, more steps may be added once the
sub-merchant completes its profile. requirementsRevision increases each time
the list of steps is recalculated.
Handle information requests
After the sub-merchant applies, or at any time after it’s live, Coinflow’s underwriting team may send it a request for information (RFI). Coinflow doesn’t email the sub-merchant about these, so your platform must show them.
- Listen for the
Sub-merchant RFI Sentwebhook, or call List RFIs withactionRequired=true. - Mint an embed session for the sub-merchant, exactly as in step 2.
- Open the RFI in an iframe at
/embed/rfi/{rfiId}#token=EMBED_SESSION_TOKEN.
See Information Requests for the details.
Settlement step
When settlement options are enabled for your sub-merchants (see
Partner Setup),
onboarding includes a wallet step where the sub-merchant chooses where its
funds settle. It only offers the options enabled for that sub-merchant.
- The step never blocks submitting the application. After submitting, the iframe opens the first step still needing action, usually this one, and the overall
statusstaysaction_requireduntil it’s complete. - For a Coinflow-managed settlement account, Coinflow emails a one-time code to the account owner (the
emailyou created the sub-merchant with) and the sub-merchant approves the account in the iframe. If they leave part way through, the step offers to finish setup next time. - An external settlement destination can’t be changed after it’s set.
Identity verification
- Verification runs inside the iframe. If the sub-merchant’s device has no camera or it’s blocked, they may be offered the option to continue verification on their phone and come back.
- Verification is decided after the sub-merchant finishes. The step shows that verification was submitted, and they can carry on with the other steps. The application can be submitted once verification is approved.
- Verification links for other business owners can be copied from the iframe and shared with them.
Opening onboarding as a link
If you’d rather not host an iframe, you can send the sub-merchant to the same pages as a full page hosted by Coinflow:
-
Mint the session when the user clicks through, and redirect straight to the link. It’s the same 15-minute session as the iframe, so don’t email or store the link. Reloading the page needs a fresh link.
-
Omit
parentOriginto mint a link-only session. A link-only session refuses to load inside any iframe. A session minted withparentOriginworks both ways. -
Pass
returnUrlto show a Return to your platform button after the sub-merchant submits. Its origin must be covered by an approved Whitelist URL.With neither
parentOriginnorreturnUrl, minting doesn’t need any Whitelist URL. -
No embed events are posted when there’s no parent page. Follow progress with webhooks and Get Onboarding.
Testing in sandbox
- Complete Partner Setup in the sandbox dashboard, approving your local or staging origin.
- Create a sub-merchant in sandbox, mint a session and load the iframe from the approved origin.
- Point a sandbox webhook URL at your server to receive onboarding events.
Troubleshooting
Minting returns 400 about Whitelist URLs
parentOrigin (or returnUrl) isn’t covered by an approved Whitelist URL, or your account has none. Check the exact origin, including scheme and port, and that the request was approved. See Partner Setup.
Minting returns 401
The request wasn’t made with an Admin API key, or x-coinflow-submerchant-id names a merchant that isn’t one of your sub-merchants.
The iframe shows "Not allowed on this site"
A page framing the iframe isn’t on an approved origin. Every page in the frame chain must be covered by a Whitelist URL. A link-only session (minted without parentOrigin) shows “This link can’t be opened inside another site” when framed instead.
The iframe loads but no embed events arrive
Events are only posted to the parentOrigin the session was minted with. Check that it exactly matches your page’s origin, including scheme and port, and that your listener compares event.origin with the Coinflow onboarding origin for the environment.
The camera doesn't open during verification
The iframe is missing allow="camera; microphone; clipboard-write", or a frame above it doesn’t grant those permissions.
Updating a sub-merchant returns 409
The sub-merchant has already submitted its application. Pre-filled details can’t be changed after that.

