Skip to content

Authentication & Security


Store API Keys Securely

API keys grant full access to your merchant account. Treat them as secrets.

Why: A leaked API key allows anyone to initiate transactions, query your data, or exhaust your balance. Rotating a compromised key under pressure is error-prone and disruptive.

Recommended approach:

  • Store keys in a secrets manager (e.g., AWS Secrets Manager, Azure Key Vault, HashiCorp Vault) or encrypted environment variables — never in source code, config files committed to version control, or client-side code.
  • Restrict access to API keys to the minimum set of services and team members that need them.
  • Audit access to your secrets store regularly.
# Good — loaded from environment at runtime
api_key = os.environ["PAYALO_API_KEY"]

# Bad — hardcoded in source
api_key = "<your-api-key>"

Rotate API Keys Periodically

Why: Regular rotation limits the window of exposure if a key is compromised without your knowledge.

Recommended approach:

  • Establish a rotation schedule (e.g., quarterly).
  • Support multiple active keys during the rotation window: deploy the new key to all services before revoking the old one.
  • Contact your account manager to issue a new key and schedule deactivation of the old one.

Enforce HTTPS / TLS

Why: API keys are transmitted in HTTP headers. Without TLS, they are visible to anyone who can observe network traffic.

Recommended approach:

  • Always use https:// for all gateway requests. The gateway rejects plain HTTP.
  • Ensure your resultUrl (callback endpoint) is also served over HTTPS.
  • Keep your TLS libraries and certificates up to date. Disable legacy protocols (TLS 1.0, 1.1).
  • Validate the gateway's TLS certificate in your HTTP client — do not disable certificate verification, even in staging.

Validate Callback Authenticity

Why: Your callback endpoint is publicly reachable. Without verification, an attacker could forge callback requests to manipulate your transaction state.

Recommended approach:

  • On every incoming callback, verify that the X-API-KEY header matches the API key issued for your brand using a constant-time comparison so a forged key cannot be probed via response timing.
  • Reject any request where the header is missing or does not match.
  • Restrict your callback endpoint to HTTPS only.
import secrets

def handle_callback(request):
    presented = request.headers.get("X-API-KEY", "")
    if not secrets.compare_digest(presented, EXPECTED_API_KEY):
        return Response(status=401)
    # Process the callback...