Skip to content
Dashboard

Warning: Provisional contract proposal

These endpoints are not operational and no SDK is published. Examples use test identifiers only and nothing is sent anywhere.

Payments

Checkout

KrokoPay hosts the payment page for every charge and payment link. Send the buyer to one URL; the checkout handles Pix, cards, your brand and every outcome.

The checkout is the page where the buyer pays. It is hosted by KrokoPay, carries your brand and works for two kinds of id: a charge you created through the API, or a payment link you share as many times as you like. You never render card fields yourself, so card numbers never pass through your servers.

How the checkout opens

Every checkout lives at https://krokopay.app/pay/{id}. The id decides what the buyer sees:

  • chg_…: a charge created with POST /v1/charges. Its checkout_url already points here. One charge, one payment.
  • plink_…: a payment link. Its url points here. Every buyer who submits the form gets a new charge with link_id set.
Checkout URL patternsHTTP
# A charge created through the API (returned as checkout_url)https://krokopay.app/pay/chg_9Qs5MbT2kXn8Vd​# A payment link (returned as url): reusable, one charge per buyerhttps://krokopay.app/pay/plink_2Wn6HsT9cVb4Lq
Open the checkout from your siteTypeScript
// In the browser. Your own endpoint creates the charge with the secret key// and returns only its checkout_url.const response = await fetch("/api/orders/1042/checkout", { method: "POST" });if (!response.ok) throw new Error("Could not start the checkout");const { checkout_url } = (await response.json()) as { checkout_url: string };window.location.assign(checkout_url);

Success: Nothing to embed

Redirecting to the URL is the whole integration on the front end. No script tag, no package, no publishable key is needed to open the checkout.

What the buyer sees

  1. Step 1: Your brand and the order

    Your display name, initials tile and tagline at the top, then the description and the amount in BRL.

  2. Step 2: A payment method

    Only the methods allowed by the charge or link (methods).

  3. Step 3: Pix

    A QR code and a copy-and-paste code with a countdown until expires_at (15 minutes in the test environment; the production window is to be defined).

  4. Step 4: Card

    Number, expiry, CVC and holder name, validated in the browser before submitting. Only the brand and last four digits are kept.

  5. Step 5: Payer details

    Name and email, used to match an existing customer by email or create a new one.

  6. Step 6: The result

    A receipt when paid, or a clear message with what to do next when the payment cannot go through.

Brand identity

The checkout reads your brand from the account settings, not from the request. Change it once in Settings and every charge and link uses it.

SettingWhere it appears
Display nameHeader of the checkout and the receipt.
Accent colorPrimary button and the selected payment method.
InitialsOne or two letters shown in the logo tile.
TaglineShort line under the name. Optional.
Support emailShown on the receipt and on error states, so buyers can reach you.
Information: Pick an accent color with enough contrast against white text: the checkout uses it on the pay button.

Checkout states

The same URL shows a different screen depending on the state of the charge or link behind it.

StateWhenWhat the buyer can do
Waiting for paymentA pending charge, or an active payment link.Choose a method and pay.
PaidThe charge is paid (also refunded or partially_refunded).See the receipt. Opening the URL again never charges twice.
DeclinedA card attempt failed; the charge is failed.Read the reason and, if the charge came from a link, start again from the link.
ExpiredA Pix charge passed expires_at without payment.Start again from the link, or ask you for a new charge.
UnavailableThe payment link is inactive, or its product or price was archived.Nothing to pay; contact the support email.
InvalidThe id does not exist.Nothing to pay; check the link they received.

Reproduce every state with the test cards below (any future expiry and any CVC work), or by letting a Pix countdown run out. More in Test environment.

Test cardOutcome
4242 4242 4242 4242Approved: the charge becomes paid.
4000 0000 0000 0002Declined with card_declined.
4000 0000 0000 9995Declined with insufficient_funds.
4000 0000 0000 0069Declined with expired_card.
4000 0000 0000 0127Declined with incorrect_cvc.

Language of the checkout

