API Reference

Sessions

Create stablecoin or PIX payment instructions for your own transparent checkout, with an optional hosted fallback.

A session creates one charge from an active product. It returns the raw payment instructions for your own checkout UI and a Dolafy-hosted checkoutUrl for the same charge. Switching between your UI and the hosted page never creates a second charge.

  • A stablecoin product returns an exact token, network, amount, and one-time deposit address in stablecoin.
  • A PIX product returns the payable Copia e Cola string in pix.

Create a session

POST /v1/checkout/sessions
x-api-key: dlfy_live_...
Idempotency-Key: session:txn_1048
content-type: application/json

Provide exactly one of productId (≤ 120 chars) or externalProductId (≤ 200 chars). Optional common fields are transactionReference (≤ 200), userId (≤ 200), buyerEmail (valid email, ≤ 320), description (≤ 500), amount, and discountPercent. If transactionReference is omitted, Dolafy generates txn_<uuid>.

Omit amount to charge the product’s current catalog price. Send amount as a positive number or decimal string with at most two decimal places to set this session’s exact final total; it may be higher or lower than the catalog price. Prefer a decimal string so your language does not introduce floating-point rounding. The currency still comes from the product—USD for stablecoin and BRL for PIX—and cannot be overridden. discountPercent remains available for percentage discounts and may be a number or numeric string greater than 0 and less than 100, with at most two decimal places. Provide either amount or discountPercent, never both. Neither option changes the reusable product or its payment methods. Unknown top-level request fields are rejected.

Stablecoin request

For a stablecoin product, paymentMethod is required. Choose one crypto entry from the product’s paymentMethods and send its type, chain, and settlementCurrency:

{
  "externalProductId": "pro-plan",
  "transactionReference": "txn_1048",
  "userId": "user_42",
  "buyerEmail": "ana.silva@example.com",
  "description": "Pro Plan custom order",
  "amount": "37.45",
  "paymentMethod": {
    "type": "crypto",
    "chain": "base",
    "settlementCurrency": "USDC"
  }
}

Supported values are base or solana for chain, and USDC or USDT for settlementCurrency. The selected combination must be enabled on that product.

Stablecoin response

Returns 201 Created on first creation, 200 OK on an identical replay.

{
  "session": {
    "id": "310ace43-4c69-4fd2-acd8-94645dbe1938",
    "transactionReference": "txn_1048",
    "status": "created",
    "checkoutUrl": "https://dolafy.com/checkout/c-8f41a2d9?dolafy_session_id=310ace43-4c69-4fd2-acd8-94645dbe1938",
    "expiresAt": "2026-08-12T12:30:00.000Z",
    "product": {
      "id": "6a713a92-350a-4cc6-a996-1e55e97d3a36",
      "externalProductId": "pro-plan",
      "slug": "c-8f41a2d9",
      "name": "Pro Plan",
      "amount": "37.45",
      "currency": "USD"
    },
    "pricing": {
      "originalAmount": "29.00",
      "discountPercent": null,
      "discountAmount": "0.00",
      "finalAmount": "37.45",
      "currency": "USD"
    },
    "paymentType": "stablecoin",
    "stablecoin": {
      "network": "base",
      "token": "USDC",
      "amount": "37.45",
      "depositAddress": "0x7D2f...91A4",
      "expiresAt": "2026-08-12T12:30:00.000Z"
    }
  }
}

Show the buyer stablecoin.amount, stablecoin.token, stablecoin.network, and stablecoin.depositAddress. The address is unique to this charge. The buyer must send the exact token on the exact network before expiry; sending another asset or using another network does not pay the charge.

PIX request and response

For a PIX product, omit paymentMethod. The product already has exactly one payable rail:

{
  "externalProductId": "curso-pro",
  "transactionReference": "txn_1048",
  "userId": "user_42",
  "buyerEmail": "ana.silva@example.com",
  "description": "Curso Pro checkout",
  "discountPercent": "20.00"
}

The common session fields have the same shape. The rail-specific portion is:

{
  "session": {
    "id": "310ace43-4c69-4fd2-acd8-94645dbe1938",
    "transactionReference": "txn_1048",
    "status": "created",
    "checkoutUrl": "https://dolafy.com/checkout/c-8f41a2d9?dolafy_session_id=310ace43-4c69-4fd2-acd8-94645dbe1938",
    "expiresAt": "2026-08-12T12:30:00.000Z",
    "product": {
      "id": "6a713a92-350a-4cc6-a996-1e55e97d3a36",
      "externalProductId": "curso-pro",
      "slug": "c-8f41a2d9",
      "name": "Curso Pro",
      "amount": "39.92",
      "currency": "BRL"
    },
    "pricing": {
      "originalAmount": "49.90",
      "discountPercent": "20.00",
      "discountAmount": "9.98",
      "finalAmount": "39.92",
      "currency": "BRL"
    },
    "paymentType": "pix",
    "pix": {
      "code": "000201...6304ABCD",
      "amount": "39.92",
      "currency": "BRL",
      "expiresAt": "2026-08-12T12:30:00.000Z"
    }
  }
}

