Skip to main content

Glossary

Common terms that appear across the CROSS Pay API, SDK, and Webhook documentation. Each entry follows the same shape: a one-line definition, an example, and where you'll encounter it.


Payment lifecycle

PaymentIntent

A server-side object representing the merchant's intent to start a single payment. Created by POST /v1/payments.

  • ID format: pay_<22-char base62> (e.g., pay_4xKqRtJp9aB2c7zNm0)
  • One PaymentIntent maps 1:1 to a single payment attempt
curl -X POST https://api.crosspay.io/v1/payments \
-H "Authorization: Bearer $CROSS_PAY_API_KEY" \
-d '{"currency":"USD","amount":"9.99","payer_uid":"user-123"}'
# → { "id": "pay_abc123", "status": "PENDING", "checkout_url": "..." }

Checkout

A session in which the buyer selects a payment method and interacts with the PG. Maps 1:1 to a PaymentIntent. ID format: cs_<16-char base62> (e.g., cs_a1b2c3d4e5f6g7h8).

The checkout_id itself acts as a capability token, so the browser can call /v1/checkout/{checkout_id} directly — without an API key.

Quote

A fee, tax, and total estimate for a specific payment method. Frozen at SelectQuote time and unchanged until the payment terminates.

{
"fee_rate": "0.029",
"fee_amount": "1450",
"estimated_tax": "5000",
"total_amount": "56450"
}

Session (PG session)

An internal object that ties a merchant's PaymentIntent to a payment record on an external PG (Worldpay / PayLetter / BinancePay / on-chain). Format: sess_<base62>.

Merchants don't handle this directly, but for on-chain payments you fetch contract call parameters via GET /v1/onchain/sessions/{session_id}.


Payment status (PaymentStatus)

For the full state machine and transition rules, see Webhooks Overview — Payment state machine.

PENDING

Immediately after PaymentIntent creation, before quote selection. The merchant cancel API is only allowed at this stage.

PROCESSING

The handover-to-external-PG window that begins right after POST /checkout/{id}/quotes (SelectQuote) creates a PG session. The server waits for the PG/chain terminal webhook (PAID / FAILED) or the expiry worker (EXPIRED).

Merchant branching example:

switch (payment.status) {
case 'PENDING':
return showCheckout(payment.checkout_url)
case 'PROCESSING':
return showWaitingScreen('PG processing — awaiting result') // not confirmed yet
case 'PAID':
return fulfillOrder(payment)
case 'FAILED':
case 'EXPIRED':
case 'CANCELLED':
return showFailureScreen(payment)
}

Terminal states

PAID / FAILED / EXPIRED / CANCELLED / PARTIALLY_REFUNDED / REFUNDED. These do not transition to other states (refunds are the exception, following PAID → PARTIALLY_REFUNDED → REFUNDED).


Authentication and security

Merchant API Key

A server-side secret required for /v1/payments/** calls. Passed via the Authorization: Bearer <key> header. Must not be exposed in the browser.

Production keys use the sk_live_ prefix. A separate sk_test_ prefix for the public sandbox environment is coming soon.

Idempotency-Key

A client-issued key that ensures the same request is processed only once even if it arrives multiple times. Cached in Redis for 24 hours; subsequent calls with the same key replay the original response.

POST /v1/payments HTTP/1.1
Idempotency-Key: 0190a1b2-c3d4-7e5f-89ab-cdef01234567

Reusing the same key with a different body returns 409 IDEMPOTENCY_CONFLICT.

Callback Secret (webhook secret)

A per-merchant secret used to verify signatures on the merchant's webhook endpoint. Stored encrypted at rest on the CROSS Pay side and issued out-of-band (email or partner channels).

Verification algorithm: HMAC-SHA256 over ${webhook-id}.${webhook-timestamp}.${body}. See Verifying Webhooks for details.

MAC2 (Worldpay HPP)

The HMAC-SHA256 signature Worldpay Hosted Payment Pages uses to detect tampering of buyer-redirect URLs. Computed over the query strings of successURL / failureURL / cancelURL.


Safeguards

FDS (Fraud Detection Service)

A fraud detection check run just before the /v1/checkout/** response. When blocking, it returns HTTP 200 with only the fds: { outcome: "DENY", code, message, ... } envelope.

{
"fds": {
"outcome": "DENY",
"code": "COUNTRY_BLOCKED",
"risk_level": "HIGH",
"risk_score": 92
}
}

Merchant SDKs must branch on fds.outcome, not on the HTTP status.

Stale webhook guard

If the merchant changes the payment method on the same checkout, payment.provider is updated. If the previous PG sends a delayed callback, the server detects a mismatch between payment.provider and the webhook's PG and ignores it with ACK 200 + WARN. The stale terminal event never reaches the merchant endpoint.


Delivery

event queue

The internal queue where payment domain events accumulate before they are delivered to the merchant. Events are captured in the same transaction as the PG callback, guaranteeing at-least-once delivery.

Standard Webhooks v1

The webhook envelope specification CROSS Pay follows (https://www.standardwebhooks.com). Three headers (webhook-id, webhook-timestamp, webhook-signature) handle identification, idempotency, and signature verification together.

at-least-once · dedup key

A webhook can arrive at least once — possibly more. Merchants must use the webhook-id header value as a dedup key to handle duplicates.

const seen = await redis.set(`webhook:${webhookId}`, '1', 'NX', 'EX', 86400)
if (!seen) return res.status(200).end() // already processed

Currency and amounts

amount (decimal string)

amount is always a string (to avoid JS Number precision loss). Exceeding the currency's ISO 4217 decimals returns 422 INVALID_AMOUNT.

CurrencyValid example
USD"9.99" (decimals=2)
JPY"500" (decimals=0)
USDT @ BSC"10.123456789012345678" (decimals=18)

amount_smallest_unit

An integer string passed directly to the token contract call for on-chain payments. Equivalent to amount × 10^decimals.

amount: "9.9", USDT @ Ethereum (decimals=6)
→ amount_smallest_unit: "9900000"

On-chain payments

PayGateway

The payment contract CROSS Pay deploys to each chain. The buyer's wallet calls it directly. Fetch the ABI and address via GET /v1/chains/{slug}.

pay_uuid

The payment identifier corresponding 1:1 to the PayGateway.pay(bytes16 uuid, ...) signature. Format: 0x + 32 hex characters (16 bytes). The wallet client passes the getBytes(pay_uuid) result directly into the contract call.

finality

The point at which the blockchain is considered to no longer reorg a transaction. CROSS Pay waits for finality before emitting the payment.completed event, so paid_at reflects the finality confirmation time, not the TX broadcast time.


Suggesting additional terms

If a term is missing from this glossary, please file an issue on GitHub Issues or email dev@to.nexus.