Skip to content

API reference ​

The Merchant API is used by your server to create and query payment orders. API keys must be stored server-side.

Base URL ​

text
https://api.tariapay.com/v1

Authentication ​

Bearer token is recommended:

text
Authorization: Bearer tpk_...

Also accepted for compatibility:

text
x-api-key: tpk_...

If the API key is missing, invalid, or revoked, the API returns 401.

Core endpoints ​

MethodPathPurpose
POST/payment-intentsCreate a new payment order
GET/payment-intentsList orders, or look up by orderId
GET/payment-intents/:paymentIdRetrieve a single payment order (with transferDepositAddress + transferInstructions once a deposit address exists)
GET/payment-intents/:paymentId/transfer-statusDirect-transfer status of your own order: amount received, short/over, wrong chain or token, late funding. ?scanAllChains=true also reads the other enabled chains. See Pay programmatically
GET/payment-intents/:paymentId/transfer-depositStrictly read-only deposit balances for your own order (never triggers detection)
POST/payment-intents/:paymentId/transfer-deposit/settleSettle a funded deposit now instead of waiting for the sweeps
POST/payment-intents/:paymentId/expireExpire an unpaid order with no deposit received
GET/payment-status?orderId=On-chain payment status of your own order, by your orderId (replaces the public merchant + orderId lookup)
POST/payment-intents/:paymentId/refundsRefund a confirmed payment in full to the original payer wallet
GET/refundsList merchant refunds

Public checkout endpoints ​

These endpoints are used by Hosted Checkout, the Checkout Button, and the Checkout Panel; ordinary merchants normally don't call them directly. The Button path only needs your server to return the checkoutUrl; only the Panel path requires passing the paymentId to the frontend.

MethodPathPurpose
GET/checkout/v1/payment-intents/:paymentIdRead public checkout data
POST/checkout/v1/payment-intents/:paymentId/attemptsCreate the payment configuration after the buyer selects a network and currency
POST/checkout/v1/payment-intents/:paymentId/syncSync the on-chain receipt after the buyer submits a transaction
POST/checkout/v1/payment-intents/:paymentId/transfer-statusTransfer payments: check whether funds have arrived at the order's dedicated deposit address

The public checkout data carries only what the buyer's page needs — amount, status, networks, displayReference, publicMetadata — not your orderId, return URLs or private metadata. GET /checkout/v1/payment-intents/:paymentId/return?outcome=success|cancel is where the checkout sends the buyer back to you. GET /public/payment-status answers by paymentId or txHash only, is rate limited, and a txHash lookup returns on-chain fields only.

The :paymentId on these public endpoints accepts both the bare UUID and the pi_<uuid> form. The legacy /prepare endpoint is kept for compatibility only — do not use it in new integrations.

Subscription endpoints ​

For merchants with their own customer system managing subscriptions — see Subscriptions (API).

MethodPathPurpose
POST/subscription-plansCreate a plan (price object)
GET/subscription-plansList plans
GET/subscription-plans/:planIdRetrieve a single plan
PATCH/subscription-plans/:planIdUpdate a plan
POST/subscriptionsOpen a subscription for a customer; returns the subscription, invoice, and payment link
GET/subscriptionsList subscriptions, filterable by customerId / planId
GET/subscriptions/:idRetrieve a single subscription
GET/subscriptions/:id/invoicesList a subscription's billing-period invoices
POST/subscriptions/:id/cancelCancel a subscription

Creating a payment order ​

bash
curl -X POST "https://api.tariapay.com/v1/payment-intents" \
  -H "Authorization: Bearer tpk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "orderId": "order_1001",
    "amount": "12.50",
    "currency": "USDC",
    "successUrl": "https://merchant.example/success",
    "cancelUrl": "https://merchant.example/cancel",
    "customer": {
      "email": "buyer@example.com"
    },
    "metadata": {
      "cartId": "cart_12"
    }
  }'

Request fields ​

