Unified Transfer is in active development. As a pioneer merchant, you will be informed of the updates through your Maya Relationship Manager.
Overview
Unified Transfer requires all protected API requests to be digitally signed using JSON Web Signature (JWS) in addition to OAuth 2.0 authentication.
This guide explains how to implement your JWS library and correctly generate and attach the required signature.
Pre-requisite
Before proceeding, make sure you have read the following guides:
JWS Implementation
Step 1: Use your valid private key
Use the RSA private key generated during Setting Up Your JWKS Endpoint for Unified Transfer.
Important:
- The private key must correspond to a public key published in your JWKS endpoint.
- The
kidused in the JWS header must match thekidof the public key in your JWKS.- Never expose or transmit your private key.
Step 2: Create your JWS Header
Every signature should use this header format:
{
"alg": "RS256",
"kid": "your-unique-key-id-12345",
"typ": "JWT"
}
Where:
alg: The signing algorithm (RS256 recommended)kid: Your Key ID from the JWKS endpoint (must match)typ: Token type (JWT)
If the
kiddoes not match a registered key, the request will be rejected.
Step 3: Sign the Exact Request Payload
Generate and include the signature in the x-jws-signature header.
Implementation Examples
Node.js (jsonwebtoken library)
const jwt = require('jsonwebtoken');
const fs = require('fs');
// Load your private key once at startup
const privateKey = fs.readFileSync('private-key.pem');
const keyId = 'your-unique-key-id-12345';
function signRequest(requestBody) {
// Create JWS signature for this specific request
const signature = jwt.sign(requestBody, privateKey, {
algorithm: 'RS256',
keyid: keyId,
header: {
typ: 'JWT'
}
});
return signature;
}
// Usage example
const requestBody = {
data: {
initiation: {
debit_account: { /* ... */ },
credit_account: { /* ... */ },
amount: { /* ... */ }
}
}
};
const signature = signRequest(requestBody);
// Use signature in x-jws-signature header
Python (PyJWT library)
import jwt
import json
# Load your private key once at startup
with open('private-key.pem', 'r') as f:
private_key = f.read()
key_id = 'your-unique-key-id-12345'
def sign_request(request_body):
"""Create JWS signature for a specific request"""
signature = jwt.encode(
request_body,
private_key,
algorithm='RS256',
headers={'kid': key_id, 'typ': 'JWT'}
)
return signature
# Usage example
request_body = {
"data": {
"initiation": {
"debit_account": {},
"credit_account": {},
"amount": {}
}
}
}
signature = sign_request(request_body)
# Use signature in x-jws-signature header
Troubleshooting Signature Issues
Signature Verification Failed
Possible causes:
kidin signature doesn't match JWKS endpoint- Request body doesn't match signed payload
- Using the wrong private key
- Algorithm mismatch (e.g., using RS512 instead of RS256)
Solutions:
- Verify
kidmatches your JWKS - Ensure you're signing the exact request body
- Confirm you're using the correct private key for the environment
- Check the algorithm is RS256
Invalid Signature Format
Possible causes:
- Signature is not in JWS Compact Serialization format
- Missing or incorrect header fields
Solutions:
- Ensure signature has three parts separated by dots (header.payload.signature)
- Verify JWS header includes
alg,kid, andtypfields
Developer Notes and Tips
- Use the correct private key and kid values
- The private key should be the correct pair of the public key loaded in your JWKS endpoint.
kidin your JWS header should match the one in your JWKS endpoint.- Update the values during key rotation
- Sign the exact payload: The signature must match the exact JSON body sent in the request
- Handle errors gracefully: Implement retry logic for signature verification failures
- Never log signatures: Signatures can be used to replay requests if intercepted
FAQs
Q: Can I use the same key pair for multiple environments?
A: No. Use separate key pairs for Sandbox and Production environments for better security isolation.
Q: Do I need to notify Maya every time I rotate keys?
A: Yes, coordinate with Maya before removing old keys to ensure a smooth transition. Adding new keys can be done independently.
Next Steps
Once you are done with the JWS Implementation, you are now ready for onboarding and will begin your integration. To start, see Getting Started with Unified Transfer.