Skip to main content
This page is for developers who build their own backend and user interface. It explains how to build Agent payment capabilities with the Clink RESTful API. You can use the Customer Portal API (the Agent Portal API in the Clink API docs) to manage a user’s wallet, payment methods, purchase authorizations, and orders, and then use Browser Pay to complete payment on the merchant page. This path suits platforms that want to control their own product interface, user experience, and business flows. It does not require your Agent to connect directly to the user MCP, and it does not require the Vault SDK. Clink owns user payment data and authorization boundaries; your platform owns user identity, business orchestration, the merchant browser, and order state.
This tutorial uses Sandbox UAT examples. First request a platform client_id and client_secret from Clink as described in How to get platform credentials. The emails, user IDs, and tokens in the examples are placeholders.

1. Prepare the environment and platform credentials

Clink configures credentials separately for each environment. Do not mix Sandbox UAT and Production tokens, user connections, payment methods, or card associations. The RESTful API uses the platform client_id and client_secret issued through Pre-registration, and shares the same platform client with MCP. For how to apply, what Clink registers, and the RSA public key, see How to get platform credentials. During onboarding, register the redirect_uri used for first-time user authorization and the Portal scopes portal:read portal:write. In addition to the platform credentials, your backend also stores CLINK_API_BASE_URL. Keep user tokens, decrypted card fields, and payment credentials only on a trusted server. Do not put them in browser code, URLs, logs, Agent input, or ordinary business messages.

2. Get a platform token

Call the OAuth token endpoint with the platform credentials. The platform token is used only on the server to manage user connections and exchange for Portal Tokens. It cannot call user Portal APIs directly, and it cannot replace user authorization.
Cache the platform token according to expires_in in the response, and get a new one after it expires.

3. Get a Portal Token for a user

The Customer Portal API uses a Portal Token that represents a single Clink user. First verify the user’s email in your system, and associate the Clink user with a stable platform user ID. New users, and users who already have a valid authorization for the current platform, only need email. When an existing Clink user authorizes the current platform for the first time, the redirect and PKCE fields are also required. We recommend generating a random state and a PKCE code_verifier before every request, computing the S256 code_challenge, and temporarily binding them to the platform user:

Authorized user

If the user is new, or has already completed authorization for the current platform, the endpoint returns a Portal Token:
Store the Portal Token encrypted on the server and bind it only to the returned customer_id. Use it when calling the Customer Portal API:

User authorization required

