Checkout

Create payment links, collect Pix, and track orders through the Hodle API.

Checkout turns a product into a hosted Pix payment link. The seller manages products and settlement settings with an API key. The payer-facing endpoints are public so the hosted page—or your own checkout UI—can read the product, create an order, and poll payment status.

The checkout reuses Hodle's existing deposit rail. Price, settlement asset, network, and destination address are always loaded from the seller's product and account; payer input cannot override them.

Authentication and availability

Seller endpoints require your production API key:

Authorization: Bearer hodle_live_...

The account must have Checkout enabled and at least one settlement rail. Public endpoints do not require an API key. They are rate limited by IP and accept only the documented fields.

Availability follows the Checkout flag and the settlement rails enabled for the account in the environment addressed by the request.

Seller endpoints

GET /api/checkout/products

Lists products owned by the account behind the API key, newest first.

curl --request GET \
  --url https://api.hodle.com.br/api/checkout/products \
  --header "Authorization: Bearer $HODLE_API_KEY"
{
  "success": true,
  "data": {
    "products": [
      {
        "id": "68bb089d3696d243ba022bc1",
        "slug": "plano-premium-k7m2p4",
        "name": "Plano Premium",
        "description": "Acesso por 30 dias",
        "imageUrl": null,
        "priceCents": 8990,
        "stock": null,
        "sold": 12,
        "views": 84,
        "asset": "BRLA",
        "network": "polygon",
        "askEmail": true,
        "askTaxId": true,
        "askNote": false,
        "status": "ACTIVE",
        "createdAt": "2026-09-05T13:00:00.000Z",
        "updatedAt": "2026-09-05T13:00:00.000Z"
      }
    ]
  }
}

POST /api/checkout/products

Publishes one product. The settlement asset and network come from the current Checkout settings and cannot be passed in this request.

curl --request POST \
  --url https://api.hodle.com.br/api/checkout/products \
  --header "Authorization: Bearer $HODLE_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "name": "Plano Premium",
    "description": "Acesso por 30 dias",
    "priceCents": 8990,
    "stock": null,
    "askTaxId": true,
    "askNote": false
  }'
const response = await fetch('https://api.hodle.com.br/api/checkout/products', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.HODLE_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    name: 'Plano Premium',
    description: 'Acesso por 30 dias',
    priceCents: 8990,
    stock: null,
    askTaxId: true,
    askNote: false,
  }),
})

const { data } = await response.json()
import os, requests

response = requests.post(
    "https://api.hodle.com.br/api/checkout/products",
    headers={"Authorization": f"Bearer {os.environ['HODLE_API_KEY']}"},
    json={
        "name": "Plano Premium",
        "description": "Acesso por 30 dias",
        "priceCents": 8990,
        "stock": None,
        "askTaxId": True,
        "askNote": False,
    },
)

product = response.json()["data"]["product"]
FieldTypeRequiredDescription
namestringyesProduct name, up to 120 characters.
descriptionstringnoDescription, up to 240 characters.
imageBase64data URInoPNG, JPEG, or WEBP image as a base64 data URI.
priceCentsintegeryesUnit price in BRL cents. Minimum 100.
stockinteger / nullnoTotal sellable units. null or omission means unlimited stock.
askTaxIdbooleannoRequire a valid CPF/CNPJ before creating Pix. Defaults to true.
askNotebooleannoAllow a payer note of up to 140 characters. Defaults to false.

Returns 201 with data.product in the same shape as the list endpoint.

PATCH /api/checkout/products/:productId

Updates an owned product. Send at least one field:

curl --request PATCH \
  --url https://api.hodle.com.br/api/checkout/products/68bb089d3696d243ba022bc1 \
  --header "Authorization: Bearer $HODLE_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{"priceCents": 9490, "status": "PAUSED"}'
FieldTypeValues
priceCentsintegerBRL cents, from 100 to 100000000.
stockinteger / nullNon-negative, or null for unlimited.
statusstringDRAFT, ACTIVE, or PAUSED.

A product owned by another API account answers 404, exactly like a missing product.

GET /api/checkout/settings

Returns the effective settlement configuration and which assets the account is currently allowed to select.

{
  "success": true,
  "data": {
    "settings": {
      "displayName": "Hodle Store",
      "supportEmail": "[email protected]",
      "asset": "USDC",
      "network": "polygon",
      "availableAssets": ["BRLA", "USDT", "USDC", "BRS"]
    }
  }
}

