Architecture
The system at a glance: which component lives where, who calls whom, and what each side is responsible for.
End-to-end data flow
┌────────────────────────────── Your platform ─────────────────────────────┐
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐ │
│ │ POS terminal │───▶│ Transaction │───▶│ Webhook emitter │ │
│ │ / cashier │ │ service │ │ (signs + sends) │ │
│ └──────────────┘ └──────────────┘ └────────┬─────────┘ │
│ ▲ │ │
│ │ │ HTTPS POST │
│ ┌──────────────┐ │ X-Provider-Signature │
│ │ OAuth server │◀──── Pattern A only │ │
│ │ Order API │ │ │
│ └──────┬───────┘ │ │
│ │ │ │
└─────────┼─────────────────────────────────────────┼──────────────────────┘
│ │
│ GET /orders/{id} │ POST /webhooks/{provider}
│ Authorization: Bearer ... │
│ ▼
┌─────────┼─────────────────────────────── Paperless ─────────────────────┐
│ │ ┌──────────────────┐ │
│ │ │ Webhook ingest │ │
│ │ │ (verify, store, │ │
│ │ │ enqueue) │ │
│ │ └────────┬─────────┘ │
│ │ │ │
│ │ ▼ │
│ │ ┌──────────────────┐ │
│ └─────────────────────────────▶│ Worker (Celery) │ │
│ │ - fetch order │ │
│ │ - resolve cust. │ │
│ │ - write receipt │ │
│ └────────┬─────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────┐ │
│ │ PostgreSQL │ │
│ │ - receipts │ │
│ │ - customers │ │
│ │ - integrations │ │
│ └────────┬─────────┘ │
│ │ │
└─────────────────────────────────────────────────┼───────────────────────┘
│
▼
Customer mobile / web apps
What each side owns
| Component | Your platform | Paperless |
|---|---|---|
| OAuth 2.0 server | You host /oauth/authorize and /oauth/token (Pattern A only). |
Initiates the authorization-code flow. Stores encrypted tokens. |
| Merchant directory | You issue and own the canonical merchant ID. | Maps your merchant ID to a Paperless merchant record. |
| Location sync | You expose GET /locations (Pattern A only). |
Pulls locations on connect and on demand. |
| Order / receipt data | You own the source of truth and expose it via webhook + fetch (A) or push (B). | Snapshots the order into an immutable Receipt row. |
| Customer identifier | You stamp paperless_customer_id onto the order, or expose email/phone lookup. |
Resolves the identifier against its own customer DB. |
| Webhook signing key | You store the signing secret in a vault and sign every webhook. | Stores the same secret, verifies every webhook. |
| Idempotency | You must supply a stable, globally-unique external_id per order. |
Enforces uniqueness; duplicate deliveries are deduped silently. |
| Retry on delivery failure | You must retry non-2xx responses with exponential backoff. | Returns 5xx briefly during overload; safe to retry. |
Glossary
| Term | Meaning |
|---|---|
merchant | A business that uses your POS. One merchant may have many locations. |
location | A physical or logical store. One location belongs to exactly one merchant. |
order / transaction | A single completed sale. The unit of work Paperless ingests. |
receipt | Paperless's immutable snapshot of an order, attached to a customer. |
external_id | Your stable, globally-unique identifier for an order. Idempotency key. |
external_event_id | Your stable, globally-unique identifier for a webhook delivery (not the order). |
paperless_customer_id | A UUID issued by Paperless that identifies a customer. Stamped on orders. |
tender | A payment instrument applied to an order (card, cash, gift card, etc.). |
line item | One product or service row on an order. |
tax | A tax row on an order. ADDITIVE taxes are added on top; INCLUSIVE taxes are already in the line price. |
KMS | Key Management Service. Paperless encrypts every OAuth token at rest before storing it. |
DLQ | Dead-letter queue. Where webhook deliveries land after they exhaust their retry budget. |
Identifiers and their lifetimes
| ID | Issued by | Stable? | Used as |
|---|---|---|---|
merchant_id | You | Forever | Foreign key on every webhook and order. |
location_id | You | Forever | Where the sale happened. |
external_id (order) | You | Forever | Idempotency key. If you re-deliver the same order, Paperless will silently dedupe. |
external_event_id | You | Forever | Idempotency key for the webhook delivery itself. |
access_token | You (OAuth server) | Short-lived | Bearer token Paperless uses on Order API. Pattern A only. |
refresh_token | You (OAuth server) | Long-lived, rotates | Used to mint new access tokens. Pattern A only. |
paperless_customer_id | Paperless | Forever | UUID. Stamped on the order so the receipt finds its owner. |
Constraints that apply to every integration
- At-least-once delivery. You may deliver the same webhook more than once. Paperless dedupes by
external_event_idandexternal_id. - Order independence. Webhooks may arrive out of order. Each one is self-contained.
- UTC timestamps only. Anything else is rejected.
- Money as integer minor units. No floats.
1234+"USD"= $12.34. - TLS 1.2+ end-to-end. No plaintext HTTP, even in sandbox.
- PII minimization. Card PAN is never sent. Only
last4is permitted.