Skip to content

Create a payment order

A payment order connects a business order in your system to the Taria Pay payment flow. When your server creates a payment intent, it receives a paymentId and a checkoutUrl.

  • With Hosted Checkout, the frontend redirects to checkoutUrl.
  • With the Checkout Button, the button on your page opens checkoutUrl.
  • With the Checkout Panel, the frontend passes paymentId to <CheckoutPanel />.

Who makes the request

The request must come from your server. Never call the Taria Pay API directly from the browser, and never put an API key in frontend code, mobile app bundles, or public repositories.

FieldRequiredDescription
orderIdRequiredYour own order ID; must be unique within your merchant account
amountRequiredThe order amount; a string is recommended
currencyRequiredUSDC, USDT, or EURC — the primary coin
acceptedCurrenciesOptionalExtra coins the hosted checkout may offer, e.g. ["USDC","USDT"]. The primary currency is always included. Omit to show only currency.
successUrlRecommendedWhere the buyer returns after paying
cancelUrlRecommendedWhere the buyer returns after canceling
customerOptionalBuyer email, name, and other details
metadataOptionalYour business context, e.g. a cart ID
paymentMethodsOptionalControls which payment methods the checkout page shows, see below
fixedTransferCustomerIdOptionalGive a verified returning customer a fixed transfer deposit address, see below
expiresAtOptionalOrder expiration time, ISO-8601 format

SDK example

ts
const paymentIntent = await tariapay.paymentIntents.create({
  orderId: "order_1001",
  amount: "12.50",
  currency: "USDC",
  acceptedCurrencies: ["USDC", "USDT"],
  successUrl: "https://merchant.example/success",
  cancelUrl: "https://merchant.example/cancel",
  customer: {
    email: "buyer@example.com",
    name: "Alice",
  },
  metadata: {
    cartId: "cart_12",
  },
});

return {
  paymentId: paymentIntent.paymentId,
  checkoutUrl: paymentIntent.checkoutUrl,
};

REST example

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",
    "acceptedCurrencies": ["USDC", "USDT"],
    "successUrl": "https://merchant.example/success",
    "cancelUrl": "https://merchant.example/cancel",
    "customer": {
      "email": "buyer@example.com",
      "name": "Alice"
    },
    "metadata": {
      "cartId": "cart_12"
    }
  }'

Controlling the checkout's payment methods

By default the checkout page offers both wallet payment and direct transfer (on supported networks), with the transfer section collapsed. You can adjust this per order with the optional paymentMethods field:

json
{
  "orderId": "order_1001",
  "amount": "12.50",
  "currency": "USDC",
  "paymentMethods": {
    "wallet": true,
    "transfer": true,
    "transferDefaultOpen": true
  }
}
FieldDefaultDescription
wallettrueShow the connect-wallet payment module
transfertrueOffer direct transfer; false also makes the server reject transfer requests for this order
transferDefaultOpenfalseRender the transfer section expanded; forced on when wallet is false

Rules and fail-safes:

  • wallet and transfer cannot both be false — that returns a 400.
  • Both switches are enforced server-side, not just hidden in the UI: the endpoint behind a disabled method returns 403.
  • Direct transfer remains subject to network support. If you set wallet: false but the network the order is currently on does not support transfer, the checkout automatically falls back to showing the wallet module — and accepts wallet payments on it — so the buyer always has a way to pay. Switching to a transfer-capable network hides the wallet module again.
  • Omitting the field keeps today's behavior exactly; existing integrations need no changes.

Fixed deposit address for returning customers

By default, every order gets a brand-new transfer deposit address that is never reused. For identity-verified returning customers, you can instead give each customer one fixed deposit address that stays the same across all of their orders — and across every supported network. Repeat buyers who pay from an exchange can save the address once (for example in their exchange's address book) and skip copying a new address every time.

Pass your own customer ID when creating the order:

ts
const paymentIntent = await tariapay.paymentIntents.create({
  orderId: "order_1001",
  amount: "12.50",
  currency: "USDC",
  fixedTransferCustomerId: "user_42", // your customer ID — verified accounts only
})

Over REST, set the reserved metadata key instead (this is exactly what the SDK field does):

json
{
  "orderId": "order_1001",
  "amount": "12.50",
  "currency": "USDC",
  "metadata": {
    "fixed_transfer_customer_id": "user_42"
  }
}

Rules and responsibilities:

  • Only pass customers whose identity you have verified — a signed-in account with a verified email, a wallet-signature login, or an equivalent check. The buyer will rely on this address staying theirs, so never derive it from unverified input such as a free-typed email. For guests and unverified users, simply omit the field — they keep getting fresh per-order addresses.
  • The address is scoped to your merchant account plus the customer ID you pass. Use a stable, opaque ID from your own system (a user ID, not an email that can change).
  • One open order at a time. While a customer has an unpaid order using the fixed address, creating another order with the same fixedTransferCustomerId returns 409 with code fixed_transfer_active_payment. Resume or cancel the customer's previous order instead of retrying — with a stored orderId you can look it up via retrieveByOrderId.
  • Only funds sent while the order is open count toward it. Each new order starts from a fresh balance checkpoint on the address; money that arrived before the order was created (or between orders) is not automatically applied to a later order. Tell buyers to transfer only after opening an order — if funds are sent outside one, contact support to recover them.
  • Wallet payments are unaffected: the checkout still offers both methods as usual, and payment results and webhook events are identical either way.
  • The fixed address only changes which deposit address transfer payments use. Everything else — confirmation, wrong-network recovery, webhooks, the transfer refund process — works the same as ordinary direct transfers (see Supported payment methods).

Important rules

  • A single payment order supports both wallet payments and direct transfers (the checkout page shows an order-specific deposit address); you do not need to pass any payment-method fields. Both methods produce identical payment results and webhook events. To adjust the presentation, see paymentMethods above; for background see Supported payment methods.
  • orderId must be unique within your merchant account.
  • Creating the same orderId again usually returns a conflict error. If create times out, call retrieveByOrderId instead of minting a new id.
  • checkoutUrl looks like https://checkout.tariapay.com/pi_<uuid>. Always use the value returned by the API as-is — do not construct checkout URLs yourself. The paymentId itself is a plain UUID with no prefix.
  • Merchants do not need to submit an on-chain settlement address.
  • You usually do not need to pass chainId when creating a payment order; the checkout page shows the payment networks currently available.
  • Never treat successUrl as the final payment result.

Next steps