01Overview
Cryptss Pay exposes a REST API over HTTPS. Requests and responses use JSON (UTF-8). No SDK required — any HTTP client works.
Authentication
Most endpoints require a logged-in session. Authentication is cookie-based: call POST /api/auth/signin (or /api/auth/demo) and the session cookie is set automatically. Public endpoints (pay links, tracking) need no session.
Roles
| Role | Description | Demo account |
|---|---|---|
user | Merchant / freelancer / SMB | demo@cryptss.com · demo1234 |
client | Payer on the client portal | client@acme.com · demo1234 |
admin | Platform operator console | admin@cryptss.com · demo1234 |
02Auth & sessions
Create accounts, sign in, and manage the session.
Create a merchant account. Creates a default USDC wallet automatically.
| Field | Type | Required | Notes |
|---|---|---|---|
email | string | yes | Unique |
name | string | yes | Your name or business |
business | string | no | Business name |
password | string | yes | Min 8 characters |
// 201 Created
{ "ok": true, "user": { "id": 5, "email": "me@studio.com", "name": "Me", "role": "user" } }
Sign in with email + password. Sets the session cookie.
| Field | Type | Required |
|---|---|---|
email | string | yes |
password | string | yes |
// 200 OK
{ "ok": true, "user": { "id": 1, "email": "demo@cryptss.com", "name": "Layla Haddad", "role": "user" } }
One-click demo login. Used by the sign-in page.
| Field | Type | Values |
|---|---|---|
role | string | user · client · admin |
Current session user. 401 when logged out.
Destroys the session.
Always returns success (no account enumeration).
03Invoices
Create, list, filter, cancel and remind invoices. Invoice numbers are auto-incremented (INV-2044, INV-2045 …).
List invoices for the signed-in user.
| Query | Type | Notes |
|---|---|---|
status | string | sent · paid · escrow · overdue · cancelled · draft |
q | string | Search number / client / amount |
// 200 OK
{ "invoices": [ { "id": 1, "number": "INV-2041", "token": "aZ…x", "client_name": "Acme Co.",
"client_email": "client@acme.com", "amount": "2350.00", "asset": "USDC",
"status": "escrow", "escrow": 1, "due_date": "2026-08-17", "memo": "Brand system",
"created_at": "…", "paid_at": "…", "pay_url": "https://cryptss.com/app#/pay/aZ…x",
"track_url": "https://cryptss.com/app#/track/aZ…x" } ] }
Create an invoice.
| Field | Type | Required | Notes |
|---|---|---|---|
client_name | string | yes | Client or company name |
client_email | string | no | Auto-linked to existing clients |
amount | number | yes | > 0, max 100,000,000 |
asset | string | no | USDC (default) · USDT · DAI |
due_date | string | no | YYYY-MM-DD |
escrow | bool | no | Hold funds in escrow until approved |
memo | string | no | Description / line item |
// 201 Created
{ "ok": true, "invoice": { "number": "INV-2044", "token": "…", "status": "sent", … } }
Cancel a payable invoice. 409 if already paid/escrowed.
| Field | Type | Required |
|---|---|---|
id | int | yes |
Logs a "reminder sent" notification for an overdue invoice.
| Field | Type | Required |
|---|---|---|
id | int | yes |
04Public pay links & tracking
No authentication needed — this is what a payer opens when they receive an invoice link.
Invoice snapshot for the pay page.
// 200 OK
{ "invoice": { "number": "INV-2044", "client_name": "Acme Co.", "amount": "650.00",
"asset": "USDC", "status": "sent", "escrow": false, "due_date": "…",
"memo": "…", "payee": "Studio Layla — Design", … } }
404 unknown token · 410 cancelled invoice.
Settle an invoice without an account.
| Field | Type | Required | Notes |
|---|---|---|---|
token | string | yes | Invoice token |
method | string | no | wallet (default) · card |
payer_name | string | no | Shown as payer |
// 200 OK — paid, or held in escrow when the invoice has escrow enabled
{ "ok": true, "status": "paid" | "escrow", "tx_hash": "0x…", "invoice": { … } }Timeline for the payment tracking page.
// 200 OK — steps include created, sent, payment received, escrow held/released
{ "steps": [ { "label": "Invoice created", "at": "…", "done": true }, … ] }05Payments
Settled and pending payments, newest first. Optional ?q= search.
// 200 OK
{ "payments": [ { "id": 1, "invoice_id": 1, "payer": "Acme Co.", "amount": "2350.00",
"asset": "USDC", "tx_hash": "0x…", "method": "wallet", "status": "settled", "created_at": "…" } ] }06Escrow
Funds from escrow invoices are held until the merchant releases them or a dispute is resolved.
List escrows (held · released · disputed).
Release a held escrow to the merchant wallet. 409 if not held.
| Field | Type | Required |
|---|---|---|
id | int | yes |
Open a dispute on a held escrow.
| Field | Type | Required |
|---|---|---|
id | int | yes |
reason | string | no |
07Wallet
Stablecoin balances across chains.
// 200 OK
{ "wallets": [ { "chain": "base", "asset": "USDC", "address": "0x…", "balance": "8420.00" }, … ] }Add demo funds to a wallet.
| Field | Type | Required | Notes |
|---|---|---|---|
chain | string | yes | base · polygon · arbitrum |
amount | number | yes | > 0 |
08Cash out
Cash-out history + KYC status.
| Field | Type | Required | Notes |
|---|---|---|---|
amount | number | yes | Must be ≤ wallet balance |
fiat | string | no | BHD (default) · AED · SAR |
bank_ref | string | no | e.g. NBB ····4471 |
422 insufficient_balance / 422 kyc_required.
Demo KYC — approves instantly.
09Virtual card
Card details (last4, frozen), monthly spend vs limit, recent spends.
Purchase with the card — debits the largest wallet.
| Field | Type | Required |
|---|---|---|
merchant | string | yes |
amount | number | yes |
403 card_frozen · 422 over_card_limit · 422 insufficient_balance.
Toggles frozen state. Returns { "ok": true, "frozen": bool }.
10Recurring billing
Recurring schedules (retainers / subscriptions).
| Field | Type | Required | Notes |
|---|---|---|---|
client_name | string | yes | |
amount | number | yes | |
asset | string | no | USDC default |
interval | string | no | weekly · monthly · quarterly |
next_date | string | no | YYYY-MM-DD |
Pause / resume. Body: { id }.
Delete. Body: { id }.
11Clients
Clients with per-client billed totals.
Body: { name, email?, company?, allowlist? }.
Add/remove a client from the agent allowlist. Body: { id }.
12x402 AI agent payments
The agent receives a machine-readable payment request and decides autonomously: settle (within policy), deny (vendor not allowlisted or over cap), or pause (over the human approval threshold).
Current policy + month spent.
// 200 OK
{ "policy": { "agent_name": "Acme Procurement Bot", "per_payment_cap": "1000",
"monthly_limit": "10000", "approval_threshold": "500", "allowlist_only": 1,
"wallet_address": "0x…" }, "month_spent": 300 }Update policy. Any subset of: agent_name, per_payment_cap, monthly_limit, approval_threshold, allowlist_only.
Ask the agent to pay. Use an existing invoice token, or vendor + amount.
| Field | Type | Notes |
|---|---|---|
invoice_token | string | Pay a specific invoice |
vendor | string | … or synthesize an invoice for this vendor |
amount | number | Required with vendor |
// Decision responses
{ "decision": "settled", "tx_hash": "0x…", "invoice": "INV-2046" }
{ "decision": "denied", "reason": "vendor_not_allowlisted" | "over_per_payment_cap" | "over_monthly_limit", … }
{ "decision": "paused", "reason": "over_approval_threshold", "approval_id": 12, "invoice": "INV-2047" }Human approves a paused payment. Body: { activity_id }. Settles the invoice.
Human denies a paused payment. Body: { activity_id }.
Agent decision log: request · check · settle · pause · approve · deny.
13AI copilot
Ask the copilot anything — it answers from your live account data (balances, invoices, overdue items, cash-out timing).
| Field | Type | Required |
|---|---|---|
message | string | yes |
// 200 OK
{ "reply": "Your wallets hold $11,512.50 in total across Base, Polygon and Arbitrum…" }
nemotron-3-ultra-550b via NVIDIA_API_KEY; without a key a grounded local copilot answers from the live database.14Analytics & tax
Last 12 months of settled volume.
Top clients by settled volume.
Invoice status distribution.
Quarterly settled totals + platform fees for the year. Optional ?year=.
// 200 OK
{ "year": 2026, "years": ["2026","2025"], "quarters": [ { "quarter": "Q1", "total": 6080, "fees": 60.8, "n": 2 }, … ],
"total": 20010, "fees": 200.1 }Full-year CSV download of settled payments with fees.
15Notifications
Latest 30 notifications + unread count.
// 200 OK
{ "notifications": [ { "id": 1, "title": "Payment received", "body": "INV-2039 · Acme Co. paid 3,200.00 USDC",
"kind": "payment", "read": 0, "created_at": "…" } ], "unread": 3 }Mark one ({ id }) or all (empty body) as read.
16Client portal
For client-role users — the payer's view of their bills.
Due totals, escrow held, paid totals, wallets.
Invoices sent to this client.
Pay a bill from the client wallet.
| Field | Type | Required | Notes |
|---|---|---|---|
invoice_id | int | yes | |
method | string | no | wallet · card |
422 insufficient_balance if the client wallet can't cover it.
Payment history with tx hashes.
Saved payment methods.
17Admin console
Requires the admin role. All other roles get 403.
Platform-wide numbers.
// 200 OK
{ "users": 3, "merchants": 1, "volume": 26960, "payments_n": 13, "fees": 269.6,
"escrow_held": 2350, "disputes_open": 0, "cashouts_pending": 2, "agent_volume": 300 }Merchants with volume + invoice counts.
Open disputes.
Body: { id, outcome: "release" | "refund" }.
Pending cash-outs / KYC queue.
Body: { id, decision: "approved" | "rejected" }.
Provider health with live latency probes.
18API keys (developers)
Key list — prefixes only. Full keys are shown once at creation.
Create a key. Body: { label? }.
// 201 Created — full key returned ONCE
{ "ok": true, "id": 3, "key": "ck_live_…" }Revoke a key. Body: { id }.
19Errors & status codes
Errors always return JSON: { "error": "machine_readable_code" }, plus optional detail fields.
| Code | Meaning |
|---|---|
200 / 201 | OK / Created |
401 | Not authenticated (unauthorized, session_expired) |
403 | Role gate (admin_only) or card_frozen |
404 | Unknown endpoint, invoice, escrow, token |
409 | State conflict (cannot_cancel, not_held, invoice_not_payable) |
410 | invoice_cancelled |
422 | Validation (invalid_amount, client_required, insufficient_balance, over_card_limit, …) |
429 | Rate limited |
500 | Server error |
ck_live_ prefix is shown, the full key is hashed (sha256) in the database.
Cryptss