FieldRequiredDescription
orderIdRequiredOrder ID from your business system
amountRequiredOrder amount; a string is recommended
currencyRequiredUSDC, USDT, or EURC — the primary coin
acceptedCurrenciesOptionalUSDC / USDT / EURC array for the checkout coin picker. Omit to show only currency.
customerOptional{ email?, name? } (legacy customerEmail / customerName also work)
successUrlRecommendedURL to return the buyer to your site after payment; redirected server-side once the payment is processing or confirmed, never exposed to the checkout page
cancelUrlRecommendedURL to return the buyer to your site after canceling
displayReferenceOptionalOrder reference shown to the buyer, up to 64 printable characters. orderId is never shown
publicMetadataOptionalUp to 10 buyer-visible key/value pairs (keys [A-Za-z0-9_.-]{1,40}, values up to 200 characters)
metadataOptionalMerchant-defined key-value pairs, private to you (webhooks, dashboard, API)
paymentMethodsOptional{ wallet?, transfer?, transferDefaultOpen? } — controls which payment methods the checkout shows, see Create a payment
deferTransferDepositOptionalREST API boolean, default false. Set true for hosted redirects to prepare the transfer address when checkout loads, instead of waiting during creation. The create response may omit transferDepositAddress. Fixed-customer address ownership checks always run during creation.
metadata.fixed_transfer_customer_idOptionalYour customer ID for a verified returning customer — reuses one fixed transfer deposit address across their orders (SDK: the fixedTransferCustomerId field). See Fixed deposit address
expiresAtOptionalISO-8601 timestamp. No cap and no default (omit = never expires on its own); allow an hour or more for programmatic payers

Optional header: Idempotency-Key (1–255 printable ASCII characters, per merchant). Same key + same body → the original order, HTTP 200, idempotentReplay: true; same key + different body → HTTP 409, code idempotency_key_reused; an unusable key → HTTP 400, code invalid_idempotency_key.

Response structure ​

json
{
  "paymentIntent": {
    "paymentId": "b1985d0b-2026-4f8c-bf75-59ea53fe5466",
    "id": "b1985d0b-2026-4f8c-bf75-59ea53fe5466",
    "status": "requires_payment",
    "orderId": "order_1001",
    "amount": "12.50",
    "currency": "USDC",
    "checkoutUrl": "https://checkout.tariapay.com/pi_b1985d0b-2026-4f8c-bf75-59ea53fe5466",
    "successUrl": "https://merchant.example/success",
    "cancelUrl": "https://merchant.example/cancel",
    "customer": {
      "email": "buyer@example.com",
      "name": "Alice"
    },
    "metadata": {
      "cartId": "cart_12"
    },
    "txHash": null,
    "paidAt": null,
    "expiresAt": null,
    "createdAt": "2026-03-30T00:00:00.000Z",
    "updatedAt": "2026-03-30T00:00:00.000Z"
  }
}

Beside paymentIntent, a create response also carries paymentConfig, availableChains, the payment-method flags and, once a direct-transfer deposit address is allocated (the default; not with deferTransferDeposit: true), transferDepositAddress and the structured transferInstructions (address, expiry, per-chain token contracts, decimals and exact minor-unit amounts, and the rules for the payer). The retrieve response carries the same two fields once the address exists.

Payment order IDs and checkout URLs ​

  • paymentId is the bare UUID without a prefix. Use this value when calling the Merchant API (queries, refunds).
  • checkoutUrl is the typed-prefix checkout address, of the form https://checkout.tariapay.com/pi_<uuid> (pl_ for payment links, su_ for subscription plans). Hand it to the buyer exactly as returned — never construct checkout URLs yourself. The path format may change between versions, and the checkoutUrl returned by the API is always the authoritative form.
  • Older checkout links you previously saved or shared (such as /payment-intents/<uuid> or /paylink/<slug>) remain valid indefinitely — they will not break or redirect.

Issuing a refund ​

Refunds must be initiated from your server. The current API performs a full refund to the original payer: the chain, currency, amount, and destination wallet all come from the confirmed original payment — the caller cannot override the refund address.

ts
const refund = await tariapay.paymentIntents.refund(
  "b1985d0b-2026-4f8c-bf75-59ea53fe5466",
  { reason: "Customer canceled the order" },
);
bash
curl -X POST "https://api.tariapay.com/v1/payment-intents/b1985d0b-2026-4f8c-bf75-59ea53fe5466/refunds" \
  -H "Authorization: Bearer tpk_..." \
  -H "Content-Type: application/json" \
  -d '{"reason":"Customer canceled the order"}'

A refund first atomically reserves the funds from your available balance for the payment's chain and currency. If the balance is insufficient, the API returns 422; after the on-chain submission it returns processing or completed, and repeated requests never transfer funds twice.

Error structure ​

json
{
  "error": {
    "type": "invalid_request_error",
    "code": "order_id_conflict",
    "message": "orderId already exists for merchant",
    "requestId": "req_123"
  }
}

Common errors ​

Status codeCommon causes
400Missing or malformed request fields
401API key missing, invalid, or revoked
409orderId already exists; or code fixed_transfer_active_payment — the customer's fixed transfer address is still held by another open order (resume or cancel that order first)
403Code address_sanctioned — the refund or withdrawal destination is on a sanctions list; do not retry. See Sanctions screening
422Merchant's available balance is insufficient for the refund
503Code screening_stale or screening_unavailable — refunds and withdrawals are paused until sanctions data refreshes; retry later
500Server error — record the requestId and contact support

Next steps ​