Authorisation
All Pay.io API requests must be authenticated with three headers:
X-API-Key
Your unique merchant API key from Merchant Console.
X-API-Nonce
Unique identifier (UUID) per request.
X-API-Signature
RSA-SHA256 signature generated using your private key.
Creating a Public and Private Key
Merchants must provide Pay.io with a public key during onboarding.
Requirements:
At least 2048 bits
PEM format
You can use the following code sample to generate the public key and private key.
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import serialization
# Generate 2048-bit private key
private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
# Serialize keys to PEM
pem_private = private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.NoEncryption()
)
pem_public = private_key.public_key().public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
)Creating a Merchant Signature
Every API request must be signed.
Steps
Generate a nonce — Secure random string, at least 16 chars
# Example in Python def generate_nonce(): return str(uuid.uuid4())Build canonical string using the rules:
The request’s signature is calculated over this exact concatenation (no delimiters):
METHOD + PATH + NONCE + QUERY + BODY
Sign with your merchant’s private key using RSA-SHA256.
Base64-encode the signature.
Send it in the
X-API-Signatureheader
Example Python
Example Authenticated Request
Error Codes
Error Type: missing signature
missing signatureStatus Code: 401
Response Body:
Error Type: missing api key
missing api keyStatus Code: 401
Response Body:
Error Type: invalid api key
invalid api keyStatus Code: 401
Response Body:
Error Type: nonce too short
nonce too shortStatus Code: 400
Response Body:
Error Type: nonce already used
nonce already usedStatus Code: 401
Response Body:
Error Type: invalid nonce
invalid nonceStatus Code: 400
Response Body:
Error Type: missing nonce
missing nonceStatus Code: 401
Response Body:
Error Type: timestamp expired
timestamp expiredStatus Code: 401
Response Body:
Error Type: multiple nonces
multiple noncesStatus Code: 401
Response Body:
Last updated