Payvala Security protects the connections, API requests, and information exchanged between Payvala and its partner financial institutions (FIs). It helps ensure that only trusted institutions can connect, make authorized requests, and access the data they are permitted to use.
Security works through multiple layers. Network controls determine which connection path can reach Payvala. Client certificates and access tokens help verify the institution, while request signatures help confirm that API requests are genuine and have not been changed. Payvala also checks permissions and validates requests before processing them.
Security also includes protecting sensitive information, managing certificates and keys safely, keeping each institution's data separate, and preparing for security incidents. Merchant-facing APIs and Soundbox devices use separate security methods from FI API connections.
This overview introduces the security model and summarizes each layer. Each topic is explained in full on one dedicated page. Every requirement is labeled Confirmed, Provisional, Proposed, or Open, and values marked † are provisional. Provisional, proposed, and open items must not be treated as final production commitments.
Payvala protects each financial institution (FI) connection through several checks. First, the FI connects through one approved network path: a private connection or the public path through Cloudflare. The network path controls which traffic can reach Payvala, but it does not verify the caller's identity. Each FI API request must then pass mutual TLS (mTLS), present a short-lived access token linked to the client certificate, and carry a valid request signature made with the method registered for its key. Payvala then checks the request format and the FI's API permissions before processing the request. The health and status endpoints are documented exceptions to the token and signature rules (see Security Rules for Each API). Optional message encryption (JWE) adds protection for the message body. It is off by default for normal FI API traffic and is always used to deliver a new HMAC secret. Merchant-facing APIs and Soundbox devices use separate security methods, and device connections never use the FI paths.
Identity & Access
Payvala uses the FI's registered client certificate and a short-lived access token linked to that certificate to verify the caller. It checks the token's permissions on every request. The institution identity comes from the registered certificate, not from a value supplied in the request.
Network & Communication
Each FI uses one network path for normal traffic: a private connection or the public path through Cloudflare. FI API connections require TLS 1.3, with no fallback to older TLS versions. The network path does not replace certificate, token, or signature checks.
Application & Data
Payvala checks request size, media type, and message format before processing the body. It verifies the registered request signature and applies the API's validation rules. Access is limited to the operations and data permitted for that FI.
Operational Security
Security procedures cover key and certificate management, controlled approval of sensitive key operations, audit records, protection against repeated signature failures, and emergency procedures for certificate authority problems. Items marked provisional or proposed must not be treated as confirmed commitments.
Payvala APIs do different jobs, so each API belongs to exactly one security class. The class sets the request-signing method, validation rules, and access controls that the API must meet, and how its caller must connect. Four classes apply to the current FI and merchant APIs: K, W, R, and M. Additional classes for people, staff, devices, outbound calls, and device commands (H, I, D, O, and C) are proposed for surfaces that are not yet built and await owner confirmation. This page gives a quick overview of the requirements for each class. Detailed procedures for creating, rotating, and revoking keys are covered on the separate Key Management page.
Class K: Key Management
Applies to API 2, which manages keys. Requests must use JWS signing; HMAC is not accepted for this API. The FI's master key signs each request, and that key is held in the FI's hardware security module. A master key cannot be used on any data API. Each new key waits for an activation delay and can be cancelled during it.
Class W: Data Ingest
Applies to APIs 3, 7, and 8, which receive transaction, device-classification, and heartbeat submissions. Each key must use its registered HMAC or JWS signing profile, with no downgrade to another method. Each transaction carries a unique txnId. A repeated transaction within 48 hours returns the original result instead of being processed again.
Class R: Reads
Applies to APIs 5, 6, and 9, which return information to authorized callers: device status, FI transaction reads, and the events feed. Results are paginated so clients can retrieve them in manageable portions. A device serial number that does not exist gives the same response as one that belongs to another FI, so one institution cannot discover another institution's devices.
Class M: Merchant First Party
Applies to APIs 1 and 4, called by Payvala's own app or web page on a merchant's behalf, through Cloudflare. These flows do not use an FI client certificate. Merchants sign in with their device serial number and printed device code, or with a one-time code sent by email, which gives lower assurance. Access tokens are bound to a device key (DPoP) after a pushed authorization request (PAR) and PKCE S256.
Financial institutions (FIs) can connect to Payvala through the approved public route using Cloudflare. Cloudflare acts as the entry point for incoming traffic and applies configured network protections before requests reach the Payvala FI API. The origin accepts traffic from Cloudflare only, helping prevent requests from reaching the service through an unapproved public route. This section explains how traffic reaches Payvala; certificate verification, access tokens, request signing, and API permissions are explained in their dedicated security sections.
All Financial Institution (FI) API connections must use TLS 1.3, and older TLS versions are not accepted. Mutual TLS (mTLS) requires both sides to prove their identity using certificates. Each FI generates its private key and certificate request inside its own hardware security module (HSM), and the private key never leaves the HSM. Software-only private-key storage is not permitted in production. Connections with missing, invalid, or unregistered certificates are refused before any data is read. Because mTLS does not support session resumption, FI clients should keep connections open using HTTP keep-alive and use a small connection pool rather than opening a new connection for every request.
TLS 1.3 — Secure Communication
mTLS — Certificate-Based Authentication
Client Key Type
Certificate Issuer
Certificate Validity and Renewal
Certificate Revocation
An access token is a short-lived credential that allows an FI to call approved APIs. Each token is linked to the client certificate used to request it and lasts 900 seconds (15 minutes). There is no refresh token. When a token expires, the FI requests a new one. The FI should cache the current token and reuse it until it expires instead of requesting a token for each call. Token permissions limit which APIs it can reach. On every call Payvala checks the token's signature, issuer, audience, expiry, scope, and certificate binding, and confirms that the certificate is still registered to an active institution. If the certificate is revoked or the FI is suspended, its tokens stop working at once, without waiting for expiry.
Token Type
Lifetime
Grant
Control-plane Scope
Data-plane Scopes
Status Scope
Each API key is registered to one request-signing method: HMAC or JWS. HMAC uses a shared secret, which must never be sent with a request. JWS uses a private key held by the FI to create a signed proof for each request, and Payvala checks that proof against the registered public key. Payvala checks the signature to help confirm that the request came from the expected key and was not changed. A key's method is fixed, so a key cannot switch methods, and a request signed with the wrong method is rejected with 400 invalid_signature. API 2 accepts JWS only. The older X-Api-Key header is no longer used. A third profile, RFC 9421 HTTP Message Signatures (http-sig), is planned with a target date of 30 June 2027. That date can move by mutual agreement, and it is not a commitment.
| Field | Description |
|---|---|
X-Api-Key-Id | Key identifier for HMAC and JWS. It is an identifier, not a secret, and is covered by the HMAC signature. |
X-Timestamp | HMAC only. Must be within 300 seconds of the platform clock. Covered by the signature. |
X-Nonce | HMAC only. Unique per request and remembered for 600 seconds to block replay. Covered by the signature. |
X-Signature | HMAC only. Base64 of the 32-byte HMAC-SHA256 result over the version 2 signing string: the HTTP method, the path with query, the key identifier, the timestamp, the nonce, and the raw body bytes. Because the method and path are signed, a signature cannot be reused on a different request. |
X-Request-Proof | JWS only. Signed with ES256 or PS256 and typ payvala-proof+jwt. Carries iat (within 300 seconds), jti (remembered 600 seconds), htm, htu, a SHA-256 digest of the body and, for API 3, the txnId. A new proof is computed for every request. |
Keys and credentials must be managed safely from creation to retirement. A new key waits for an activation delay before it becomes usable. The delay is provisionally 30 minutes (allowed range 15 to 60), and the key can be cancelled during that time. During planned rotation, the new key is added before the old one is retired, with a 24-hour overlap, so integrations can switch without an avoidable outage. HMAC secrets rotate every 90 days, with 14 days' notice. If the master key is lost or suspected to be compromised, a controlled out-of-band recovery applies. It involves two FI officers, two Payvala approvers, registered contacts, and a cooling-off period. Retired and expired keys cannot be reactivated.
One Key per API
Each key is created for one API and holds one scope and one signing profile. No key covers several APIs. Every call checks that the scope the API requires, the token's scope, and the key's scope agree.
Key Identification
Each key is identified by its kid. The JWE header names the decryption key by kid.
Non-Disruptive Rotation
New keys are added without interrupting existing integrations, with a 24-hour overlap on both sides.
HMAC Secret Handling
The platform generates the HMAC secret and returns it once, encrypted (JWE) to the FI's encryption key. It can never be read back. A request that carries the secret is rejected with 400, and that credential is flagged for rotation.
Limited Key Operations
Key operations are deliberately rare: a handful per hour and, provisionally, 20 per day per FI. Every key operation is written with its signed request to write-once storage.
Credential Protection
Private keys and credentials stay in the owner's hardware security module or secrets manager. Suspected compromise must be reported to Payvala within 1 hour.
JSON Web Key Sets (JWKS) publish the public keys used for encryption and signature verification between Payvala and FIs. Payvala publishes its public encryption keys at /.well-known/jwks.json. Signing keys (master, approver, and request-proof keys) use ES256 with an EC P-256 key (preferred) or PS256 with an RSA key of 2048 bits or more. Encryption keys are RSA keys of 2048 bits or more. Private keys are generated by their owner and never leave the owner's hardware security module. Each new public key is confirmed by a fingerprint call-back (RFC 7638 thumbprint) and checked for uniqueness across all FIs and both environments before it is registered.
| Field | Description |
|---|---|
kty | Key type. EC for ES256 signing keys (preferred); RSA for PS256 signing keys and for encryption keys. |
kid | Unique key identifier. Selects the key during planned rotation and in the JWE header. |
use | Intended key usage. enc for encryption keys; sig for signing keys. A signing key is refused as an encryption key. |
alg | Algorithm. RSA-OAEP-256 for encryption keys today; ES256 or PS256 for signing keys. RS256 is not permitted. |
crv | EC curve, for EC keys only (P-256). |
x | EC public key x coordinate in Base64URL, for EC keys only. |
y | EC public key y coordinate in Base64URL, for EC keys only. |
n | RSA modulus encoded using Base64URL, for RSA keys only. |
e | RSA public exponent encoded using Base64URL, for RSA keys only. |
FIs obtain Payvala's public encryption keys with a GET request to /.well-known/jwks.json. An FI may register the address of its own key set, but only for its encryption key. Never for its master, approver, or request-proof keys, and never for certificates. That address must be HTTPS on a domain the FI registered at onboarding. Payvala caches the last good set and keeps it if a fetch fails. It uses a new key only 24 hours after the key first appears (Proposed), alerts the FI's security contacts on every change, and runs the uniqueness check on each new key. Key identifiers allow the correct key to be selected during planned rotation. Exact endpoint details are documented in Developer → API.
TLS protects data while it travels between systems. Request signatures add a separate check that a request is genuine and has not been changed. Optional JWE encryption adds protection to the message body itself. It is off by default, except when used to deliver a new HMAC secret. Encryption does not prove who sent a message; certificates, tokens, and signatures do that. Requests must follow the published size and format rules. FIs must not send account numbers, BVN, NIN, phone numbers, or card numbers in requests. The rules for handling personal data are covered in Protecting Personal and Sensitive Data.
JWE (JSON Web Encryption) is an optional way to encrypt the message body inside the TLS connection. It is off by default for normal API traffic and is always used when Payvala delivers a new HMAC secret. An FI whose policy does not allow a processor to see transaction data in clear, typically on the public path, can switch it on for API 3, API 5, and API 6. Those APIs carry amounts, payer references, device serial numbers, and device location. JWE encrypts the body but does not authenticate the sender; the certificate, token, and signature do that. When it is enabled, both sides decrypt every body, and the edge can check sizes but not content.
Serialization
Key Exchange
Content Encryption
Encryption Key
Key Publication
| Header | Description |
|---|---|
Authorization | Bearer <AccessToken> |
Content-Type | application/jose |
X-Api-Key-Id | <Key identifier> |
When response encryption is enabled for an FI, the response body is returned as a compact JWE with Content-Type application/jose, encrypted to the FI's registered encryption key. Every authenticated response carries Cache-Control: no-store and X-Content-Type-Options: nosniff, whether or not its body is encrypted. Exact response structure is documented in Developer → API.
FI integrations exchange only what each operation needs, typically a transaction reference, amount, device serial number, and txnId. The payerRef field is personal data and is treated as a direct or pseudonymous identifier. Payvala stores the value as sent, encrypts it at field level at rest, masks it in logs to its last four characters, never places it in an error response, and shows it only to the merchant of that device. It is kept no longer than the transaction record. Credentials, access tokens, secrets, and private keys must never appear in application logs, source repositories, or unsecured configuration.
Credential & Token Protection
Access tokens and credentials must be protected from unauthorized disclosure. HMAC secrets are never returned after creation.
Private Key Protection
Private keys stay in the owner's hardware security module and are never exposed to Payvala or to any other party.
Minimal Data Exchange
FIs must not send account numbers, BVN, NIN, phone, or card numbers. payerRef is optional, and the FI chooses its content: an opaque, stable token, a masked name, or a token generated per merchant. A token that is the same for a payer at every merchant lets two merchants recognize the same payer, so a per-merchant token or masked name is the safer choice.
Secure Logging Practices
Sensitive values must not be exposed in logs. FIs keep their own logs for at least 12 months so they can correlate with Payvala audit records, and log payerRef only to its last four characters.
Merchant-facing APIs (1 and 4) and the planned administrator portal run in a browser, so the browser must be told how to protect the user. FI APIs are machine-to-machine and are not meant to be called from browsers. Their hosts send no cross-origin (CORS) headers and refuse cross-origin preflight requests, which is itself a control.
Transport Enforcement
Strict-Transport-Security with max-age of one year and includeSubDomains. Preload is added only after all subdomains are confirmed HTTPS-only.
Content Security Policy
Nonce-based scripts, no unsafe-eval, no inline scripts without a nonce, object-src 'none', base-uri 'none', frame-ancestors 'none', and upgrade-insecure-requests. The policy starts in report-only mode and is then enforced.
Cookies
Session cookies use the __Host- prefix with Secure, HttpOnly, SameSite=Strict (Lax only where a sign-in redirect requires it), Path=/, and no Domain attribute. Tokens are never kept in local storage.
Framing, Sniffing & Referrer
X-Frame-Options DENY, X-Content-Type-Options nosniff, and Referrer-Policy strict-origin-when-cross-origin, or no-referrer on pages that carry identifiers in the address. Permissions-Policy turns off camera, microphone, geolocation, and payment unless a feature is needed.
Caching
Cache-Control: no-store on every authenticated page and API response, so that data is not left in shared or browser caches.
CORS & CSRF
Merchant and portal APIs allow only an exact list of Payvala front-end origins, never a wildcard with credentials, and preflight responses are cached for at most 10 minutes. State-changing requests need SameSite cookies and a per-session token, or use a bearer token in a header.
Sign-in Protection
Rate limits, lockout after repeated failures, generic error messages, and an optional bot challenge after repeated failures. The sign-in method for the administrator portal is an open decision: either the FI's identity provider or Payvala-managed accounts with multi-factor authentication.
Each FI can access only its own permitted data. Payvala identifies the institution from its client certificate, not from a value supplied in the request. Important key-management and request-check outcomes are recorded for later review. Detailed platform-wide log collection and threat detection are covered in a separate plan and are not specified in this section.
Tenant Isolation
Tenant isolation is enforced in the server and again in the database. Unknown resources and resources owned by another FI return identical answers, so existence is not revealed.
Authentication Activity
Traceability of identity verification activity for operational and security review.
Authorization Activity
Traceability of access-decision activity for operational and security review.
Request Validation Activity
Traceability of request-validation outcomes for troubleshooting and investigation.
Credential Management Activity
Every key operation is written with its signed request, and a secret can never be read back after creation.
Traffic & Abuse Protection
Three consecutive signature failures on one API, for one FI and one profile, trip a circuit breaker. The failing call returns 400. Later calls return 503 with circuit_break_active, and security contacts are alerted. For API 2, a person must reset the breaker. For the other data APIs, a trial request is allowed after a cooldown of 5 minutes (†). The FI must not build automatic retries around circuit_break_active. Per-FI rate limits apply to every API.
Keeping the integration secure is a shared responsibility. Payvala manages the platform-side controls, while each FI manages its own systems, network settings, keys, certificates, and monitoring. Each side must complete the security steps it controls.
Payvala Responsibilities
Operates the platform-side controls: TLS 1.3 at the edge, certificate and token validation, signature verification, limits, audit records, and key-operation controls. Publishes the status endpoint, runs the emergency plan for the certificate authorities, and gives the required incident notices.
Integrating Organization Responsibilities
Protects its certificate and master keys in a hardware security module under dual control; production requires an HSM. Stores HMAC secrets in a key manager, keeps system clocks within 60 seconds of an NTP source, retains logs for at least 12 months, reports incidents within 1 hour, and monitors its own success rate, latency, and 429 and 503 counts.
Protect Private Keys
Generate keys in a hardware security module, where they are non-exportable. Production requires an HSM. Keep the master key under dual control.
Protect Credentials
Store HMAC secrets and tokens securely in a key manager. Never log them, and never place them in source repositories.
Use Correct Environment
Use the institution ID, client IDs, endpoints, certificate authority, and keys for the selected environment. A staging certificate is never accepted in production.
Protect Sensitive Data
Do not send account numbers, BVN, NIN, phone, or card numbers. Send a full name only where the FI's privacy notice covers sharing it with the merchant. See Protecting Personal and Sensitive Data for the full rules.
Rotate Keys & Credentials
Rotate HMAC secrets every 90 days, with 14 days' notice. Renew client certificates before their 12-month expiry. Payvala notifies 30 days ahead, and the old and new certificates overlap for 7 days.
Keep Components Updated
Keep supported security components and dependencies up to date. Retire deprecated API versions before the Sunset date given in the response headers. After a breaking change, the old version runs for at least 90 days (Proposed).
Handle Failures Safely
Keep clocks synchronised within 60 seconds of an NTP source. Drift above 300 seconds causes every request to be rejected with 400. Never retry a 400, 401, 403, or 404 unchanged. Retry only timeouts, 429, and 503 responses (not circuit_break_active), with exponential backoff starting at about one second, a cap of 60 seconds, and jitter, and honour Retry-After. A transaction retry must reuse the original txnId.
Monitor Integration Activity
Track request success rate, latency, and 429 and 503 counts. Log X-Track-Id for each call, and cf-ray on the public path, so that support can trace it.