NodeRailsCRYPTO PAYMENT INFRASTRUCTURE
DocumentationAPI Reference
Dashboard

Payment Intents

A payment intent represents a single payment from a customer. It tracks the lifecycle from creation through authorization and capture. Settlement happens automatically after the escrow timelock expires. You can also cancel or refund payments.

Payment intent lifecycle

Status flowtext
CREATED → AUTHORIZED → CAPTURED → SETTLED
           ↘ CANCELLED
                       ↘ REFUND_PENDING → REFUNDED
                       ↘ FAILED

Create a payment intent

POST/payments/intents
💡

API key only

Creating payment intents requires a secret API key. JWT authentication is not supported for this endpoint.

Request body

ParameterTypeRequiredDescription
amountstringYesPayment amount (decimal string, e.g. "99.99")
currencystringNoFiat currency code (default: "USD")
customerAccountIdstringNoExisting customer UUID
externalIdstringNoYour system's order or reference ID (max 255)
allowedChains"ALL" | number[]NoAllowed blockchain chain IDs
allowedTokens"ALL" | string[]NoAllowed token identifiers
captureMode"AUTOMATIC" | "MANUAL"NoWhether to capture immediately or hold in escrow
successUrlstringNoRedirect URL after payment
cancelUrlstringNoRedirect URL on cancel
idempotencyKeystringNoPrevent duplicate intents (max 255)
metadataobjectNoArbitrary key-value metadata
SDK exampletypescript
const intent = await noderails.paymentIntents.create({
  amount: '99.99',
  currency: 'USD',
  captureMode: 'AUTOMATIC',
  allowedChains: [1, 137, 42161],   // Ethereum, Polygon, Arbitrum
  allowedTokens: 'ALL',
  metadata: { orderId: 'order_456' },
  idempotencyKey: 'order_456',
});

console.log(intent.id);     // "pi_xyz789"
console.log(intent.status); // "CREATED"
cURLbash
curl -X POST https://api.noderails.com/payments/intents \
  -H "x-api-key: nr_live_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "amount": "99.99",
    "currency": "USD",
    "captureMode": "AUTOMATIC",
    "allowedChains": [1, 137],
    "metadata": { "orderId": "order_456" }
  }'

List payment intents

GET/payments/intents

Query parameters

ParameterTypeDescription
appIdstringFilter by app UUID
statusstringFilter by status
pagenumberPage number (default: 1)
pageSizenumberItems per page (max 100)
SDK exampletypescript
const result = await noderails.paymentIntents.list({
  status: 'CAPTURED',
  page: 1,
  pageSize: 50,
});

for (const intent of result.data) {
  console.log(intent.id, intent.amount, intent.status);
}

Retrieve a payment intent

GET/payments/intents/:id
SDK exampletypescript
const intent = await noderails.paymentIntents.retrieve('pi_xyz789');
console.log(intent.status);    // "CAPTURED"
console.log(intent.txHash);    // "0x..."
console.log(intent.chainId);   // 1

Cancel a payment intent

POST/payments/intents/:id/cancel

Cancels a payment intent that hasn't been captured yet.

SDK exampletypescript
const cancelled = await noderails.paymentIntents.cancel('pi_xyz789');
console.log(cancelled.status); // "CANCELLED"

Refund a payment

POST/payments/intents/:id/refund
ParameterTypeRequiredDescription
reasonstringYesRefund reason (1–500 chars)
SDK exampletypescript
const refunded = await noderails.paymentIntents.refund('pi_xyz789', {
  reason: 'Customer requested refund',
});

console.log(refunded.status); // "REFUND_PENDING"

Response object

All responses are wrapped in { "success": true, "data": ... }. List endpoints add pagination with total, page, pageSize, and totalPages.

