Integrate checkout
Integrate our seamless checkout solution and empower your players with payment methods across APAC.
Automatic integration (AI-assisted)
Copy the prompt below into your AI coding tool (Claude Code, Cursor, Codex, …) inside your project directory. The agent fetches our machine-readable docs and implements a complete test-mode integration: checkout, webhooks, and the delivery records that serve as your proof of delivery in disputes and chargebacks. You review the changes, add your API keys, and go live.
Even better — connect the Tokenz MCP. If your AI tool supports MCP, add our server and the agent can search the docs, create test checkout sessions, and verify webhook signatures directly — a guided, self-verifying integration. The prompt below works with or without it.
Sign in (no API key)
Use https://mcp.tokenz.one/merchant. Your client signs you in with OAuth 2.1 (authorization code and PKCE). Sign in with a Merchant Dashboard account and choose live or test mode. No API key to paste. The connection requests the dashboard:read and test_api_keys:create scopes. After you sign in, test tools mint a test key for that connection. This URL also accepts a secret_test_ key.
claude mcp add --transport http tokenz https://mcp.tokenz.one/merchant
Optional test key
https://mcp.tokenz.one/mcp does not use OAuth sign-in. With no Authorization header, the docs and webhook tools work: search_docs, get_doc, list_docs, get_openapi, list_test_cards, verify_webhook_signature, sign_test_webhook_payload, and check_auth. Test-action tools need a test key sent as Authorization: Bearer secret_test_...: create_test_checkout_session, get_checkout_session, get_order, cancel_test_order, create_test_refund, and get_refund. Live keys are refused.
claude mcp add --transport http tokenz https://mcp.tokenz.one/mcp --header "Authorization: Bearer secret_test_YOUR_KEY_HERE"
Prompt: integrate Tokenz Checkout end-to-end in test mode
You are integrating Tokenz — a Merchant of Record (MoR) checkout — into this project, end to end, in TEST MODE.
If a Tokenz MCP server is connected to you (you will see tools like `search_docs`, `get_openapi`, `create_test_checkout_session`, and `verify_webhook_signature`), use it throughout the steps below: prefer `search_docs`/`get_doc` over fetching raw doc URLs, take test cards from `list_test_cards`, and use `create_test_checkout_session` + `get_order` to prove the integration works against the real API. Everything below still applies either way.
Before writing any code:
1. Detect my project's stack and find the code that grants purchased items to a customer (fulfillment). Then ask me the questions below immediately, and fetch https://docs.tokenz.one/llms-checkout.txt while you wait for my answers. It contains the v2 checkout guides and links to the raw OpenAPI contracts. Fetch the linked Checkout Session, Order, and Webhook JSON specs before implementing their requests and payloads; those raw specs are authoritative for fields, constraints, errors, and response formats. Use https://docs.tokenz.one/llms.txt to find any additional guides you need. Stay on v2 for this new integration. If you cannot fetch URLs, ask me to paste the relevant guides and raw contracts.
2. The questions:
- What product(s) should the checkout sell (name, amount, currency)?
- Which environment file should hold my Tokenz test secret key (secret_test_...) and webhook signing secret (e.g. .env.local)? I will fill in the values myself. Remind me that the key needs the `CreateCheckoutSession`, `GetOrder`, and `RegisterDeliveryRecord` permissions.
- Confirm the framework/stack and the fulfillment code you found before patching anything. If the project has no fulfillment code yet, ask me how a paid order should be delivered and which ID identifies the customer.
- If this project only runs locally: how should Tokenz reach the webhook endpoint? (Offer to set up a tunnel such as ngrok or cloudflared, or ask me for a deployed HTTPS URL.)
Constraints (non-negotiable):
- Never hardcode, log, or commit secrets — API keys and webhook signing secrets alike; read them from environment variables only.
- Create Checkout Sessions server-side only; never expose the secret key to the browser.
- Define products and prices server-side; never trust amounts sent by the browser. Amounts are in minor units, and every product item needs a taxCategory from the docs' enum.
- Verify webhook signatures (Tokenz-Signature header) over the raw, unparsed request body; do not skip this.
- Fulfill orders from verified webhook events (order.succeeded), never from the customer reaching the success page — redirects prove navigation, webhooks prove payment. Handle webhook retries idempotently, keyed on the event's top-level `id`; the same event can be delivered more than once.
- Register a delivery record with Tokenz for every order you fulfill (POST /v2/order/{orderId}/delivery). This is a required part of the integration, not an extra: the delivery record is the proof of delivery sent to the bank or card issuer when a customer disputes a payment or files a chargeback, and an order without one has no evidence to defend it. Do not skip it, stub it, or offer it to me as optional.
- Build redirect URLs from a configured base URL, not from request headers such as Origin.
- Stay in Tokenz test mode until I explicitly ask to go live.
- Keep changes minimal; do not refactor unrelated code.
- Communicate with me in the language I use with you.
Deliverables — verify each actually works before claiming it is done:
1. A server endpoint that creates a Tokenz Checkout Session and returns its URL.
2. A checkout button/flow that redirects the customer to the hosted checkout.
3. Success, processing, and canceled pages wired to the session's redirect URLs. (Some payment methods settle asynchronously — the processing page is not optional.)
4. A webhook endpoint that receives events, verifies the signature, and updates order state. As soon as the webhook URL is known, tell me so I can register it in the Tokenz Dashboard (remind me: register it in TEST mode; the Dashboard shows the signing secret once, and I will put it into the env file myself — never ask me to paste it in chat) — then keep building while I do that.
5. Delivery registration, for every order the webhook fulfills:
- Order of operations: in the webhook handler, mark the event as processed, grant the items, and store the delivery record (or a job for it) as one transaction or one durable write, and only then acknowledge with 2xx. A retried webhook must find either nothing done or everything done, never granted items with no delivery record; if the project's storage cannot make that atomic, have the handler re-check fulfilled orders that lack a record and create it. Call the Delivery Registration API from outside the webhook response path (a queued job or background task), so a slow or unreachable API never delays the acknowledgement.
- Payload: send the full payload the docs recommend — `status`, `progress`, `at`, `user`, `items` with `deliveredQuantity` (plus the in-app balance before and after, when the item is a currency), `cartContext`, `deliveryContext`, and `deliveryInfo` — built from the real fulfillment data, never from placeholders. `cartContext` and `deliveryContext` describe the customer's device: capture the IP address, user agent, and device ID from the customer's own requests (when the Checkout Session is created, and at delivery if the customer is present), and store them with the order. Never fill them from the webhook request, which comes from Tokenz's servers; leave out a field you do not have.
- One record per delivery: register a failed delivery too (`status: failed`), send one record per delivery when an order is delivered in parts, and never let a retried webhook create a second record for the same delivery.
- Response: treat every entry in `warnings` as a bug and fix it. A failed call must never repeat or undo the fulfillment.
- Retries: each call creates a new record and there is no idempotency key, so keep every record Tokenz has not accepted in the project's own storage, in one of three states. Retryable (Tokenz answered 5xx): re-send automatically, including after a restart. Blocked (Tokenz answered 4xx): fix the cause before re-sending — 403 Forbidden means the key lacks the `RegisterDeliveryRecord` permission (on by default for secret keys), so tell me to use a secret key that has it; 401 Unauthorized means the key is missing, invalid, or revoked, so tell me to fix the key; re-send either once the key changes. Any other 4xx means the request is wrong, so fix it first. Needs review (no answer: timeout or dropped connection): never resend automatically; flag it for me to check.
6. A completed end-to-end test purchase using the test cards from the docs, with the webhook received and verified, the items granted once, and the delivery record accepted (201 Created, no warnings). If you have browser-automation tools, perform the test purchase yourself; otherwise give me exact steps.
7. A short go-live checklist for me: everything that must change to leave test mode (a live secret key with the permissions this integration uses, including `RegisterDeliveryRecord`; live webhook registration with its new signing secret; a stable public webhook URL; real tax/fulfillment handling), plus anything you stubbed.
If any step is blocked (missing key, docs ambiguity, unsupported stack), stop and ask me instead of guessing.
Prerequisites
Before you can have a working integration, make sure you have the API credentials (public key and secret key) from Tokenz. You can find your credentials on the Development page on the Tokenz Dashboard.
For more details on how Tokenz Checkout works, please see Checkout.
While integrating, use your test API keys (they contain test_, e.g. secret_test_...): Checkout Sessions created with them run in test mode and no real money moves. Switch to your live keys when you go live.
Set up the server
import os
from flask import Flask, request, redirect
from flask_cors import CORS
import requests
# Replace the keys with yours
SECRET_KEY = os.environ.get("SECRET_KEY", "secret_test_YOUR_KEY_HERE")
app = Flask(__name__, static_url_path="")
CORS(app)
root = "../client/build"
@app.route("/", methods=["GET"])
def index():
return redirect("http://localhost:3080")
Create a Checkout Session
Add an endpoint on your server that creates a Checkout Session. A Checkout Session controls what your customer sees on the Tokenz-hosted payment page, such as line items, the order amount, currency, and available payment methods.
Define the line items
Always keep sensitive information about your product inventory, like price and availability, on your server to prevent customer manipulation from the client. Define product information when you create the Checkout Session.
The order total is always computed from the itemDetails prices. The top-level amount field shown in some examples is optional, but if you provide it, it must match the itemDetails total or the request is rejected.
Tax. This quickstart (and its example payloads) documents the Merchant of Record (MoR) model — the default for Tokenz accounts — where Tokenz computes and collects tax automatically and you only set each item's taxCategory. If your account is specially configured for the Payment Gateway model, every Checkout Session must additionally include a top-level tax object in minor units (for example "tax": { "amount": 0, "currency": "USD" }); requests without it are rejected with order.tax-required. If you're unsure which model your account uses, check with your Tokenz contact.
Supply success and cancel URLs
Specify URLs for success and cancel pages—make sure they're publicly accessible so Tokenz can redirect customers to them. You can also handle the successful and canceled states with the same URL.
[optional] Define available payment method(s)
Specify the list of payment methods offered to your customer for this checkout. If the payment methods are not provided or an empty list is sent, all available payment methods will be displayed to the customer.
Redirect the customer to the Tokenz checkout
After creating the session, redirect your customer to the checkout page's URL returned in the response.
@app.route("/create-tokenz-checkout", methods=['POST'])
def create_tokenz_checkout():
CALLBACK_URL_PREFIX = request.headers['referer']
headers = {"Authorization": f'Bearer {SECRET_KEY}'}
print(headers)
payload = {
"amount": {
"currency": "JPY",
"amount": 5200
},
"itemDetails": [
{
"product": {
"label": "ひとにぎりのエメラルド",
"description": "80+8",
"images": [
"https://images.ctfassets.net/z82qbo7cv7ia/1dWPbk5Qx2M1Qikj6Knyuc/e37b2c26829c0d30793a348ae3adb3b0/fake-pass.webp"
],
"quantity": 3,
"price": {
"currency": "JPY",
"amount": 1200
},
"taxCategory": "DIGITAL_GOODS_AND_SERVICES"
}
},
{
"product": {
"label": "エメラルドの荷車",
"description": "100+10",
"images": [],
"quantity": 1,
"price": {
"currency": "JPY",
"amount": 1600
},
"taxCategory": "DIGITAL_GOODS_AND_SERVICES"
}
}
],
"customerInfo": {},
"successUrl": "http://localhost:9000/success",
"pendingUrl": "http://localhost:9000/pending",
"cancelUrl": "http://localhost:9000/cancel"
}
res = requests.post(
"https://api.tokenz.one/v2/checkoutsession", json=payload, headers=headers
)
session = res.json()
return redirect(session["url"], 303)
Build your checkout
Add a success page
Create a success page for the URL you provided as the Checkout Session successUrl to display order confirmation messaging or order details to your customer. Tokenz redirects to this page after the customer successfully completes the checkout.
<!DOCTYPE html>
<html>
<head>
<title>Thanks for your order!</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<section>
<p>
We appreciate your business! If you have any questions, please email
<a href="mailto:orders@example.com">orders@example.com</a>.
</p>
</section>
</body>
</html>
Add a processing payment page
For asynchronous payment methods, like convenience store payment or bank transfer, the payment might be in a processing state for a few minutes up to a few days. Add a page for the pendingUrl. Tokenz redirects to this page after the customer closes the instructions page for asynchronous payments.
<!DOCTYPE html>
<html>
<head>
<title>Thanks for your order!</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<section>
<p>
Your payment is being processed! We will let you know as soon as it is completed.
If you have any questions, please email
<a href="mailto:orders@example.com">orders@example.com</a>.
</p>
</section>
</body>
</html>
Add a canceled page
Add another page for cancelUrl. Tokenz redirects customers to this page when they click the back button during checkout.
<!DOCTYPE html>
<html>
<head>
<title>Checkout canceled</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<section>
<p>Forgot to add something to your cart? Shop around then come back to pay!</p>
</section>
</body>
</html>
Add a checkout button
Finally, add a page to show customers a preview of their order. Allow them to review or modify their order—as soon as they land on the Checkout page, the order is final, and they can't modify it without creating a new Checkout Session.
Add a button to your order preview page. Customers are redirected to the Tokenz-hosted payment page when they click this button.
<!DOCTYPE html>
<html>
<head>
<title>Buy cool new product</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<section>
<div class="product">
<img src="https://images.ctfassets.net/z82qbo7cv7ia/1dWPbk5Qx2M1Qikj6Knyuc/e37b2c26829c0d30793a348ae3adb3b0/fake-pass.webp" alt="ひとにぎりのエメラルド" />
<div class="description">
<h3>ひとにぎりのエメラルド</h3>
<h5>1,200円</h5>
</div>
</div>
<form action="/create-tokenz-checkout" method="POST">
<button type="submit" id="checkout-button">Checkout</button>
</form>
</section>
</body>
</html>