The checkout is available in English and Brazilian Portuguese. The default comes from the checkout language preference in Settings: auto follows the buyer's browser, or you can fix it to en or pt-br. Amounts are always shown in the charge currency (BRL), whatever the language.

After the payment

When the payment is confirmed, the charge becomes paid and KrokoPay sends charge.paid to your webhook endpoints. Fulfil the order from the webhook, not from the browser: the buyer may close the tab before reaching any page of yours.

charge.paidJSON
{  "id": "evt_6Ff7Gg8Hh9Ii0J",  "object": "event",  "type": "charge.paid",  "api_version": "2026-11-01",  "created_at": "2026-11-03T14:23:41.000Z",  "data": {    "object": {      "id": "chg_4Fp9KzW1xQm7Rt",      "object": "charge",      "amount": 49700,      "currency": "BRL",      "status": "paid",      "method": "pix",      "card": null,      "description": "Curso Identidade Visual do Zero",      "customer_id": "cus_8Hq2LmZr4TxN1a",      "product_id": "prod_3Vb7QpK9sWd2Ee",      "price_id": "price_5Kd1NcR8vYq3Hm",      "link_id": "plink_2Wn6HsT9cVb4Lq",      "subscription_id": null,      "fee": null,      "net": null,      "refunded_amount": 0,      "failure_code": null,      "created_at": "2026-11-03T14:22:05.000Z",      "paid_at": "2026-11-03T14:23:41.000Z",      "expires_at": "2026-11-03T14:37:05.000Z",      "available_at": null,      "checkout_url": "https://krokopay.app/pay/chg_4Fp9KzW1xQm7Rt"    }  }}

Warning: No redirect field yet

Sending the buyer back to a URL of yours after payment is not part of the current proposal and is to be defined. Until then the buyer stays on the checkout receipt; show the order status on your site from your own records, updated by webhooks.
  • Failed attempt: charge.failed, with failure_code on the charge.
  • Pix not paid in time: charge.expired.
  • Paying a link with a recurring price also emits subscription.created. See Subscriptions.

A payment link is a reusable checkout: share its url in an email, a chat or a button. It charges either a catalog price (price_id) or a fixed amount.

Endpoint: POST/v1/payment_links

Body parameters

namestringRequired
Title shown on the checkout.
descriptionstringOptional
Short text under the title.
price_idstringOptional
Charge a catalog price. Required unless amount is sent.
amountintegerOptional
Fixed amount in centavos, when there is no price_id.
methodsstring[]Required
pix, card or both.
curl -X POST https://api.krokopay.app/v1/payment_links \  -H "Authorization: Bearer kp_test_sk_4f9a2c7e1b8d4a6f9c3e5d7b" \  -H "Content-Type: application/json" \  -d '{    "name": "Curso Identidade Visual do Zero",    "price_id": "price_5Kd1NcR8vYq3Hm",    "methods": [      "pix",      "card"    ]  }'
curl -X POST https://api.krokopay.app/v1/payment_links \  -H "Authorization: Bearer kp_test_sk_4f9a2c7e1b8d4a6f9c3e5d7b" \  -H "Content-Type: application/json" \  -d '{    "name": "Consultoria — 1 hora",    "description": "Sessão online de uma hora.",    "amount": 25000,    "methods": [      "pix"    ]  }'
Endpoint: GET/v1/payment_links
curl https://api.krokopay.app/v1/payment_links \  -H "Authorization: Bearer kp_test_sk_4f9a2c7e1b8d4a6f9c3e5d7b"
Endpoint: POST/v1/payment_links/{id}

Updates name, description, methods or active. Changes apply to the next buyer; charges already created keep their amount.

Endpoint: DELETE/v1/payment_links/{id}

Removes a link. If it already has charges, the link is deactivated instead (active: false) so its history stays intact, and its URL shows the unavailable state.

curl -X DELETE https://api.krokopay.app/v1/payment_links/plink_2Wn6HsT9cVb4Lq \  -H "Authorization: Bearer kp_test_sk_4f9a2c7e1b8d4a6f9c3e5d7b"