PaymentIntent object (create / cancel)json
{
  "success": true,
  "data": {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "appId": "b2c3d4e5-f6a7-8901-bcde-f23456789012",
    "customerAccountId": null,
    "externalId": "order_456",
    "amount": "99.99",
    "currency": "USD",
    "allowedChains": [1, 137, 42161],
    "allowedTokens": "ALL",
    "captureMode": "AUTOMATIC",
    "timelockDuration": 86400,
    "disputeStartDuration": 43200,
    "status": "CREATED",
    "authorizationMethod": null,
    "authorizationChainId": null,
    "authorizationTokenKey": null,
    "authorizationWalletAddress": null,
    "authorizationTxHash": null,
    "authorizationSignature": null,
    "authorizedAt": null,
    "cryptoAmount": null,
    "cryptoTokenKey": null,
    "cryptoTokenDecimals": null,
    "exchangeRate": null,
    "captureTxHash": null,
    "capturedAt": null,
    "captureAttempts": 0,
    "timelockEndsAt": null,
    "settledAt": null,
    "refundedAt": null,
    "refundTxHash": null,
    "refundReason": null,
    "platformFeeBps": 0,
    "expiresAt": "2025-01-16T10:30:00.000Z",
    "sourceType": null,
    "sourceId": null,
    "successUrl": null,
    "cancelUrl": null,
    "metadata": { "orderId": "order_456" },
    "idempotencyKey": "order_456",
    "createdAt": "2025-01-15T10:30:00.000Z",
    "updatedAt": "2025-01-15T10:30:00.000Z"
  }
}

PaymentIntent fields

idstringUnique payment intent UUID
appIdstringApp this payment belongs to
customerAccountIdstring | nullLinked customer UUID
externalIdstring | nullYour system's order or reference ID
amountstringPayment amount as a decimal string
currencystringFiat currency code (e.g. USD)
allowedChains'ALL' | number[]Permitted blockchain chain IDs
allowedTokens'ALL' | string[]Permitted token identifiers
captureModestringAUTOMATIC or MANUAL
timelockDurationnumberEscrow lock duration in seconds
disputeStartDurationnumberWindow (seconds) after capture during which a dispute can start
statusstringCREATED, AUTHORIZED, CAPTURED, SETTLED, CANCELLED, REFUND_PENDING, REFUNDED, or FAILED
authorizationMethodstring | nullDIRECT, PERMIT, or APPROVAL
authorizationChainIdnumber | nullChain ID used for payment
authorizationTokenKeystring | nullToken key used for payment
authorizationWalletAddressstring | nullPayer wallet address
authorizationTxHashstring | nullOn-chain authorization tx hash
authorizationSignaturestring | nullEIP-2612 permit signature, if applicable
authorizedAtstring | nullISO 8601 timestamp of authorization
cryptoAmountstring | nullToken amount paid (raw units)
cryptoTokenKeystring | nullToken key of the payment token
cryptoTokenDecimalsnumber | nullDecimal precision of the payment token
exchangeRatestring | nullUSD-to-token exchange rate at time of payment
captureTxHashstring | nullOn-chain capture tx hash
capturedAtstring | nullISO 8601 capture timestamp
captureAttemptsnumberNumber of capture attempts
timelockEndsAtstring | nullISO 8601 timestamp when the escrow timelock expires
settledAtstring | nullISO 8601 settlement timestamp
refundedAtstring | nullISO 8601 refund timestamp
refundTxHashstring | nullOn-chain refund tx hash
refundReasonstring | nullReason for refund
platformFeeBpsnumberPlatform fee in basis points
expiresAtstring | nullISO 8601 expiration timestamp
sourceTypestring | nullOrigin: CHECKOUT, PAYMENT_LINK, INVOICE, or SUBSCRIPTION
sourceIdstring | nullID of the originating resource
successUrlstring | nullRedirect URL after payment
cancelUrlstring | nullRedirect URL on cancel
metadataobjectArbitrary key-value pairs
idempotencyKeystring | nullDeduplication key
createdAtstringISO 8601 creation timestamp
updatedAtstringISO 8601 last-update timestamp
💡

Retrieve and list include relations

The retrieve endpoint adds nested transactions (Transaction[]), dispute (Dispute | null), and customerAccount (CustomerAccount | null). The list endpoint includes transactions only.

Refund response

The refund endpoint returns a custom object, not a full PaymentIntent:

Refund responsejson
{
  "success": true,
  "data": {
    "paymentIntentId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "transactionId": "c3d4e5f6-a7b8-9012-cdef-345678901234",
    "mtxmTxId": "mtxm_tx_id",
    "txHash": "0x...",
    "status": "PENDING"
  }
}