Skip to main content
link by stripe connects a user’s wallet through oauth and issues a payment credential for an approved purchase: a merchant-bound link pay token on supported stripe checkouts, or a single-use virtual card everywhere else. KERNEL inspects the checkout and chooses which one; you never choose or handle it. KERNEL’s native integration handles wallet connection, token refresh, approval actions, and card storage through vault items. oauth credentials and card material use kms-backed envelope encryption. use KERNEL’s fill api to safely inject the approved card’s values into an attached browser without passing them through your application’s injection code or model context. you provide references and selectors; KERNEL returns outcomes, not the values. link supplies the card, while fill is a KERNEL operation shared with other supported vault items. link is the wallet provider, not the merchant’s payment processor. a virtual card works on any checkout with supported, uniquely selectable card inputs, so the merchant’s processor doesn’t need to be stripe. a link pay token works only on stripe checkouts that expose link’s agent payment tools; KERNEL detects them during authorization. for the overall offering, see payments on KERNEL.

Before you start

link currently supports only users with US phone numbers.
create a project-scoped client and vault. the examples below use these kernel and vault variables.

Choose an oauth client

use KERNEL’s oauth client by default. if you bring your own client, complete the setup below before following the shared payment lifecycle. register a provider configuration once for your organization. configurations are shared across projects, so authenticate this step with an organization-scoped api key. project-scoped credentials can reference an existing configuration when creating a wallet, but can’t create, update, or delete configurations. keep the client credentials outside the agent’s accessible files. the SDK examples read them from backend environment variables. for the CLI, create a protected file readable only by its owner (for example, mode 0600):
link-client.json
for each end user, complete your existing link oauth flow in your backend and obtain its access and refresh tokens. keep the client secret, pkce verifier, and tokens out of agent context, browser code, urls, and logs. create the wallet with the project-scoped kernel client and vault from Before you start. supply the access and refresh tokens from the same grant, with a currently valid access token. CLI users should restore their project-scoped KERNEL_API_KEY before running the wallet command and put the grant in this protected file:
link-grant.json
a successful import returns a connected wallet without a link_oauth action. KERNEL takes over refresh-token rotation, so your backend must stop refreshing that grant. continue with Select a payment method.

Lifecycle

  1. connect a wallet: use KERNEL’s client and present the returned link_oauth action, or complete oauth in your backend and import the grant with your provider configuration.
  2. require the wallet to be connected.
  3. request the advertised payment_methods expansion and let the user choose an eligible method.
  4. reach the final checkout page in a browser with the vault attached, then create a card item with the purchase details. creating the card doesn’t contact link. to change the details before authorizing, update the card.
  5. retrieve the card, verify that it advertises authorize, and after explicit user approval invoke it with the browser’s browser_id and the checkout’s exact current top-level page_url. KERNEL inspects that checkout, chooses a link pay token or a virtual card, and sends the user an approval request.
  6. complete the returned spend_approval or push_approval action and wait for state.status to become ready.
  7. require the advertised fill operation and follow its description: a link pay token takes browser_id and page_url only, and a virtual card also takes field/selector bindings. inspect the fill outcome, then submit the checkout yourself once.
each item’s available_operations[].description describes the next step and its recovery, so have your agent read it rather than hard-coding the flow.

Connect a wallet

this section shows the KERNEL-managed oauth path. if you imported a connected wallet with your own client above, continue with Select a payment method. before showing a link connection option, list the vault’s items. if a link wallet already exists in any state, reuse it and do not let the user add another. show its existing action or status instead. the api makes item keys unique but does not currently enforce one wallet per provider, so the ui must enforce a maximum of one link wallet per vault. the examples use presentProviderAction, an application-owned function that publishes the action to an authenticated session for the end user who owns the vault. bind the action to that user, vault, and item; apply a short application ttl capped by wallet.expires_at when present; and stop serving it when the action changes or disappears. derive authenticatedUser from the server-side session, not a request field. do not log the url or put it in model context.
open collection and approval urls in a trusted user-facing surface. don’t give them to the agent or print full wallet responses into model context. run cli --open only from a trusted, human-operated terminal because the command output can contain the action url.

Select a payment method

request payment_methods only when available_expansions advertises it. the expansion comes from link at request time and is not persisted in the vault item.
show the returned methods in a trusted user-facing surface, let the user choose one, and set its id as LINK_PAYMENT_METHOD_ID. missing capability metadata means eligibility is unknown. only eligible: false is an explicit negative result.

Create and authorize a card item

create the card once the browser is on the final checkout page and you know the final amount, currency, and merchant. the examples use browser, a KERNEL browser created with this vault attached, and checkoutURL / checkout_url, the browser’s exact current top-level checkout url obtained through your browser-control method.
amount uses minor currency units, so 2306 means 23.06 usd. link accepts values from 1 to 500000, but a virtual card allows at most 50000. context must contain at least 100 characters. card creation is live-only, and spec.test is not supported. until you authorize the card at a checkout, you can change its spec with an update. after that, updates return 409: delete the card and create a new one with the updated details. authorization fixes how link delivers the credential: link resolves the merchant shown on the approval screen from the checkout’s stripe account, so a link pay token request doesn’t send merchant_name or merchant_url. the token is fetched fresh for each fill and never returned to you. don’t inspect or invoke the checkout’s webmcp tools yourself. KERNEL does that during authorize and fill. authorizing without browser_id and page_url still issues a virtual card that fills pages on the merchant_url origin. use it only as a fallback when checkout inspection keeps failing.

