FinCode uses a role-based authentication system with JWT tokens to secure API access. Each user is assigned a specific role that determines their permissions and accessible resources within your tenant.
All API requests must include a valid access token in the Authorization header
otherwise stated.
Authentication Flow
User Roles & Permissions
MANAGER
Plugins management
Agent configuration
KYC/AML configuration
Analytics and reporting
Process transaction refunds.
Organisation user management
Crossboarder setup & operations
AGENT
Call-over reports
Corridor management
View customer profiles
Transaction status updates
Exchange rate and fee markups
Tenant-specific analytics and reporting
CASHIER
Print receipts
Process payments
Create transactions
Handle cash collections
View transaction history
Verify transaction details
CUSTOMER
Request quotes
Initiate transfers
Create beneficiaries
View own transactions
View transaction history
Update profile information
Server-to-Server Authentication
FinCode supports server-to-server authentication using JWT tokens, allowing your systems to interact programmatically with the API. This ensures secure, stateless communication for backend integrations.
For comprehensive details on securing your integration, including best practices for managing credentials, please refer to the Security section.
API Token Authentication
For backend services and integrations that require simpler, long-lived authentication, FinCode provides API Tokens . These tokens are generated from your dashboard and allow you to call authenticated endpoints without going through the login flow.
API Tokens are ideal for server-to-server communication, scheduled jobs, and automated processes where the standard login flow is impractical.
Key Features
Custom Expiry : Choose from 24 hours, 1 month, 3 months, 6 months, or 1 year
Multiple Tokens : Create separate tokens for different services or environments
Full Control : Rotate, invalidate, or delete tokens anytime from your dashboard
Using API Tokens
Include the token in the X-Auth-Token header:
curl -X GET "https://{domain}.fincode.software/api/v6/services/your-endpoint" \
-H "Content-Type: application/json" \
-H "X-Auth-Token: your-api-token-here" \
-H "platform: fincode" \
-H "uuid: 200"
Learn More For complete details on API tokens, encryption keys, and when to use each, see the Encryption Keys and Tokens guide.
Interactive Authentication Testing
Test authentication for different user roles in your sandbox environment. Select a role to see the appropriate login request and response.
MANAGER
AGENT
CASHIER
CUSTOMER
Manager Authentication Managers have full access to all platform features and administrative functions. Login Request: curl -X PUT "https://{domain}.fincode.software/api/v6/services/securitymanagement/login" \
-H "Content-Type: application/json" \
-H "platform: fincode" \
-H "uuid: 200" \
-d '{
"email": "manager@yourcompany.com",
"currentPassword": "your-secure-password"
}'
Node.js Example: const axios = require ( 'axios' );
async function loginAsManager () {
const response = await axios . put (
'https://{domain}.fincode.software/api/v6/services/securitymanagement/login' ,
{
email: 'manager@yourcompany.com' ,
currentPassword: 'your-secure-password'
},
{
headers: {
'Content-Type' : 'application/json' ,
'platform' : "fincode" ,
'uuid' : "200" ,
}
}
);
return response . data ;
}
Expected Response: {
"access_token" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." ,
"expires_in" : 3600 ,
"refresh_token" : "def50200a1b2c3d4e5f6..." ,
"user" : {
"id" : "user_mgr_123" ,
"email" : "manager@yourcompany.com" ,
"role" : "MANAGER" ,
"tenant_id" : "tenant_456" ,
"permissions" : [
"users:read" ,
"users:write" ,
"transactions:read" ,
"transactions:write" ,
"reports:read" ,
"settings:write" ,
"webhooks:manage"
]
}
}
Agent Authentication Agents handle customer-facing operations and transaction processing. Login Request: curl -X PUT "https://{domain}.fincode.software/api/v6/services/securitymanagement/login" \
-H "Content-Type: application/json" \
-H "platform: fincode" \
-H "uuid: 200" \
-d '{
"email": "agent@yourcompany.com",
"currentPassword": "your-secure-password"
}'
Node.js Example: const axios = require ( 'axios' );
async function loginAsAgent () {
const response = await axios . put (
'https://{domain}.fincode.software/api/v6/services/securitymanagement/login' ,
{
email: 'agent@yourcompany.com' ,
currentPassword: 'your-secure-password'
},
{
headers: {
'Content-Type' : 'application/json' ,
'platform' : 'fincode' ,
'uuid' : '200'
}
}
);
return response . data ;
}
Expected Response: {
"access_token" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." ,
"expires_in" : 3600 ,
"refresh_token" : "def50200a1b2c3d4e5f6..." ,
"user" : {
"id" : "user_agt_456" ,
"email" : "agent@yourcompany.com" ,
"role" : "AGENT" ,
"tenant_id" : "tenant_456" ,
"permissions" : [
"transactions:read" ,
"transactions:create" ,
"transactions:update" ,
"customers:read" ,
"customers:verify" ,
"kyc:perform" ,
"reports:read"
]
}
}
Cashier Authentication Cashiers handle payment processing and cash transactions at physical locations. Login Request: curl -X PUT "https://{domain}.fincode.software/api/v6/services/securitymanagement/login" \
-H "Content-Type: application/json" \
-H "platform: fincode" \
-H "uuid: 200" \
-d '{
"email": "cashier@yourcompany.com",
"currentPassword": "your-secure-password"
}'
Node.js Example: const axios = require ( 'axios' );
async function loginAsCashier () {
const response = await axios . put (
'https://{domain}.fincode.software/api/v6/services/securitymanagement/login' ,
{
email: 'cashier@yourcompany.com' ,
currentPassword: 'your-secure-password'
},
{
headers: {
'Content-Type' : 'application/json' ,
'platform' : 'fincode' ,
'uuid' : '200' ,
}
}
);
return response . data ;
}
Expected Response: {
"access_token" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." ,
"expires_in" : 3600 ,
"refresh_token" : "def50200a1b2c3d4e5f6..." ,
"user" : {
"id" : "user_csh_789" ,
"email" : "cashier@yourcompany.com" ,
"role" : "CASHIER" ,
"tenant_id" : "tenant_456" ,
"permissions" : [
"transactions:create" ,
"transactions:read" ,
"payments:process" ,
"cash:handle" ,
"receipts:print"
]
}
}
Customer Authentication Registered customers can access self-service features through your customer portal. Login Request: curl -X PUT "https://{domain}.fincode.software/api/v6/services/securitymanagement/login" \
-H "Content-Type: application/json" \
-H "platform: fincode" \
-H "uuid: 200" \
-d '{
"email": "customer@example.com",
"currentPassword": "customer-password"
}'
Node.js Example: const axios = require ( 'axios' );
async function loginAsCustomer () {
const response = await axios . put (
'https://{domain}.fincode.software/sandbox/api/v6/services/securitymanagement/login' ,
{
email: 'customer@example.com' ,
currentPassword: 'customer-password'
},
{
headers: {
'Content-Type' : 'application/json' ,
'platform' : 'fincode' ,
'uuid' : '200' ,
}
}
);
return response . data ;
}
Expected Response: {
"access_token" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." ,
"expires_in" : 3600 ,
"refresh_token" : "def50200a1b2c3d4e5f6..." ,
"user" : {
"id" : "user_cust_101" ,
"email" : "customer@example.com" ,
"role" : "CUSTOMER" ,
"tenant_id" : "tenant_456" ,
"customer_id" : "cust_202" ,
"permissions" : [
"profile:read" ,
"profile:update" ,
"transactions:create" ,
"transactions:read:own" ,
"beneficiaries:manage" ,
"quotes:request"
]
}
}
Making Authenticated Requests
Once authenticated, include the access token in all subsequent API requests:
const axios = require ( 'axios' );
const response = await axios . get (
'https://{domain}.fincode.software/api/v6/services/admin/organisation-preference-management/fetch-organisaction-preference' ,
{
headers: {
'X-Auth-Token' : process . env . JWT_ACCESS_TOKEN ,
'Content-Type' : 'application/json' ,
platform: 'fincode' ,
uuid: '200' ,
},
}
);
Required Headers:
Authorization: Bearer {access_token} - Your JWT access token
X-Auth-Token: {api_token} - Your JWT access token
Content-Type: application/json - For POST/PUT requests
platform: fincode - For identifying request platform
uuid: 200 - Unique uuid string
Token Management
Token Expiration
Access tokens expire after 1 hour . You have two options to maintain authentication:
Refresh Token
Auto-Refresh
Use the refresh token to obtain a new access token without re-authentication: async function refreshAccessToken ( refreshToken ) {
const response = await axios . post (
'https://{domain}.fincode.software/api/v6/services/securitymanagement/refresh' ,
{
refresh_token: refreshToken
},
{
headers: {
'Content-Type' : 'application/json' ,
'X-Auth-Token' : process . env . JWT_ACCESS_TOKEN ,
'platform' : 'fincode' ,
'uuid' : '200' ,
}
}
);
return response . data ;
}
Response: {
"access_token" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." ,
"expires_in" : 3600
}
Implement automatic token refresh in your application: let accessToken = null ;
let refreshToken = null ;
let tokenExpiry = null ;
async function ensureValidToken () {
if ( ! tokenExpiry || Date . now () >= tokenExpiry - 300000 ) {
if ( refreshToken ) {
const data = await refreshAccessToken ( refreshToken );
accessToken = data . access_token ;
tokenExpiry = Date . now () + ( data . expires_in * 1000 );
} else {
const data = await login ();
accessToken = data . access_token ;
refreshToken = data . refresh_token ;
tokenExpiry = Date . now () + ( data . expires_in * 1000 );
}
}
return accessToken ;
}
const token = await ensureValidToken ();
Token Revocation
Revoke tokens when logging out or if compromised:
async function logout ( accessToken ) {
await axios . post (
'https://{domain}.fincode.software/api/v6/services/securitymanagement/logout' ,
{},
{
headers: {
'X-Auth-Token' : process . env . JWT_ACCESS_TOKEN ,
platform: 'fincode' ,
uuid: '200' ,
},
}
);
}
Security Best Practices
Secure Storage
Store tokens in secure, httpOnly cookies for web apps
Use secure storage mechanisms on mobile (Keychain/KeyStore)
Never store tokens in localStorage or sessionStorage
Encrypt tokens at rest in your backend
Token Rotation
Rotate refresh tokens after each use - Implement token expiration monitoring
Set up automatic token refresh - Handle token refresh failures gracefully
Network Security
Always use HTTPS in production
Implement certificate pinning for apps
Use secure communication channels
Monitor for man-in-the-middle attacks
Access Control
Follow principle of least privilege
Regularly audit user permissions
Implement session timeout
Log all authentication attempts
Role Permission Matrix
Permission MANAGER AGENT CASHIER CUSTOMER Create Transactions ❌ ❌ ✅ ✅ (own) View All Transactions ✅ ✅ ❌ ❌ Update Transactions ✅ ✅ ✅ ❌ Manage Users ✅ ✅ (own) ✅ ❌ KYC/AML Configuration ✅ ❌ ❌ ❌ KYC/AML Verification ❌ ❌ ❌ ✅ Tenant Configuration ✅ ❌ ❌ ❌ Process Refunds ✅ ❌ ❌ ❌ Analytics/Reports ✅ ✅ (limited) ❌ ❌ Manage Beneficiaries ✅ ❌ ❌ ✅ (own) Plugin Management ✅ ❌ ❌ ❌ Agent Configuration ✅ ❌ ❌ ❌ Rate/Fee Markups ❌ ❌ ❌ ✅ (own) Request quotes ❌ ❌ ✅ ✅
Error Handling
Causes:
Invalid or expired access token
Missing Authorization header
Malformed JWT token
Solution:
axios . interceptors . response . use (
response => response ,
async error => {
if ( error . response ?. status === 401 ) {
try {
const newToken = await refreshAccessToken ( refreshToken );
error . config . headers [ 'Authorization' ] = `Bearer ${ newToken . access_token } ` ;
return axios . request ( error . config );
} catch ( refreshError ) {
window . location . href = '/login' ;
}
}
return Promise . reject ( error );
}
);
Causes:
Insufficient permissions for the requested resource
Role doesn’t have access to the endpoint
Attempting to access another user’s data
Response: {
"error" : "forbidden" ,
"message" : "Insufficient permissions to access this resource" ,
"role" : "CASHIER"
}
Next Steps