Security Guide
Core security practices merchants should follow when integrating with Chapa.
This guide covers the core security practices merchants should follow when integrating with Chapa Payments, Payouts, Refunds, Webhooks, and Virtual Accounts.
Security is a shared responsibility:
- Chapa secures the platform, encrypts data in transit and at rest, and enforces platform policies.
- Merchants must secure API keys, verify payment results, protect webhook endpoints, and prevent fraud and misuse.
1. Protect Your API Keys
Use the right key in the right place
- Secret keys (
CHAPA_TEST_...,CHAPA_LIVE_...) must be used only on your backend - Never expose secret keys in frontend apps, mobile apps, or public repositories
Storage best practices
- Store keys in environment variables or a secrets manager
- Rotate keys periodically
- Limit who has access to live keys
- Separate test and live configurations
2. Always Verify Payments Server-Side
Do not trust:
- Redirect URL parameters
- Client-side callbacks
- "Success" UI screens alone
Always confirm with:
GET /v2/payments/{reference}/verifyFor payouts:
GET /v2/payouts/{reference}/verifyOnly fulfill orders or mark payouts complete after verification.
3. Webhook Security
Webhooks deliver the final state for payments, payouts, and refunds.
Enforce HTTPS
Accept webhooks only on HTTPS endpoints.
Validate authenticity (recommended)
At minimum:
- Allowlist Chapa IPs (if you maintain a network boundary)
- Verify event consistency by calling verification endpoints
- Reject unexpected payloads or missing required fields
Handle retries safely (idempotency)
Chapa may retry webhook delivery if your endpoint fails or times out.
Your webhook handler must be idempotent:
- Use event +
chapa_reference(ormerchant_reference) as a unique key - Never double-fulfill an order or double-mark a transaction as paid
4. Use Idempotency Keys for Writes
For all create/mutate operations, use an Idempotency-Key:
- Payment initialization
- Direct charge initiation
- Payouts
- Refunds
- Virtual account deposits and deductions
Idempotency prevents:
- Double charging
- Duplicate payouts
- Duplicate refunds
- Duplicate wallet debits
5. Secure Customer Data
Treat the following as sensitive data:
- Phone numbers
- Email addresses
- Bank account numbers
- Internal references and metadata
Best practices
- Encrypt sensitive data at rest if needed
- Apply least-privilege access to databases and logs
- Avoid logging full payloads that contain PII
- Mask PII in logs (e.g.
2517*****727)
6. Never Store PINs or OTPs
If you support Direct Charge authorization flows:
- Never store PIN or OTP values
- Never log PINs or OTPs
- Collect input securely
- Send only over HTTPS
- Discard immediately after submission
7. Prevent Replay and Tampering
Webhooks
- Reject duplicate events (idempotent processing)
- Validate state transitions (e.g. success should not revert to pending)
- Optionally re-verify high-value transactions
Merchant references
- Ensure
merchant_referenceis unique per transaction - Avoid predictable references if exposed externally
8. Environment Safety (Test vs Live)
- Test with
CHAPA_TEST_... - Go live with
CHAPA_LIVE_... - Never mix environments
If you see errors like:
"API key environment does not match business environment."...it usually indicates a test/live mismatch.
9. Minimum Security Checklist (Go-Live)
Before moving to production, confirm:
| Requirement | Status |
|---|---|
| Live API keys stored securely (not in code) | Required |
| Webhook endpoint uses HTTPS and is reachable | Required |
| Webhook handler is idempotent | Required |
| Payment and payout verification enforced server-side | Required |
| Logs do not store PII or secrets | Required |
| Refund and payout actions are restricted to authorized roles | Required |
| Monitoring and alerts are enabled for failure spikes | Recommended |
Next Steps
- Accept Payment - Initialize payments
- Webhooks - Handle webhook events
- Verify Payment - Verify transaction status