Get Started

Quickstart

Take your first test payment with Hosted Checkout in four steps, without building a card form.

Hosted Checkout is the fastest way to get paid: Tonder hosts the payment page, so card data never touches your servers (no PCI scope). This quickstart takes you from zero to a verified test payment in four steps.

Before you begin

  • A Tonder account — sign in at dashboard.tonder.io (Production) or dashboard-stage.tonder.io (Sandbox).
  • Your test API key from Developers → API Keys. Authenticate every request with your public key: Authorization: Token YOUR_TEST_API_KEY.

Amounts are in decimal format: 150.00 = MXN 150.00. Set external_id to your order reference — it's the key you'll reconcile payments by.

Steps

Create a checkout session

From your server, create a session with your public key. The response returns a url to send the customer to.

curl -X POST 'https://api-stage.tonder.io/checkout/v1/sessions' \
  -H 'Authorization: Token YOUR_TEST_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "customer": {
      "first_name": "Vicente",
      "last_name": "Quintero",
      "email": "vquintero@testuser.com"
    },
    "amount_total": 150.00,
    "currency": "MXN",
    "line_items": [
      {
        "name": "Deposit",
        "quantity": 1,
        "unit_price": 150.00,
        "product_id": "your internal product id"
      }
    ],
    "payment_method_types": [
      "card",
      "mercadopago",
      "oxxopay",
      "spei",
      "safetypayCash",
      "safetypayTransfer",
      "neosurf"
    ],
    "return_url": "https://tonder.io",
    "external_id": "ORD-12345-4",
    "metadata": { "external_id": "ORD-12345-4" }
  }'
curl -X POST 'https://api.tonder.io/checkout/v1/sessions' \
  -H 'Authorization: Token YOUR_LIVE_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "customer": {
      "first_name": "Vicente",
      "last_name": "Quintero",
      "email": "vquintero@testuser.com"
    },
    "amount_total": 150.00,
    "currency": "MXN",
    "line_items": [
      {
        "name": "Deposit",
        "quantity": 1,
        "unit_price": 150.00,
        "product_id": "your internal product id"
      }
    ],
    "payment_method_types": [
      "card",
      "mercadopago",
      "oxxopay",
      "spei",
      "safetypayCash",
      "safetypayTransfer",
      "neosurf"
    ],
    "return_url": "https://tonder.io",
    "external_id": "ORD-12345-4",
    "metadata": { "external_id": "ORD-12345-4" }
  }'

The response (200 Created) includes the redirect url, the session id, and a pending status:

{
  "id": "cs_97_41521_d11ba771527b4056c7f85786cfbb980b",
  "url": "https://stage-payflow.tonder.io/checkout/cs_97_41521_d11ba771527b4056c7f85786cfbb980b",
  "status": "pending",
  "payment_id": 41521,
  "amount_total": 150.00,
  "currency": "MXN",
  "external_id": "ORD-12345-4",
  "transaction_status": "Pending"
}

Redirect the customer

Send the customer to the url from the response — that's Tonder's hosted payment page.

res.redirect(session.url);

Complete a test payment

On the hosted page, pay with a test card: 4000 0000 0000 0077 (approved), any future expiry (e.g. 12/30), and any 3-digit CVC (e.g. 123). Find the full set of test cards under Developers → Test Data in the dashboard.

When done, Tonder returns the customer to your return_url with the session id appended: https://your-store.com/checkout/complete?session_id=cs_97_41521_….

Confirm the result

Always confirm server-side — don't assume the redirect means success.

  • Webhook (recommended). Tonder sends a session.completed event to your endpoint (Developers → Webhooks). Match it to your order via metadata.external_id and respond 200.
  • Status check. Or fetch the session and read status:
curl -X GET 'https://api-stage.tonder.io/checkout/v1/sessions/cs_97_41521_d11ba771527b4056c7f85786cfbb980b' \
  -H 'Authorization: Token YOUR_TEST_API_KEY'
curl -X GET 'https://api.tonder.io/checkout/v1/sessions/cs_97_41521_d11ba771527b4056c7f85786cfbb980b' \
  -H 'Authorization: Token YOUR_LIVE_API_KEY'

A successful payment returns status: "completed" and transaction_status: "Success":

{
  "id": "cs_97_41521_d11ba771527b4056c7f85786cfbb980b",
  "status": "completed",
  "transaction_status": "Success",
  "amount_total": 150.00,
  "currency": "MXN",
  "external_id": "ORD-12345-4",
  "paid_at": 1751478550234
}

Webhooks are the most reliable way to confirm payments — prefer them over polling. Acknowledge each event with a 200 and reconcile using metadata.external_id.

Next steps

Was this page helpful?

On this page