Pay

A payment gateway and processing engine

Payment intents, charges, refunds and disputes over a REST API. Every movement of money is written to a double-entry ledger that must balance, and every state change emits a signed webhook. Amounts are integers in minor units, so nothing is ever lost to a floating-point rounding error.

Correct by construction

A ledger transaction whose debits do not equal its credits is rejected, not written. The books can always be reconciled because an unbalanced entry cannot exist.

Safe to retry

Send an Idempotency-Key and a repeat is replayed from the stored response. The same key with a different body is refused, so a client bug cannot charge twice.

Secrets stay secret

API keys are stored only as a SHA-256 hash and card numbers never reach the database. A dump of this database cannot be replayed as a login or a payment.

Collect a payment

curl https://pay.example.com/api/v1/payment_intents \
  -H "Authorization: Bearer sk_test_..." \
  -H "Idempotency-Key: order_1043" \
  -d amount=2500 -d currency=USD

# -> { "id": "pi_...", "status": "requires_payment_method",
#      "client_secret": "pi_..._secret_..." }

curl .../payment_intents/pi_.../confirm \
  -d client_secret=pi_..._secret_... \
  -d payment_method[card][number]=4242424242424242 \
  -d payment_method[card][exp_month]=12 \
  -d payment_method[card][exp_year]=2030 \
  -d payment_method[card][cvc]=123

# -> { "status": "succeeded", "amount": 2500 }

API surface

MethodPathPurpose
POST/api/v1/payment_intentsCreate an intent to collect a payment
POST/api/v1/payment_intents/:id/confirmConfirm with a card; returns succeeded, requires_action or a decline
POST/api/v1/payment_intents/:id/actionComplete a 3-D Secure challenge
POST/api/v1/payment_intents/:id/captureCapture a manually-authorised charge
POST/api/v1/charges/:id/refundRefund all or part of a captured charge
GET/api/v1/ledgerThe double-entry ledger, with a balance check
POST/api/v1/webhook_endpointsRegister a URL to receive signed events
GET/api/v1/eventsThe event log
GET/api/v1/disputesChargebacks raised against you
GET/api/healthLiveness plus a database round-trip

Try the guided flow at /demo — it runs a real payment end to end against the API.