GET STARTED

rostopay Documentation & API

rostopay is non-custodial biometric payment infrastructure. Your buyer authorizes with their live face on their own device; money moves bank-to-bank over RTP® and lands in the merchant account as an instant cash payment. You never touch card numbers, PCI scope or chargebacks.

Quickstart — 4 lines

Drop the SDK on your checkout. The rosto-pay button renders next to your other payment methods and handles the full face flow.

<!-- 1. load the SDK --> <script src="https://js.rostopay.com/v3"></script> <!-- 2. drop the button where your payment methods live --> <rosto-pay key="pk_live_oak_ember_112" amount="23.40" currency="usd"></rosto-pay>

That's it. On success the buyer sees the receipt, you receive a charge.settled webhook, and the money is already in your account — cash, final, no card networks in between.

Test mode & test faces

Keys prefixed pk_test_ run the entire flow against the sandbox — no real banks, no real faces. Use the built-in test personas to exercise every outcome:

TEST PERSONARESULT
face_okAuthorizes and settles instantly
face_no_livenessFails liveness — liveness_failed
face_deepfakeRejected by anti-deepfake — synthetic_media
face_insufficientBank declines — insufficient_funds
face_slow_bankSettles after 30 s — tests your pending UI

Test charges appear in the dashboard with a TEST badge and anchor to the Polygon Amoy testnet.

ACCEPT PAYMENTS

Checkout SDK

The web component accepts attributes for amount, metadata and callbacks. Events fire at every step so your UI can react.

<rosto-pay key="pk_live_…" amount="23.40" order-id="ord_5512" delivery-address="sync" <!-- buyer's saved address flows into the order --> discount="2%"> <!-- pass your card-fee savings to the buyer --> </rosto-pay> document.querySelector('rosto-pay') .addEventListener('settled', (e) => { // e.detail = { charge_id, proof_hash, amount, receipt_url } });
authorized settled failed cancelled

QR & in-person

Every payment link renders as a QR in the dashboard — print it at the counter, on the valet ticket or the table tent. For fixed points of sale, the merchant terminal shows a rotating QR bound to your register. The buyer scans with their phone camera; the face flow runs on their device, so you need zero hardware.

Already on Shopify, WooCommerce, Square, Toast or another platform? rostopay plugs in without code — see all Integrations →

API REFERENCE

Authentication

The API is REST over HTTPS at api.rostopay.com. Authenticate with your secret key as a bearer token. Secret keys (sk_live_…) live only on your server — the public key in the SDK can't move money.

curl https://api.rostopay.com/v1/charges \ -H "Authorization: Bearer sk_live_…"

Charges

A charge is created by the SDK or a payment link when the buyer's face authorizes. You read them; you don't create them server-side — only a live face can.

GET /v1/charges/ch_8C31FB09 { "id": "ch_8C31FB09", "status": "settled", // authorized | settled | failed | refunded "amount": "23.40", "net": "23.15", // flat fee, no percentage "rail": "rtp", "proof_hash": "0x8C31…FB09", // verify.rostopay.com "order_id": "ord_5512", "created": "2026-07-21T09:41:22Z" }

List with GET /v1/charges?from=…&to=… — cursor-paginated, filterable by status, location and register.

Refunds

Full or partial. The refund is a new bank-to-bank push back to the buyer, chained to the original proof hash — so it's publicly verifiable too.

POST /v1/refunds { "charge": "ch_8C31FB09", "amount": "23.40", "reason": "requested_by_customer" }

Errors

Standard HTTP codes plus a machine-readable body. The ones you'll actually see:

CODEMEANING
liveness_failedBuyer didn't pass biovital liveness — never charged
synthetic_mediaAnti-deepfake rejected the capture
insufficient_fundsBuyer's bank declined — nothing moved
bank_unavailableRail outage — retry with the same idempotency key
rate_limited429 — back off per Retry-After
WEBHOOKS

Events

Register an endpoint in the dashboard and rostopay POSTs signed JSON on every state change:

charge.authorized charge.settled charge.failed refund.settled invoice.paid payout.reconciled
{ "type": "charge.settled", "data": { "id": "ch_8C31FB09", "amount": "23.40", "proof_hash": "0x8C31…FB09" } }

Signatures & retries

Every delivery carries a Rosto-Signature header (HMAC-SHA256 of the body with your endpoint secret). Verify it before trusting the payload. Failed deliveries retry with exponential backoff for 72 hours; events are idempotent by event_id.

const ok = rostopay.webhooks.verify(req.body, req.headers['rosto-signature'], endpointSecret);
RESOURCES

Libraries & SDKs

Node.js
npm i rostopay
Python
pip install rostopay
Ruby
gem install rostopay
PHP
composer require rostopay
Go
go get rostopay.com/go
iOS / Android
native checkout kits
Is everything up?
Live status for the API, SDK, rails, webhooks and verify.
System status →

Changelog & versions

The API is date-versioned — pin yours with the Rosto-Version header. Breaking changes only ship in new versions; the SDK auto-updates within a major.

SDK v3.4
Jul 15, 2026
NEWCoercion-pattern detection on by default; new cancelled event; button renders 40% faster on low-end Android.
API 2026-06-01
Jun 01, 2026
NEWImmutable invoices & estimates (/v1/invoices, /v1/estimates) with public status; invoice.paid webhook.
SDK v3.3
Apr 22, 2026
CHANGEDdelivery-address="sync" now returns a structured address object; legacy string form still accepted in v3.
API 2026-03-01
Mar 01, 2026
NEWPayment links API; per-register QR endpoints; cursor pagination on all list calls. DEPRECATED page= pagination (removed 2027-01-01).
SDK v3.0
Jan 09, 2026
BREAKINGWeb component replaces the v2 iframe embed; one-line drop-in; v2 supported until Jan 2027.

Explore rostopay

Online cash payment, biometric checkout and pay-with-your-face resources.