Appearance
Security
What Maytes does, and what your integration must do, to keep payments safe. Most of this boils down to one rule: everything secret lives on your server.
Card data never touches you
Your customer enters their card details in the Maytes-hosted checkout window, and payments are processed by our payment provider. Card numbers never pass through your servers, your frontend, or the Maytes merchant API — so integrating Maytes does not put card data in your PCI scope. Don't collect card details yourself "on behalf of" the checkout; there is no API for submitting them and no reason to hold them.
Your three secrets
| Secret | Used for | If it leaks |
|---|---|---|
client_secret (per environment) | Minting OAuth access tokens | Anyone can act as your merchant account — create, capture, cancel, refund. |
| Webhook signing secret (per subscription) | Verifying that deliveries came from Maytes | Anyone can forge "authorized" events at your endpoint. |
| OAuth access tokens | Every merchant API call | Same power as the credentials, until expiry. |
Rules for all three:
- Server-side only. Never in browser or mobile code, never in your repo, never in client-reachable config. The Checkout Button is designed around this — it calls your backend, and your backend calls Maytes.
- Store them in a secret manager or environment variables injected at deploy time.
- Separate per environment. Test and production have independent credentials and webhook secrets; a leaked test secret shouldn't be a production incident.
- Don't log them. Redact
authorizationheaders and token responses from request logging.
Verify every webhook delivery
Your webhook endpoint URL is guessable; the X-Maytes-Signature header is what proves a request came from Maytes. Verify it on every request — raw body, constant-time comparison, all v1 entries, and a timestamp tolerance (we recommend 5 minutes) to blunt replay of captured requests. Reject failures with a 4xx and don't process the payload. The full algorithm and copy-paste verifiers for Node, Python, and PHP are in Webhooks → Verify the signature.
Rotate secrets without downtime
- Webhook signing secret: rotation has a built-in 2-hour dual-signature grace window, so you can rotate on a schedule (or on staff departure) without dropping deliveries — see the rotation runbook. For a suspected leak,
revoke_previous=truekills the old secret immediately. - OAuth credentials: contact Maytes support to reissue. Treat a suspected
client_secretleak as urgent — until it's rotated, the holder can move money on your account.
Trust server-side state, not the browser
Everything a shopper's browser tells you can be forged — including a landing on your return_url. Before fulfilling an order:
- In the webhook flow, fulfil on your own capture success (a call your server made with its own credentials) — never on the redirect.
- In the legacy flow, your success page must call capture (or
GETthe checkout) server-side and branch on the API's answer — never fulfil just because the shopper reached the page. - Use the capture assertions (
expected_total_amount,currency,merchant_order_id) so a mixed-up ID can't capture the wrong order.
Handle customer data minimally
The optional customer_data block on create (name, email, mobile) exists to pre-fill the shopper's Maytes experience. Send it only when you have it and need it — don't invent placeholder values, and treat what you send as personal data under your privacy obligations. Maytes stores it encrypted at rest.
Transport
All Maytes endpoints are HTTPS-only, and your webhook endpoint must be HTTPS too. Webhook bodies are signed for authenticity and integrity — TLS already provides confidentiality in transit.
What's next
- Webhooks — signature verification and secret rotation in full.
- Authentication — the OAuth token lifecycle.
- Sandbox environment — including the signature-rejection and duplicate-delivery checks in the go-live list.
