Skip to main content

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

FieldRequiredDescription
issYesThe issuer URL registered with Paynovus for your account.
subYesYour partner identifier in Paynovus.
expYesExpiration time (Unix timestamp). Recommended: 60 seconds from now.
iatYesIssued-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 prefixMiddlewareEffect
/menone beyond auth middlewareReturns the verified Partner object
/individual/accounts/:id/*assertPartnerIndividualAccess403 if IndividualOnboarding.partnerId !== req.auth.partnerId
/cards/:id/*assertPartnerCardOwnership403 if the card is not in the partner's tenant scope
/cards (no :id)none beyond auth middlewareReturns 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: