Authentication (current)
The Current API is deprecated for new integrations. It stays online indefinitely for backward compatibility — existing wiring doesn't need to change — but new builds should target v1 instead.
The current Scratch Power API uses OAuth2 authentication. Each
integrator is provisioned with a client_id, client_secret, an
organisation code, and an integration user (username + password).
To request integration credentials, email support@scratch-power.com.
Hosts
| Environment | Host |
|---|---|
| Production | https://api.scratchpower.com |
| Staging | https://api.staging.scratchpower.com |
Login — get an access token
POST /auth/logincurl -X POST https://api.scratchpower.com/auth/login \
-H "Content-Type: application/json" \
-d '{
"client_id": "your-client-id",
"client_secret": "your-client-secret",
"grant_type": "password",
"identifier": "your-username",
"org_code": "YOUR_ORG",
"secret_pass": "your-password",
"source_channel": "USSD"
}'const res = await fetch("https://api.scratchpower.com/auth/login", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
client_id: process.env.SP_CLIENT_ID,
client_secret: process.env.SP_CLIENT_SECRET,
grant_type: "password",
identifier: process.env.SP_USERNAME,
org_code: process.env.SP_ORG,
secret_pass: process.env.SP_PASSWORD,
source_channel: "USSD",
}),
});
const { access_token, refresh_token, access_in } = await res.json();import os, requests
resp = requests.post(
"https://api.scratchpower.com/auth/login",
json={
"client_id": os.environ["SP_CLIENT_ID"],
"client_secret": os.environ["SP_CLIENT_SECRET"],
"grant_type": "password",
"identifier": os.environ["SP_USERNAME"],
"org_code": os.environ["SP_ORG"],
"secret_pass": os.environ["SP_PASSWORD"],
"source_channel": "USSD",
},
)
data = resp.json()Response
{
"access_token": "eyJhbGciOi...",
"access_in": 3598,
"token_type": "bearer",
"refresh_token": "eyJhbGciOi...",
"scope": "read write"
}access_in is the access token's lifetime in seconds (3600 = 1 hour).
Refresh before it elapses to keep the session alive.
Use the access token on every subsequent call:
Authorization: Bearer <access_token>Refresh
POST /auth/refreshcurl -X POST https://api.scratchpower.com/auth/refresh \
-H "Content-Type: application/json" \
-d '{
"client_id": "your-client-id",
"client_secret": "your-client-secret",
"grant_type": "refresh_token",
"refresh_token": "eyJhbGciOi...",
"source_channel": "USSD"
}'Response shape is identical to /auth/login. Each refresh issues a
new refresh_token — store it and discard the old one.
Logout
DELETE /auth/logout
Authorization: Bearer <access_token>JWTs are stateless — the server does not maintain a blacklist. Logout records an audit event; the caller should discard both tokens locally.
Get the authenticated user
GET /auth/me
Authorization: Bearer <access_token>Returns the actor, role, organisation, and accounts. The
accounts[].id value is the debited_account_id you'll pass on
/api/topup/{validate,confirm}.
{
"actor": {
"id": 6,
"full_name": "ScratchPower Dealer",
"phone_number": "26777469047",
"username": "dealer",
"email": "admin@scratchpower.com",
"status": "ACTIVE"
},
"role": { "id": 6, "code": "DLR", "name": "Dealer", "permissions": ["ROLE_TOPUP", ...] },
"organisation": { "id": 1, "code": "SPW", "name": "Scratch Power" },
"accounts": [
{
"id": 2,
"name": "Current BWP",
"currency": "BWP",
"category": "CURRENT",
"status": "ACTIVE",
"type": "WALLET",
"rank": 1
}
],
"roles": [...]
}In most integrations you'll only ever have one account — call
/auth/me once on bootstrap and cache accounts[0].id for the
debited_account_id field on every transaction.