Authorization errors

these errors happen before any payment request is created, so the card stays requested and you can authorize again: if the user declines or the request expires, delete the card and create a new one. once approval has been requested, {"type":"authorize"} only re-checks the request and never creates another payment request.

Fill the checkout

after the user completes approval, retrieve the card with wait: 60. continue only when it is ready and advertises fill; one bounded wait may finish before approval does. the examples below show the fill request; for the full controller and agent handoff, follow the browser agent payments guide. the advertised fill description says which inputs the card needs. every fill supplies browser_id and the exact current top-level page_url. the browser must have the vault attached in the same project, and the card must remain ready, unexpired, and undeleted with its parent wallet. a link pay token fill also requires that wallet to be connected, because the token is retrieved with it. timeout_ms is optional. page_url must use https without embedded credentials and must be on the origin of the checkout page you authorized at, or on the origin of spec.merchant_url for a card authorized without a checkout. the origin comparison includes the host and port (default 443 is normalized); it does not allow other subdomains. the path can differ, so a fill still works after the checkout moves to another page on the same origin, but the request must name the exact current page. a disallowed origin returns 403 destination_denied. descendant payment frames can have different origins; the restriction applies to the top-level merchant page. omit fields. KERNEL selects card on the checkout if needed, checks that the checkout’s stripe account is the one the user approved, retrieves a fresh token, and passes it to the checkout’s link tools. on stripe checkouts, the card form is replaced by the user’s link payment method.
a different stripe account on the page returns 403 destination_denied, and nothing is passed to the page. KERNEL checks the account before retrieving the token and again before passing it.

Fill a virtual card

supply ordered fields bindings. combined expiration requires format: "MM/YY" or "MM/YYYY".

Map card fields to inputs

the examples below continue after wallet connection and spend approval with a ready notebook-order card, the same project-scoped kernel client with retries disabled, and a browser created with its vault attached. checkoutURL / checkout_url is the browser’s exact current top-level url, obtained through your browser-control method; no playwright page object is required. verify the purchase and destination before calling fill; neither a model-proposed url nor a selector authorizes disclosure. format is forbidden for every field except a card’s combined expiration. request only needed billing fields. an absent or empty requested billing value returns 400 field_unavailable before any browser writes; it doesn’t make other card fields unavailable. don’t invent missing billing data. these selectors illustrate a checkout you control with separate number, combined expiry, and cvc inputs. replace them with selectors verified on your page, including within payment frames. supply 1–32 ordered bindings, never raw values or frame ids.

Handle the outcome

the cli exits nonzero for failed or unknown, but retains the value-free result on stdout with -o json. use the per-field statuses to decide what to fix before retrying. a transport error can leave the outcome uncertain even without a result body. see the shared fill outcome contract for per-field statuses and reconciliation. fill returns value-free per-field outcomes. completed means the fields were filled, not that payment succeeded. a failed result can leave earlier writes in place, and unknown or a lost response means the outcome is uncertain. fill never submits, so a retry is safe. retry only after checking the page, and never in an automatic loop. don’t fall back to aliases. decide whether to submit separately, and never retry checkout automatically. single-use describes the provider-issued card, not one-use alias consumption. fill does not consume the item or clear its encrypted material on the first field write. expiry, deletion, and item lifecycle restrictions still apply; a ready item is not evidence that a purchase can safely be repeated. don’t repeat authorize or create a replacement item to retry an unknown purchase. inspect outcomes, item events, and the merchant’s order state first.

Item reference

wallet and card items accept these spec fields. fields not listed here are rejected. a card’s spec.wallet must reference a link wallet in the same vault. the default link client is {type: 'kernel_managed'}. for your own client, set authorization.client to {type: 'customer_managed', provider_config: {name: 'checkout-link'}} and supply authorization.tokens with access_token and refresh_token. amount uses minor currency units. link accepts 1–500000, and a virtual card allows at most 50000. link requires a three-letter currency, limits merchant_name to 255 characters, requires an absolute http or https merchant_url, and requires at least 100 characters in context. the card item’s expires_at comes from link: the spend request’s expiry, or the issued virtual card’s validity. when link reports no expiry for a link pay token request, fill stays available for 30 minutes after authorization, including the time the user takes to approve. link line_items support name, quantity, unit_amount, description, sku, url, image_url, product_url, and totals. each totals entry supports type, display_text, and amount. link metadata accepts string values. card updates replace the complete spec; they are not partial merges. a requested link card accepts any valid spec, and a pending virtual-card request can update the fields link supports on its existing request. once a card is authorized with browser_id and page_url, updates return 409: delete it and create a new card.

Item states

  • wallet: pending_authorization, connected, declined, reconnect_required, degraded
  • card: requested, pending_authorization, ready, consumed, expired, declined, recovery_required
card state can include masks.brand and masks.last4. retrieve the card’s advertised operations before using it. for an unresolved provider outcome, follow payment recovery; a ready item alone is not evidence that a purchase can safely be repeated. deleting a card clears its stored provider value. deleting a wallet also invalidates its dependent cards.