Best practices
The security model for payment acceptance — PCI DSS scope, what PayMongo handles vs what the merchant is responsible for, and best practices for keeping payment data safe across all integration types.
Overview
Accepting payments involves handling sensitive financial data. PayMongo is certified as a PCI DSS Service Provider Level 1 — the highest level of compliance — which means PayMongo handles the most security-critical parts of payment processing. But your integration still has responsibilities.
This page breaks down what PayMongo handles, what you're responsible for, and the specific practices that keep your integration secure.
PCI DSS scope breakdown
| Responsibility | PayMongo handles | Your integration handles |
|---|---|---|
| Card number storage | PayMongo tokenizes and stores card data | Never store raw card numbers |
| 3D Secure processing | PayMongo manages 3DS 2.0 | Redirect customers to 3DS URLs, handle returns |
| Encryption in transit | TLS on all API endpoints | Ensure your server makes HTTPS-only requests |
| Fraud detection | Machine learning models, Fraud and Risk team | Monitor your orders for unusual patterns |
| Vulnerability scanning | Continuous scanning, third-party pen testing | Keep your own dependencies and server updated |
| PCI audit | Annual audits by PCI-certified assessors | Maintain your own SAQ (Self-Assessment Questionnaire) based on your integration type |
Do's and don'ts
API keys
| Do | Don't |
|---|---|
| Store secret API keys in environment variables or a secrets manager | Hardcode secret keys in source code |
| Use the public API key in frontend code | Expose your secret key in the browser, a mobile app, or a public repository |
Card data
| Do | Don't |
|---|---|
| Collect card details client-side and create a Payment Method using the public key | Send raw card numbers, expiry dates, or CVCs to your server |
| Use PayMongo's tokenization to handle card data | Store card data in your own database, even temporarily |
| Let PayMongo handle card validation | Log request bodies that contain card details |
Webhooks
| Do | Don't |
|---|---|
| Verify that webhook events come from PayMongo using the webhook secret | Trust payment status from the redirect URL query parameters alone |
| Confirm payment status server-side by retrieving the Payment Intent before fulfilling | Fulfill orders based solely on a client-side success response |
| Use separate webhook endpoints for test and live modes | Use the same webhook endpoint for both environments |
HTTPS
| Do | Don't |
|---|---|
| Enforce HTTPS on all pages where payments are initiated | Serve checkout pages over HTTP |
Use your return_url (after 3DS/redirect) to retrieve Payment Intent status server-side | Trust the URL parameters on return without server-side verification |
3D Secure as a fraud mitigation tool
PayMongo applies 3D Secure 2.0 automatically for card payments where it's available. When a transaction is successfully authenticated with 3DS:
- Liability for fraud-related chargebacks shifts from you to the issuing bank
- The customer's bank bears the loss if a 3DS-authenticated transaction is later disputed as fraudulent
This doesn't cover disputes for other reasons (product not received, subscription cancellation, etc.) — but it significantly reduces your fraud exposure for card transactions.
Webhook signature validation
PayMongo signs webhook events so you can verify they genuinely come from PayMongo. Validate the signature before processing any webhook:
- Retrieve the
X-Paymongo-Signatureheader from the request - Compute the HMAC-SHA256 of the raw request body using your webhook secret
- Compare the computed signature to the header value
Reject any request where the signatures don't match — it may be a forged event.
Keeping your integration secure over time
- Regularly rotate API keys
- Monitor webhook delivery logs in the PayMongo dashboard for unexpected failures
- Keep server-side dependencies (languages, frameworks, libraries) up to date
- Review PayMongo's API changelog for deprecations or security-related updates
- Test your integration in test mode after any significant change before deploying to production
Updated about 4 hours ago