Preview: the API is being built and these endpoints may change
Authentication
API keys, how to keep them safe, and how to rotate them without downtime.
Send your key as a bearer token on every request:
curl https://api.simconnectng.com/api/v1/wallet/balance \
-H "Authorization: Bearer $SIMCONNECT_KEY"Keys
- Test keys start with
scn_test_, live keys withscn_live_. The key decides the mode: there is no separate test address. - A key is shown once, when you create it. Store it in your environment or secret manager.
- Keep keys out of client-side code, mobile apps and version control.
A request with no key, or a key that does not exist, is refused with 401 AUTH_REQUIRED.
Rotating a key
Create a new key, deploy it, then revoke the old one. Both work during the overlap, so there is no downtime.
Locking a key down
Each key can carry an IP allowlist. Requests from any other address are refused with 403 PERMISSION_DENIED, "Client address is not allowed for this key".
Signing requests
A key can also require signed requests. Its signing secret is shown once, with the key. Each request then carries two more headers:
| Header | Value |
|---|---|
SimConnect-Timestamp | The current unix time in seconds |
SimConnect-Signature | Lower case hex HMAC SHA-256 of <timestamp>.<raw body>, keyed with the signing secret |
import crypto from "node:crypto";
const body = JSON.stringify({ product_code: "MTN-VTU", amount: 500, phone_number: "08012345678" });
const timestamp = Math.floor(Date.now() / 1000).toString();
const signature = crypto.createHmac("sha256", process.env.SIMCONNECT_SIGNING_SECRET).update(`${timestamp}.${body}`).digest("hex");
// Send body exactly as signed, with SimConnect-Timestamp: timestamp and SimConnect-Signature: signature.Sign the exact bytes you send; a GET signs an empty body. A timestamp more than five minutes from our clock, or a signature that does not match, is refused with 401 AUTH_REQUIRED, "Request signature missing or invalid". The IP allowlist is checked first.