pix.code is the payable Copia e Cola payload—not a bank PIX key. Render it as a QR image or provide a copy action.

Common behavior

  • session.id is the checkout charge id.
  • session.paymentType is stablecoin or pix; only the matching rail-specific object is present.
  • session.status is normalized across rails. It is normally created on the first response; a replay can return a later pending, underpaid, paid, expired, or failed state.
  • The hosted URL uses the reserved dolafy_session_id parameter to load and poll the already-created charge. Opening it never creates a second charge. The parameter is not copied into attribution, webhook data.urlParams, or success redirects. Treat the full URL as payment-session data and do not expose it in logs.
  • pricing.originalAmount snapshots the product price, while finalAmount, product.amount, and the rail-specific amount are the final charge total.
  • With an absolute amount, discountPercent is null and discountAmount is 0.00; compare originalAmount and finalAmount when you need the catalog-versus-charged difference.
  • When both pricing options are omitted, the discount fields are empty/zero and the original and final amounts are equal.
  • transactionReference is persisted as txn_id and userId as the charge externalId; both are returned by the Transactions reads and included in webhook data.
  • Confirmation is driven by webhooks. Fulfil only after checkout.payment.completed; never depend on a success page or browser redirect.

Idempotency & conflicts

An identical retry with the same Idempotency-Key returns the same charge, hosted URL, and payment instructions. Replaying a completed session still works after its product is archived.

  • Reusing an idempotency key with a different body → 409 idempotency_key_conflict.
  • The stablecoin paymentMethod is part of the idempotency body. Changing its chain or token is a different request.
  • Changing amount is a different request. Equivalent forms such as 37.45 and "37.45" normalize identically.
  • Changing discountPercent is a different request. Equivalent forms such as 20, "20", and "20.00" normalize identically.
  • Assigning the same transactionReference to another session → 409 transaction_reference_conflict.

Rate limits

Session creation is limited per customer and per organization: 3 new sessions per customer per 10 minutes, and 30 per organization per minute. Exceeding a limit returns 429 with a Retry-After header and either checkout_session_customer_rate_limit_exceeded or checkout_session_organization_rate_limit_exceeded. Customer identity is derived from userId, then buyerEmail, then transactionReference. Identical idempotent replays do not consume the limit.

Errors

Status Code Meaning
400 invalid_idempotency_key The required key is missing or malformed.
400 invalid_body Invalid fields, or not exactly one product identifier.
400 invalid_checkout_session_amount amount is not a positive supported decimal with at most two decimals.
400 invalid_discount_percent Percentage is not greater than 0 and less than 100, or has more than two decimals.
400 checkout_session_pricing_conflict Both amount and discountPercent were supplied.
400 checkout_session_payment_method_required A stablecoin product requires paymentMethod.
400 checkout_session_payment_method_not_applicable paymentMethod was sent for a PIX product.
400 checkout_session_network_not_accepted The selected network is not enabled for the product.
400 checkout_session_token_not_accepted The selected token is not enabled for the product.
400 checkout_session_invalid_amount A stablecoin product has an invalid payable amount.
400 checkout_pix_invalid_amount A PIX product has an invalid payable amount.
404 product_not_found No active organization-owned product matched.
409 idempotency_key_conflict The key was reused with another body.
409 transaction_reference_conflict Another session already reserved the reference.
409 checkout_session_in_progress Retry the identical request with the same key shortly.
429 checkout_session_*_rate_limit_exceeded Wait for Retry-After.
503 checkout_pix_not_available Your organization’s PIX route is unavailable.
503 checkout_session_capacity_unavailable Stablecoin charge capacity is temporarily unavailable.
503 checkout_session_unavailable Checkout infrastructure is temporarily unavailable.

Advanced

Pricing precision and limits

Absolute amounts are normalized to currency cents. Discounts are calculated with exact basis-point arithmetic and rounded half-up to cents. A discount that rounds to less than one cent is rejected. The final total must be at least 0.01 USD for stablecoin or 1.00 BRL for PIX. Dynamic pricing is accepted only by this authenticated session endpoint; do not add amount or discount query parameters to reusable hosted product links.

Rare errors

Status Code Meaning
400 checkout_session_discount_too_small The discount rounds to less than one cent.
400 checkout_session_amount_below_minimum The final total is below the rail minimum.
409 checkout_session_creation_failed Do not blindly retry with a new key; contact support.
503 checkout_pix_missing_payment_instructions A payable PIX code could not be generated; retry shortly.
503 checkout_session_discount_unavailable Discounted charge persistence is temporarily unavailable; retry after deployment completes.
503 checkout_session_amount_unavailable Custom amount persistence is temporarily unavailable; retry after deployment completes.