Invoice numbers
Every payment has a 32-char hex payment_id (the gateway’s internal UUID) AND a human-readable invoice_number shown to PSPs and surfaced in dashboards / receipts / support tickets. Set invoice_prefix on POST /v1/payments to control the readable form.
Format
Section titled “Format”<PREFIX>-<6-digit zero-padded global seq>Examples:
FTY-PRO-000042— fotoyu Pro plan, 42nd payment everBOOK-000043— book.uncle-z.com bookingQUAY-MO-000044— Quay monthly subscriptionHRDEX-T2-000045— HRDex Tier-2 subscriptionPOS-000046— posz retail transaction
The 6-digit suffix is a single global sequence shared across the entire gateway, not per-product. Intentional — a typo’d prefix can’t accidentally collide with another product’s space.
Prefix rules
Section titled “Prefix rules”^[A-Z][A-Z0-9-]{0,11}$- Uppercase letters / digits / dashes only
- Must start with a letter
- 1–12 characters total
The 6-digit suffix is appended by the gateway. Keep your prefix under 12 chars to leave headroom.
Per-product convention
Section titled “Per-product convention”Use these — don’t invent new ones without checking ops first:
| Product | Prefix shape | Examples |
|---|---|---|
book.uncle-z.com | BOOK (single, no tier) | BOOK-000042 |
fotoyu | FTY-<tier> | FTY-PRO-000042, FTY-POWER-000043, FTY-B-000044 |
hrdex | HRDEX-<tier> | HRDEX-T1-000042, HRDEX-T2-000043 |
Quay | QUAY-<plan> | QUAY-MO-000042 (monthly), QUAY-YR-000043 (yearly) |
posz | POS | POS-000042 |
What happens if you skip invoice_prefix
Section titled “What happens if you skip invoice_prefix”The gateway falls back to bare 32-char hex (payment.id formatted). Works, but unreadable in PSP dashboards / support tickets. Always set invoice_prefix for live traffic.
How PSPs see it
Section titled “How PSPs see it”| PSP | Field |
|---|---|
| NICEPAY | referenceNo (max 40 chars) |
| Polar | passed via metadata.gateway_invoice_number; visible in Polar’s order detail view |
| PayPal | invoice_id (max 127 chars) |
Why a global sequence
Section titled “Why a global sequence”- Cross-product collisions are impossible by construction.
- Operators searching dashboards see
BOOK-000042and immediately know it’s payment #42 across the entire portfolio, regardless of which product issued it. - Sequence is in Postgres (
payment_invoice_seq) — atomic, no race conditions. - 6 digits = 1M payments. We’ll widen if we get there.
Backward compatibility
Section titled “Backward compatibility”Older payments created before the invoice_prefix feature use bare hex. The gateway’s webhook resolver accepts BOTH shapes — first hex-decodes, fallback to FindByInvoiceNumber. So legacy and new can coexist on the same merchant.