Authentication
MID uses two credentials: signed API requests for your server-to-server integration, and a merchant JWT for the dashboard/onboarding APIs.
Request signing (server-to-server)
Verification endpoints such as POST /v1/oauth/requests and POST /v1/oauth/token are authenticated with your application's API key plus an HMAC-SHA256 signature. Send three headers on every request:
| Header | Value |
|---|---|
| X-API-Key | Application API key — mk_test_… (sandbox) or mk_live_… (production) |
| X-Timestamp | Unix time in milliseconds; rejected if more than 5 minutes from server time |
| X-Signature | Hex HMAC-SHA256 of `${apiKey}:${timestamp}:${JSON.stringify(body)}` keyed with your secret |
import crypto from 'crypto';
function midHeaders(apiKey, secret, body) {
const timestamp = Date.now().toString();
const payload = `${apiKey}:${timestamp}:${JSON.stringify(body)}`;
const signature = crypto.createHmac('sha256', secret).update(payload).digest('hex');
return {
'Content-Type': 'application/json',
'X-API-Key': apiKey,
'X-Timestamp': timestamp,
'X-Signature': signature,
};
}
const body = { recipient: '+2348012345678', /* … */ };
await fetch('https://api.dev.mobid.io/v1/oauth/requests', {
method: 'POST',
headers: midHeaders(API_KEY, API_SECRET, body),
body: JSON.stringify(body),
});Sign the exact body you send
401 Invalid signature.Application credentials
API access belongs to a merchant application, not an individual dashboard user. Create and manage applications with a merchant JWT, then use the application credentials from your backend.
| Credential | Purpose | Lifecycle |
|---|---|---|
| clientId | Identifies the application in consent and webhook data | Stable for the application |
| apiKey | Selects sandbox or live access and is included in the HMAC payload | Can be rotated |
| secret | HMAC signing key and webhook verification key | Returned at creation; kept during API-key rotation |
| Environment | Key prefix | Access |
|---|---|---|
| sandbox | mk_test_… | Issued immediately when an application is created |
| live | mk_live_… | Usable only after the merchant's live access is approved |
Rotating an API key
POST /v1/merchants/applications/:id/rotate-key with your merchant JWT and { "environment": "sandbox" } or live. The previous key stops working immediately; the secret remains unchanged. See the rotation guide.Merchant JWT (dashboard APIs)
The merchant onboarding APIs under /v1/merchants/* are authenticated with a bearer JWT returned by login. Use it to manage your business profile, documents, applications, and team.
/v1/merchants/loginExchange email + password for a merchant JWT
curl -X GET 'https://api.mobid.io/v1/merchants/me' \
-H 'Authorization: Bearer <merchant_jwt>'Where keys come from
Errors
MID uses conventional HTTP status codes. Error responses carry error: true and a human-readable message.
| Code | Meaning |
|---|---|
| 200 / 201 | Success |
| 400 | Bad Request — missing or invalid parameter |
| 401 | Unauthorized — missing/invalid API key, bad signature, or expired timestamp |
| 403 | Forbidden — OAUTH not enabled for the app, or live access not approved |
| 404 | Not Found — user not enrolled or resource missing |
| 429 | Too Many Requests — rate limit exceeded |
| 5xx | Server Error — rare; safe to retry with backoff |
{
"error": true,
"message": "Invalid signature"
}