Create a funding session
Returns an Apple Pay / Google Pay payment link for the amount you specify. Show it in your UI; when the user completes the payment the funds land in their wallet. The link is single-use and expires after 30 minutes. Requires a phone verification fresh within 60 days — see POST /api/v2/wallet/phone/start.
How it works
Ask for a funding session for an amount; we return acheckout_url. There are two kinds, picked with link_type:
hosted(default): an Agentcard-hosted payment page. Render it anywhere — an “Add funds” button, a QR code, a chat message — and the user opens it and pays with Apple Pay, Google Pay, or card. Safe to relay: the underlying payment order is created only when the user opens the page. Creating a hosted session is free; an unopened link costs nothing.embedded: an in-app payment link, minted immediately. Loadcheckout_urlin aWKWebView(iOS) or Android WebView and the user pays without leaving your app.
GET /api/v2/wallet/fund/{session_id} to know when — that endpoint is the source of truth for money; treat any client-side signal as advisory.
Fees: send the exact amount
Agentcard covers the payment provider’s fee. Sendamount_cents for exactly what the user should receive — the wallet is credited the full amount. Do not gross up the charge to compensate for fees; that just over-charges your user.
fee_centson the create and status responses is the provider’s fee (which Agentcard absorbs) when known, ornullwhile it isn’t yet —nullmeans “unknown”, never “free”.fees_coveredtells you whether the fee is on us:true(it is — the user receives the fullamount_cents),false(an anomalous fee we won’t absorb — the wallet receives the net amount), ornull(fee not known yet).falseis rare; treat it as net delivery rather than failing the flow.
Requirements
- The user must be identity-verified. Funding reuses the user’s completed identity verification — there is no separate verification step inside checkout. If the user isn’t verified, create-session returns
422 kyc_required; run identity verification first, then retry. Other verification-related 422s:funding_profile_required— a one-time funding profile is missing (collect it, then retry).kyc_transfer_required— the user’s existing verification needs a one-time carry-over before funding (a single extra step, no re-verification).unsupported— the user’s verification can’t be used for funding (for example, a non-US user).
- Amount bounds come from the API. If the amount is out of range you get
422 amount_out_of_rangewithmin_amount_centsandmax_amount_centsin the response — read those rather than hardcoding limits. - Link lifetime.
hostedandembeddedlinks both stay openable for the session’s 30-minute window.
Embedded: in-app checkout
Create the session withlink_type: "embedded", hand checkout_url to your app, and load it in a WebView:
- Apple Pay renders inside a
WKWebViewon iOS 16+ (Apple Pay on the Web is supported inWKWebView, but not inSFSafariViewController— use aWKWebView). On older iOS the user pays with Google Pay or card. No domain verification is required on your side; the checkout runs on our Apple-registered domain and pops the native Apple Pay sheet in-app. - Google Pay works in a modern Android WebView; card is always available as a fallback.
- Completion: the page navigates to
/fund/successwhen the payment completes — observe that navigation to close your WebView — and the status endpoint is the authoritative confirmation. - Wallet-only sheet: append
&only=apple_pay(or&only=google_pay) to thecheckout_urlfragment to present just that wallet button with no card form.
Mint on demand, not per render
Every embedded session creates a real payment order the moment you call the endpoint. Mint one only when the user has actually initiated payment (tapped “Add funds”), render it immediately, and create a fresh session for the next attempt if the link lapses. Don’t mint on page render or in retry loops — the API refuses excess pending sessions for the same user withtoo_many_pending_sessions.
- Never relay an embedded link through chat or email; link unfurlers can consume it and leave the user a dead page. Server → WebView, immediately, is the only safe path.
- The embedded
checkout_urlappears only on the create response; the status endpoint never re-serves it. If it lapsed, create a new session. - Test with sandbox-mode credentials — sandbox clients create TEST orders (never charged), so you can exercise the full WebView flow end to end before switching to live keys.
- On a physical device, cards must be in the platform wallet; simulators cannot show the Apple Pay sheet.
Authorizations
A platform access token. Get one on the Create an access token endpoint by exchanging your client_id + client_secret, then send it as Authorization: Bearer <token>. Tokens live one hour.
Body
The connected user's id.
Amount to fund, in USD cents.
google_pay with link_type "embedded" is accepted when the user's rail returns the web checkout style; on web rails embedded is Apple Pay only (422 payment_method_not_supported).
apple_pay, google_pay hosted returns an Agentcard-hosted payment page, safe to relay anywhere (chat, email, QR); the underlying payment order is created only when the user opens it, so unopened hosted sessions cost nothing. embedded creates a REAL payment order immediately for rendering inside your own app; mint it only when the user initiates payment, render it immediately, and never relay it through chat (link unfurlers consume it). Embedded responses carry checkout_style (crossmint_sdk | cb_onramp | web) — branch your rendering on it: crossmint_sdk boots Crossmint's native mobile SDK from the response's crossmint object (native Apple Pay / Google Pay sheet in-app), cb_onramp loads checkout_url in a WKWebView with the cbOnramp message handler (Apple Pay only — google_pay on that rail is rejected with payment_method_not_supported; the link lives about 5 minutes and counts toward the user's per-user payment limits even if never paid), web opens checkout_url in a browser context. Sandbox-mode credentials create TEST orders (never charged).
hosted, embedded Response
The funding session, with the payment link to show the user.
"funding_session"pending, processing, completed, failed, expired apple_pay, google_pay The payment link to show the user. hosted: an Agentcard-hosted page, present while the link can still be opened. embedded: the raw provider Apple Pay link, present ONLY on the create response; the poll endpoint never re-serves it, so load it in an in-app webview immediately, never relay it, and create a new session if it lapses.
region_not_supported, provider_error, null On the create response: hosted links stay openable for 30 minutes; embedded links are single-use and expire about 5 minutes after creation (create a new session instead of retrying a lapsed link). On the poll endpoint, expires_at always reflects the session's 30-minute fundability window, not the embedded link's shorter life.
Which kind of checkout_url this session carries. Returned only on the create response; the poll endpoint does not include it.
hosted, embedded The payment provider's fee in USD cents, which Agentcard covers (see fees_covered) — the user's wallet is credited the full amount_cents, so do NOT gross up the charge. Null while the fee isn't known yet (e.g. a hosted link whose payment order hasn't been minted) — null means unknown, never free. Always present on both the create response and the poll endpoint.
Whether Agentcard absorbs the provider fee for this session. true: the wallet receives the full amount_cents — send the exact amount the user should receive and do not gross up. false (rare): the fee was anomalous and the wallet receives the net amount. null: the fee isn't known yet. After completion this reflects the actual outcome.
Embedded create responses only — which rendering contract applies. 'crossmint_sdk': initialize Crossmint's native mobile checkout SDK with the crossmint object (native Apple Pay / Google Pay sheet in-app; checkout_url stays a web fallback). 'cb_onramp': load checkout_url in a WKWebView with a script message handler named cbOnramp (native Apple Pay button page with lifecycle events). 'web': open checkout_url in a browser context; the page navigates to /fund/success on completion. Treat unrecognized values as 'web'.
crossmint_sdk, cb_onramp, web Embedded create responses on the crossmint_sdk style only — the PREFERRED integration. A fully-built, provider-opaque wallet-button page: load it as-is in an in-app webview (Agentcard's iOS tooling renders it as a native-looking Apple Pay button pill). Built entirely server-side, so the payment rail behind it can change without any partner-side work. Same one-time, single-order lifetime as the credentials it embeds.
Embedded create responses on the crossmint_sdk style only. Boot credentials for Crossmint's native checkout SDK (Swift / Kotlin / React Native) — an alternative to embed_url for apps that prefer the vendor SDK. client_secret is scoped to this single order and is returned exactly once — hand it to the paying user's device, never store or relay it; create a new session if it is lost.