Authentication
All routes except the public /health-check endpoint require a JWT Bearer token signed with the ES512 algorithm.
Overview
Every request must include an Authorization header:
Authorization: Bearer <your-jwt-token>
The JWT payload should include at least these fields:
{
"iss": "https://your-partner-url.com",
"sub": "YOUR_PARTNER_ID",
"exp": 1700000060,
"iat": 1700000000
}
JWT payload fields
| Field | Required | Description |
|---|---|---|
iss | Yes | The issuer URL registered with Paynovus for your account. |
sub | Yes | Your partner identifier in Paynovus. |
exp | Yes | Expiration time (Unix timestamp). Recommended: 60 seconds from now. |
iat | Yes | Issued-at time (Unix timestamp). |
Key generation
Generate an EC key pair and share the public key with Paynovus. Keep the private key secret.
# Generate private key in SEC1 format
openssl ecparam -genkey -name secp521r1 -noout -out private-sec1.pem
# Convert to PKCS#8 format (required for most JWT libraries)
openssl pkcs8 -topk8 -nocrypt -in private-sec1.pem -out private.pem
# Extract the public key
openssl ec -in private-sec1.pem -pubout -out public.pem
Provide public.pem to Paynovus and use private.pem to sign your JWT tokens.
Generate a JWT token (Node.js)
const jwt = require('jsonwebtoken');
const fs = require('fs');
const privateKey = fs.readFileSync('./private.pem', 'utf8');
function createPartnerToken({ issuer, subject }) {
const now = Math.floor(Date.now() / 1000);
const payload = {
iss: issuer,
sub: subject,
exp: now + 60,
iat: now
};
return jwt.sign(payload, privateKey, { algorithm: 'ES512' });
}
Sending the token in requests
Include the token in the Authorization header for every protected endpoint.
curl https://api.card-management-staging.paynovus.com/api/partner/me \
-H "Authorization: Bearer $TOKEN"
If the token is valid and your account is correctly configured, the request will succeed and return your account details.
Token expiry
- Tokens expire at the time specified by
exp. - Recommended token lifetime: 60 seconds.
- Expired tokens will be rejected with
401 Unauthorized.
Key generation
Partners must generate an EC key pair and provide the public key to Paynovus. Keep the private key secret.
# Generate private key in SEC1 format
openssl ecparam -genkey -name secp521r1 -noout -out private-sec1.pem
# Convert to PKCS#8 format (required for most JWT libraries)
openssl pkcs8 -topk8 -nocrypt -in private-sec1.pem -out private.pem
# Extract the public key
openssl ec -in private-sec1.pem -pubout -out public.pem
Provide public.pem to Paynovus. Use private.pem to sign your JWT tokens.
Generating a JWT Token (Node.js)
const jwt = require('jsonwebtoken');
const fs = require('fs');
const privateKey = fs.readFileSync('./private.pem', 'utf8');
function createPartnerToken({ issuer, subject }) {
const now = Math.floor(Date.now() / 1000);
const payload = {
iss: issuer,
sub: subject,
exp: now + 60,
iat: now
};
return jwt.sign(payload, privateKey, { algorithm: 'ES512' });
}
module.exports = { createPartnerToken };
Request lifecycle (per-resource)
After the JWT is verified, additional middleware runs depending on the route:
| Route prefix | Middleware | Effect |
|---|---|---|
/me | none beyond auth middleware | Returns the verified Partner object |
/individual/accounts/:id/* | assertPartnerIndividualAccess | 403 if IndividualOnboarding.partnerId !== req.auth.partnerId |
/cards/:id/* | assertPartnerCardOwnership | 403 if the card is not in the partner's tenant scope |
/cards (no :id) | none beyond auth middleware | Returns partner-wide card listing |
What's next?
You're ready to call protected endpoints. Head to the API Reference for the full list of routes, request/response shapes, and the Try it widget: