Skip to main content

Overview

The Onboarding API uses JWT (JSON Web Token) Bearer Token authentication. Unlike the QR API which uses HTTP Basic Auth, the Onboarding API requires you to generate and sign JWT tokens with your secret key.
JWT tokens ensure that requests are authentic and haven’t been tampered with. The secret key is private and should never be exposed publicly.
Prerequisite: Before generating JWT tokens, you must first create an account using the Create Account API to obtain your Account ID and email address. These credentials are required for the JWT payload.

How JWT Authentication Works

1

Generate JWT Payload

Create a JSON payload containing the account ID and email address
2

Sign with Secret Key

Sign the payload with your secret key using the HS256 algorithm
3

Include in Authorization Header

Send the JWT token in the Authorization: Bearer {token} header
4

Server Verification

Modulus Labs verifies the token signature using the same secret key

Authentication Flow

Secret Key

Your secret key will be provided by Modulus Labs. Store it securely:
Never commit your secret key to version control or expose it in client-side code. Always store it in environment variables or secure secret management systems.
MODULUS_ONBOARDING_SECRET_KEY=your_secret_key_here

JWT Payload Structure

The JWT payload must contain these required fields:
FieldTypeRequiredDescription
subnumberYesAccount ID received from Create Account API
emailstringYesEmail address registered to the account

Example Payload

{
  "sub": 1,
  "email": "[email protected]"
}
sub
number
required
The Account ID received from the Create Account API. This identifies which merchant account is making the request.Example: 1, 12345
email
string
required
The email address registered to the merchant account. Must match the email used during account creation.Format: Valid email addressExample: "[email protected]", "[email protected]"

Generating JWT Tokens

Here’s how to generate JWT tokens in different languages:
const jwt = require('jsonwebtoken');

const SECRET_KEY = process.env.MODULUS_ONBOARDING_SECRET_KEY;

function generateToken(accountId, email) {
  const payload = {
    sub: accountId,
    email: email
  };

  const token = jwt.sign(payload, SECRET_KEY, {
    algorithm: 'HS256'
  });

  return token;
}

// Usage
const accountId = 1;
const email = '[email protected]';
const token = generateToken(accountId, email);

console.log('JWT Token:', token);
// Output: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjEsImVtYWlsIjoibWVyY2hhbnRAZ21haWwuY29tIiwiaWF0IjoxNjQwOTk1MjAwfQ.xyz123...

Required Libraries

Install the necessary JWT libraries for your language:
npm install jsonwebtoken

Making Authenticated Requests

Include the JWT token in the Authorization header with the Bearer prefix:
const axios = require('axios');

async function onboardMerchant(token, merchantData) {
  const response = await axios.post(
    'https://kyc.sbx.moduluslabs.io/v2/onboard',
    merchantData,
    {
      headers: {
        'Authorization': `Bearer ${token}`,
        'Content-Type': 'application/json'
      }
    }
  );

  return response.data;
}

// Usage
const token = generateToken(1, '[email protected]');
const result = await onboardMerchant(token, merchantData);

Token Best Practices

Generate Per Request

Generate a new token for each API request rather than reusing old tokens

Secure Storage

Store secret keys in environment variables or secret management systems

HTTPS Only

Always send tokens over HTTPS to prevent interception

Server-Side Only

Never generate or store tokens in client-side JavaScript

Validate Inputs

Validate accountId and email before generating tokens

Handle Errors

Implement proper error handling for token generation failures

Token Expiration

The Onboarding API JWT tokens do not require an expiration time (exp claim). However, you can add one for additional security if desired.

Optional: Adding Expiration

If you want to add token expiration for extra security:
const jwt = require('jsonwebtoken');

function generateTokenWithExpiry(accountId, email, expiresIn = '1h') {
  const payload = {
    sub: accountId,
    email: email
  };

  const token = jwt.sign(payload, SECRET_KEY, {
    algorithm: 'HS256',
    expiresIn: expiresIn  // '1h', '24h', '7d', etc.
  });

  return token;
}

// Token expires in 1 hour
const token = generateTokenWithExpiry(1, '[email protected]', '1h');

Error Responses

Authentication errors return a standard error format:

401 Unauthorized

{
  "code": "20000001",
  "error": "Invalid or expired JWT token",
  "referenceNumber": "abc123-def456-ghi789"
}
Cause: Token signature doesn’t match or token is malformedSolution:
  • Verify you’re using the correct secret key
  • Ensure the token is properly formatted
  • Check for any whitespace in the token string
Cause: Token has expired (if you added an exp claim)Solution:
  • Generate a new token
  • Increase expiration time if needed
Cause: Authorization header is missing or doesn’t contain Bearer tokenSolution:
  • Ensure header format is: Authorization: Bearer {token}
  • Check that the token is not empty
Cause: Account ID or email in payload doesn’t match account recordsSolution:
  • Verify the account ID is correct
  • Ensure email matches the registered account email

Security Considerations

Never expose your secret key publicly. Anyone with your secret key can generate valid tokens and access your API.

Security Checklist

1

Store Keys Securely

Use environment variables, AWS Secrets Manager, or similar secure storage
2

Use HTTPS

All API requests must be made over HTTPS (HTTP will fail)
3

Server-Side Generation

Always generate JWT tokens on your backend server, never in browser JavaScript
4

Rotate Keys

Implement a key rotation strategy if your secret key is compromised
5

Monitor Usage

Log and monitor API usage to detect suspicious activity

Testing Authentication

Test your JWT generation before making actual API calls:
const jwt = require('jsonwebtoken');

// Generate token
const token = generateToken(1, '[email protected]');
console.log('Generated Token:', token);

// Decode token (for testing only)
const decoded = jwt.decode(token);
console.log('Decoded Payload:', decoded);

// Verify token (simulates server verification)
try {
  const verified = jwt.verify(token, SECRET_KEY);
  console.log(' Token is valid:', verified);
} catch (error) {
  console.error(' Token verification failed:', error.message);
}

Next Steps