Skip to content

Create Payment

Create a payment and receive a unique payment ID.

Overview

When using the SoloPay widget, payment creation is handled automatically by the widget. This page is a reference API spec for understanding the internals or for custom implementations.

Created payments expire automatically after 5 minutes.

  • Auth: x-public-key header required (pk_xxx)
  • Chain and recipient address are determined by merchant configuration
  • tokenAddress must be whitelisted and enabled for the merchant

REST API

bash
curl -X POST https://gateway.dev.solonetwork.io/api/v1/payments \
  -H "x-public-key: pk_xxxxx" \
  -H "Origin: https://yourshop.com" \
  -H "Content-Type: application/json" \
  -d '{
    "orderId": "order-001",
    "amount": 10.5,
    "tokenAddress": "0xE4C687167705Abf55d709395f92e254bdF5825a2",
    "successUrl": "https://example.com/success",
    "failUrl": "https://example.com/fail"
  }'

Request Parameters

FieldTypeReq.Description
orderIdstringMerchant order ID (no duplicates per merchant)
amountnumberPayment amount (token units or fiat units)
tokenAddressaddressERC-20 token contract address (whitelisted & enabled for merchant)
successUrlstringRedirect URL on success
failUrlstringRedirect URL on failure
currencystringFiat currency code (e.g., USD, KRW). Triggers price conversion

currency option

When currency is provided, amount is treated as a fiat amount. The server automatically converts it using the latest 1-hour average price (TWAP) to determine the token amount. Example: amount: 10, currency: "USD" → pays the token amount equivalent to 10 USD based on the past 1-hour average price.

The 1-hour average dampens short-term price swings. The tokenPrice field in the response reflects the 1-hour average used for the conversion.

Response

Success (201 Created)

json
{
  "success": true,
  "data": {
    "paymentId": "0xabc123def456...",
    "orderId": "order-001",
    "chainId": 80002,
    "tokenAddress": "0xE4C687167705Abf55d709395f92e254bdF5825a2",
    "tokenSymbol": "SUT",
    "tokenDecimals": 18,
    "gatewayAddress": "0x...",
    "forwarderAddress": "0x...",
    "amount": "10500000000000000000",
    "recipientAddress": "0xMerchantWallet...",
    "merchantId": "0x...",
    "deadline": "1706281200",
    "successUrl": "https://example.com/success",
    "failUrl": "https://example.com/fail",
    "expiresAt": "2024-01-26T12:35:00.000Z",
    "tokenPermitSupported": true,
    "currency": "USD",
    "fiatAmount": 10.5,
    "tokenPrice": 1.0
  }
}

Error Responses

HTTPCodeCause
400TOKEN_NOT_ENABLEDToken is not enabled for this merchant
404TOKEN_NOT_FOUNDToken not in whitelist
400UNSUPPORTED_CHAINUnsupported chain
400CHAIN_NOT_CONFIGUREDMerchant has no chain configured
400RECIPIENT_NOT_CONFIGUREDMerchant recipient address not configured
400VALIDATION_ERRORInput validation failed
409DUPLICATE_ORDERorderId already used

Response Fields

FieldTypeDescription
paymentIdstringUnique payment identifier (bytes32 hash)
amountstringAmount in wei
gatewayAddressaddressPaymentGateway contract address
forwarderAddressaddressERC2771 Forwarder address (for Gasless)
merchantIdstringMerchant ID (bytes32)
deadlinestringServer signature deadline (Unix timestamp); required for pay() and gasless. Default: 1 hour (3600s)
expiresAtdatetimePayment expiry (5 minutes from creation)
tokenPermitSupportedbooleanWhether the token supports EIP-2612 Permit
currencystringFiat currency code (included only when requested)
fiatAmountnumberOriginal fiat amount (included only when requested)
tokenPricenumberLatest 1-hour average token price (TWAP) used for conversion (included only when requested)

When Using the Widget

When using the widget (@solo-pay/widget-js / @solo-pay/widget-react), there is no need to call this API directly — the widget handles it automatically.

See Widget Integration Guide

Next Steps

Non-custodial Web3 payment infrastructure for ERC-20 checkout, sponsored gas, and wallet-to-wallet settlement.