If Clink finds the user but the current platform does not yet have a valid authorized connection, the response is:
Pass authorization_url unchanged to the corresponding user. After the user completes the OAuth callback, confirm that state belongs to the platform user who initiated the request and validate iss, then call the Portal Token endpoint again to get the token. Do not skip authorization, do not modify the authorization URL, and do not hand the authorization link to the model to rewrite. If the user cancels or denies authorization, initiate a new authorization request. A Portal Token can access only the current user’s data. It cannot call /mcp, and an MCP user token cannot call /agent/platform/**.

Token expiry and renewal

A Portal Token has only an access token and no refresh token. After it expires, use the platform token to call the Portal Token endpoint again for a new one. If the current platform’s authorization for that user is no longer valid, the endpoint returns authorization_required again. The platform token is always the source of authority for getting user tokens and must be stored only on the server.

4. Persist user tokens on the server

A Portal Token is a server-side credential that represents a single user. After getting or refreshing it, the platform must persist the token, its expiry time, customer_id, and the granted scopes, encrypted and keyed by platform user and environment. Do not keep them only in the current request or in Agent process memory.
  • Use your platform’s own stable user ID as the primary key. Do not use the email as the primary key, and do not reuse tokens across users or environments.
  • Before calling a Portal API, read the token from secure server-side storage and check expires_in. After it expires, exchange for a new one with the platform token. Portal Tokens have no refresh token.
  • Update the storage atomically when the token is refreshed or re-exchanged, so concurrent requests do not overwrite the new token. When authorization becomes invalid, delete the invalid local token and guide the user through authorization again.
  • Use the token only on a trusted server. Do not write it into browser code, URLs, logs, Agent input, ordinary business messages, or client-side storage.
Example data structure:
After a service restart, you should be able to read this record by platform user ID and environment and continue calling the Portal API. After the user re-authorizes, atomically replace the old record with the new token.

5. Read the account and payment methods

Use the Portal Token to verify the current user’s status:
Read the user’s saved payment methods:
The response does not include PAN or CVV. Your interface displays only the brand, last four digits, and Agent Pay-eligible identifier returned by Clink. Do not infer from the existence of a card that the user has authorized a purchase. If the user only needs to add a card, create a hosted bind session. The request has no body, and the session is always created for the user represented by the Portal Token:
Show the short-lived url from the response to the user unchanged, and treat it as a credential: do not forward it, screenshot it, or write it to logs. After the user completes the Clink-hosted page, read the payment methods again. A bind session does not create a purchase authorization. To add a card and authorize in one step, see “Add a card and authorize” in the next step. Do not collect real card numbers or CVV on platform pages.

6. Create a purchase authorization

Browser Pay first requires an active purchase authorization (instruction) that applies to this purchase. payment_instrument_id determines the signing mode:
The response returns instruction_id, status, activation_url, and activation_expires_at. Activation steps:
  1. Send activation_url only to the target user, and open it in the user’s own browser. It is an activation link, not a Portal Token, but anyone who has the link can obtain the user’s Clink browser session while it is valid. Do not forward it, screenshot it, or write it to logs.
  2. Poll GET /agent/platform/authorizations/{instructionId} until status is ACTIVE.
  3. Read the mandate_id that covers this purchase from the instruction. Use it in the next step when you get the credential.
If the user does not complete activation, the instruction stays CREATED or PENDING and does not authorize any spending. request_id is the idempotency key: retrying with exactly the same parameters within 24 hours returns the same instruction, and reusing the same request_id with different parameters returns 409. For all fields, see the Portal API reference. To view the current user’s authorizations:
Before every payment, recheck the amount, currency, merchant, validity period, remaining limit, and authorization status. Do not reuse an authorization across users or environments.

7. Get a payment credential with Browser Pay

The merchant browser first reads the amount, currency, merchant information, and order identifier from the final checkout page. The platform backend then requests a one-time payment credential with the active instruction’s instruction_id, the mandate_id that covers this purchase, and this real checkout information. The Browser Pay credential endpoint is part of the Portal API:
amount is a decimal string in major currency units, and merchant_url must be the HTTPS checkout page URL. client_reference_id is the idempotency key for this purchase: save it and use the same value when you report the result. Retrying with the same parameters returns the same credential and does not issue a new one. For optional fields such as product details products and shipping address shipping_address, see the Portal API reference. The response mode depends on whether the platform has registered a public key with Clink: Use decrypted or plaintext card fields only briefly inside a controlled checkout executor. Do not write them to logs, databases, model context, or browser local storage, and do not keep them after checkout. Use the expiry in the decrypted payload to determine how long the credential is usable; expires_at is only an estimate. If the credential response times out, retry with the same client_reference_id to retrieve the original credential. Do not create a new authorization.

8. Complete payment on the merchant page

Your browser executor is responsible for:
  1. Opening the merchant checkout page and reading the final amount, currency, and merchant information.
  2. Confirming that this information exactly matches the purchase authorization and the payment credential request.
  3. Using the credential in a trusted payment-fill component, without exposing real card fields to the model or ordinary logs.
  4. Submitting the merchant order and reading the final result from the merchant page or order API.
  5. Calling the payment result endpoint once the result is clear.
A successful Clink API response, a 2xx response from the PSP, or a successfully issued credential does not on its own prove that the merchant order is paid. Only the final result from the merchant page or order API determines the next step.

9. Confirm the payment result

After you confirm the merchant result, report it with the same client_reference_id. This is the only entry point for confirming the transaction result:
Reporting rules:
  • Report the final result within 24 hours of credential issuance (before report_deadline). Late reports return 410.
  • For FAILED and NOT_SUBMITTED, you can include failure_reason, such as CARD_DECLINED, AMOUNT_CHANGED, or BUYER_CANCELLED.
  • paid_amount and currency_code must be sent together. If they do not match the authorized amount, the response returns paid_amount_mismatch: true.
  • Reporting a failure after a success has been recorded (or the reverse) returns 409 (result_already_reported).
When the result is unknown, first query the original merchant order, then report the final result. Do not switch cards, create a second authorization, or resubmit the same payment. For the full rules, see the Portal API reference. After the order is complete, you can read the order and its refund history:
The Customer Portal API can read refund records but cannot initiate refunds. Refunds go through other business flows provided by Clink.