m2pfintech
Integration Guide

Authentication

JWT token authentication, required headers, token management, and authorization model for M2P Prepaid Platform APIs.

All API requests require JWT authentication and tenant identification.


Required Headers

HeaderRequiredDescription
AuthorizationYesBearer <JWT_TOKEN>
X-TENANT-IDYesYour unique tenant identifier
Content-TypeYesapplication/json
X-Request-IDRecommendedUnique request ID for idempotency and tracing

Authentication Flow


Obtaining Access Token

curl -X POST https://sandbox-api.m2pprepaid.com/auth/token \
  -H "Content-Type: application/json" \
  -d '{
    "clientId": "your_client_id",
    "clientSecret": "your_client_secret",
    "grantType": "client_credentials"
  }'

Response:

{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 3600
}
const axios = require('axios');

const BASE_URL = 'https://sandbox-api.m2pprepaid.com';

async function getAccessToken() {
  const response = await axios.post(`${BASE_URL}/auth/token`, {
    clientId: process.env.M2P_CLIENT_ID,
    clientSecret: process.env.M2P_CLIENT_SECRET,
    grantType: 'client_credentials'
  });
  return response.data.access_token;
}

async function fetchProducts(token) {
  const response = await axios.get(`${BASE_URL}/v1/products/`, {
    headers: {
      'Authorization': `Bearer ${token}`,
      'X-TENANT-ID': process.env.M2P_TENANT_ID,
      'Content-Type': 'application/json'
    }
  });
  return response.data;
}
import os
import requests

BASE_URL = "https://sandbox-api.m2pprepaid.com"

def get_access_token():
    response = requests.post(f"{BASE_URL}/auth/token", json={
        "clientId": os.environ["M2P_CLIENT_ID"],
        "clientSecret": os.environ["M2P_CLIENT_SECRET"],
        "grantType": "client_credentials"
    })
    return response.json()["access_token"]

def fetch_products(token):
    headers = {
        "Authorization": f"Bearer {token}",
        "X-TENANT-ID": os.environ["M2P_TENANT_ID"],
        "Content-Type": "application/json"
    }
    response = requests.get(f"{BASE_URL}/v1/products/", headers=headers)
    return response.json()
RestTemplate restTemplate = new RestTemplate();

// Get token
HttpHeaders authHeaders = new HttpHeaders();
authHeaders.setContentType(MediaType.APPLICATION_JSON);
Map<String, String> body = Map.of(
    "clientId", clientId,
    "clientSecret", clientSecret,
    "grantType", "client_credentials"
);
var tokenResp = restTemplate.postForEntity(
    baseUrl + "/auth/token",
    new HttpEntity<>(body, authHeaders),
    TokenResponse.class
);

// Make API call
HttpHeaders apiHeaders = new HttpHeaders();
apiHeaders.setBearerAuth(tokenResp.getBody().getAccessToken());
apiHeaders.set("X-TENANT-ID", tenantId);
var resp = restTemplate.exchange(
    baseUrl + "/v1/products/", HttpMethod.GET,
    new HttpEntity<>(apiHeaders), ProductList.class
);

Token Management Best Practices

PracticeRecommendation
Cache tokensTokens valid for expires_in seconds (typically 3600). Cache and reuse.
Refresh proactivelyRefresh 5 minutes before expiry to avoid request failures.
Secure credentialsStore clientId and clientSecret in environment variables or secret managers.
Rotate regularlyRequest credential rotation every 90 days.

Authorization Model

LevelEnforced ByDescription
Tenant IsolationX-TENANT-ID headerAll data isolated per tenant
Role-Based AccessJWT claimsAdmin, Operator, Viewer access levels
Maker-CheckerBusiness rulesDual authorization for critical operations
IP WhitelistingAPI GatewayProduction APIs restricted to whitelisted IPs

On this page