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
| Header | Required | Description |
|---|---|---|
Authorization | Yes | Bearer <JWT_TOKEN> |
X-TENANT-ID | Yes | Your unique tenant identifier |
Content-Type | Yes | application/json |
X-Request-ID | Recommended | Unique 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
| Practice | Recommendation |
|---|---|
| Cache tokens | Tokens valid for expires_in seconds (typically 3600). Cache and reuse. |
| Refresh proactively | Refresh 5 minutes before expiry to avoid request failures. |
| Secure credentials | Store clientId and clientSecret in environment variables or secret managers. |
| Rotate regularly | Request credential rotation every 90 days. |
Authorization Model
| Level | Enforced By | Description |
|---|---|---|
| Tenant Isolation | X-TENANT-ID header | All data isolated per tenant |
| Role-Based Access | JWT claims | Admin, Operator, Viewer access levels |
| Maker-Checker | Business rules | Dual authorization for critical operations |
| IP Whitelisting | API Gateway | Production APIs restricted to whitelisted IPs |
