SaqSaq Docs
Best practices

Production checklist

Check everything before going to production. Each item links to the corresponding section.

Idempotency

Item
Unique and deterministic clientReference on every creation. See Idempotency.
Callback dedupe by id + status, not just id.
Persistent dedupe storage (Redis/DB), not in local memory.
Dedupe TTL ≥ 30 days.

Callbacks

Item
callbackUrl configured on every POST /pix, POST /withdraw, POST /internal-transfer.
Handler responds 2xx in under 5s. Heavy processing in queue/worker.
Tested with simulated payload via curl + ngrok.
Endpoint restricted to Saq's official IP (ask support).
Inspection via GET /user/callbacks configured for auditing.

Multi-tenant (if applicable)

Item
virtualAccount sent in all creations.
Listing filtered by virtualAccount.
Callback routing uses tx.virtualAccount, with fallback for unknown tenant.
New tenant onboarding does not require deploy (mapping in DB or dynamic config).

Money

Item
Amounts stored as integer in cents or NUMERIC(15,2), never FLOAT.
Cents ↔ reais conversion isolated in a helper, tested.
Callback validation: received amount matches expected order amount.
Fee (serviceFeeCharged) accounted for in reconciliation.
Minimum limits respected (charge ≥ R$ 1, withdrawal ≥ R$ 0.01, QR ≥ R$ 0.10).

Security

Item
Token in Secret Manager, not in versioned .env.
Token never exposed to the front-end.
Logger masks Authorization header and sensitive fields (payerDocument, pixKey).
Separate tokens for sandbox and production.
Documented rotation plan (when, who, how).
DICT queried before withdrawal by key on high amounts.

Error handling

Item
Retry only on 5xx and 429, with exponential backoff and jitter.
4xx (except 429) not retried.
Timeout handled by querying via clientReference before recreating.
Saq's requestId logged on every error.
Errors translated for the end user (does not expose raw message).

Pagination and reconciliation

Item
Listing iteration uses hasNextPage, not data.length.
limit ≤ 100.
Daily reconciliation job cross-checking GET /user/transactions with local orders table.
For large volumes, scheduled POST /user/report.
Status divergences trigger an alert.

Observability

Item
Structured logs with local id + Saq id + endToEndId + clientReference.
Metrics: creation success rate, p95 latency, errors by type.
Alerts: 5xx error > X% in short window, callback not processed > N minutes.
Distributed tracing (OpenTelemetry) propagating Saq's requestId.

Environment

Item
Sandbox used in development and testing.
Production only with real values and customers.
Separate environment variables (SAQ_TOKEN, SAQ_BASE_URL).
Webhook in production via stable URL (not temporary tunnel).

Operational

Item
Incident runbook: callback stopped arriving, persistent 5xx error, divergent balance.
Direct contact with Saq support (channel, SLA).
Documented callback resend procedure (POST /user/callbacks/resend).
Rollback plan for features touching withdrawal or transfer.

On this page