PUT /api/checkout/settings

curl --request PUT \
  --url https://api.hodle.com.br/api/checkout/settings \
  --header "Authorization: Bearer $HODLE_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "displayName": "Hodle Store",
    "supportEmail": "[email protected]",
    "asset": "USDC"
  }'

asset must be present in availableAssets. The server selects the matching network; clients do not pass one. The response contains the saved effective settings.

Payer endpoints

GET /api/public/checkout/products/:slug

Reads the payer-safe view of an active payment link.

curl --request GET \
  --url https://api.hodle.com.br/api/public/checkout/products/plano-premium-k7m2p4
{
  "success": true,
  "data": {
    "product": {
      "slug": "plano-premium-k7m2p4",
      "name": "Plano Premium",
      "description": "Acesso por 30 dias",
      "imageUrl": null,
      "priceCents": 8990,
      "available": null,
      "soldOut": false,
      "askTaxId": true,
      "askNote": false,
      "sellerName": "Hodle Store",
      "sellerSupportEmail": "[email protected]"
    }
  }
}

Missing, paused, disabled, and inactive-seller links all return the same 404 response. The public response deliberately omits seller IDs, wallets, settlement assets, networks, and provider details.

POST /api/public/checkout/orders

Creates a Pix charge for the product and quantity. The endpoint accepts only the fields below; extra fields—including price, asset, network, seller, and destination—make the request fail validation.

curl --request POST \
  --url https://api.hodle.com.br/api/public/checkout/orders \
  --header "Content-Type: application/json" \
  --data '{
    "slug": "plano-premium-k7m2p4",
    "quantity": 1,
    "payerEmail": "[email protected]",
    "payerTaxId": "52998224725",
    "payerNote": "Pedido 781"
  }'
const response = await fetch(
  'https://api.hodle.com.br/api/public/checkout/orders',
  {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      slug: 'plano-premium-k7m2p4',
      quantity: 1,
      payerEmail: '[email protected]',
      payerTaxId: '52998224725',
      payerNote: 'Pedido 781',
    }),
  },
)

const order = (await response.json()).data.order
import requests

response = requests.post(
    "https://api.hodle.com.br/api/public/checkout/orders",
    json={
        "slug": "plano-premium-k7m2p4",
        "quantity": 1,
        "payerEmail": "[email protected]",
        "payerTaxId": "52998224725",
        "payerNote": "Pedido 781",
    },
)

order = response.json()["data"]["order"]
FieldTypeRequiredDescription
slugstringyesProduct slug from the public product endpoint.
quantityintegeryesFrom 1 to 99, subject to available stock.
payerEmailstringyesE-mail recorded on the order.
payerTaxIdstringby productValid CPF/CNPJ when askTaxId is true.
payerNotestringnoOptional note, up to 140 characters.

The call returns 201 after the Pix charge is created:

{
  "success": true,
  "data": {
    "order": {
      "trackId": "f28bce4e-2f86-413e-a669-8ad74ae45a91",
      "status": "PENDING",
      "brCode": "00020126580014br.gov.bcb.pix...",
      "quantity": 1,
      "totalCents": 8990,
      "payerEmail": "[email protected]",
      "expiresAt": "2026-09-05T14:15:00.000Z",
      "paidAt": null
    }
  }
}

GET /api/public/checkout/orders/:trackId

Poll this endpoint until the order reaches a terminal state. Reading status also synchronizes it from the underlying charge and settles counted stock once.

curl --request GET \
  --url https://api.hodle.com.br/api/public/checkout/orders/f28bce4e-2f86-413e-a669-8ad74ae45a91
StatusMeaning
PENDINGPix is waiting for payment.
PAIDPayment completed and stock was settled.
FAILEDCharge failed.
EXPIREDThe 15-minute Pix payment window expired.

The response has the same data.order shape returned by order creation.

Errors

StatusMeaning
400Invalid JSON, undocumented fields, validation error, or unavailable asset.
401Missing or invalid API key on a seller endpoint.
403Checkout is disabled or the seller has no available settlement rail.
404Product, Checkout link, order, or account was not found in the caller scope.
409Product is paused or sold out.
429API-key or public-IP rate limit exceeded.
502Pix charge could not be created. Upstream/provider details are never sent.

Hosted page

You can use these endpoints from your own UI, or send the payer to Hodle's hosted page:

https://checkout.hodle.com.br/pay/:slug

The hosted page and the REST API share the same products, orders, stock, and payment state.