Skip to content

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

SecretUsed forIf it leaks
client_secret (per environment)Minting OAuth access tokensAnyone can act as your merchant account — create, capture, cancel, refund.
Webhook signing secret (per subscription)Verifying that deliveries came from MaytesAnyone can forge "authorized" events at your endpoint.
OAuth access tokensEvery merchant API callSame 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 authorization headers 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=true kills the old secret immediately.
  • OAuth credentials: contact Maytes support to reissue. Treat a suspected client_secret leak 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 GET the 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.