Best practices
Production checklist
Check everything before going to production. Each item links to the corresponding section.
| 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. |
| 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 PayZu's official IP (ask support). |
Inspection via GET /user/callbacks configured for auditing. |
| 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). |
| 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). |
| 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. |
| 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. |
PayZu's requestId logged on every error. |
Errors translated for the end user (does not expose raw message). |
| 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. |
| Item |
|---|
Structured logs with local id + PayZu 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 PayZu's requestId. |
| Item |
|---|
| Sandbox used in development and testing. |
| Production only with real values and customers. |
Separate environment variables (PAYZU_TOKEN, PAYZU_BASE_URL). |
| Webhook in production via stable URL (not temporary tunnel). |
| Item |
|---|
| Incident runbook: callback stopped arriving, persistent 5xx error, divergent balance. |
| Direct contact with PayZu support (channel, SLA). |
Documented callback resend procedure (POST /user/callbacks/resend). |
| Rollback plan for features touching withdrawal or transfer. |