Skip to content

Authentication

FWallet uses header-based API key authentication. There are two authentication modes, each for a different level of access.

Authentication Modes

X-API-Key — Tenant-Scoped Bearer Keys

Used for all tenant-scoped operations: managing wallets, creating transfers, processing deposits, querying ledger entries, and tenant administration.

Terminal window
curl https://api.fwallet.co.ug/v1/wallets \
-H "X-API-Key: fwk_test_a1b2c3d4e5f6..."

The API key determines which tenant the request belongs to. You never pass a tenant_id in the URL or body — it is derived from the key. This means a key can only access data belonging to its tenant.

HMAC request signing — Tenant-Scoped Signed Keys

High-risk server-to-server integrations can use HMAC request signing instead of sending a bearer secret on every request. Signed requests use the API key id plus timestamp, nonce, content hash, and signature headers.

See Request Signing for the canonical request format, verification rules, and SDK-oriented TypeScript and Python examples.

X-System-Key — Platform-Level

Used for platform administration: creating tenants, provisioning API keys, and accessing system-wide endpoints under /v1/system/*.

Terminal window
curl https://api.fwallet.co.ug/v1/tenants \
-H "X-System-Key: $SYSTEM_KEY"

The system key is configured at the platform level (environment variable) and is not tenant-scoped.

Provisioning API Keys

Organization admins can create applications and API keys in the dashboard at /developers. The dashboard shows the raw bearer key or signing secret only once after creation or rotation.

Server-side provisioning is available through tenant developer endpoints when the caller already has an admin-scoped tenant key:

Terminal window
curl -X POST https://api.fwallet.co.ug/v1/developer/apps \
-H "Content-Type: application/json" \
-H "X-API-Key: $TENANT_ADMIN_KEY" \
-d '{
"name": "Checkout Service",
"description": "Server-to-server checkout integration",
"environment": "live"
}'
Terminal window
curl -X POST https://api.fwallet.co.ug/v1/developer/api-keys \
-H "Content-Type: application/json" \
-H "X-API-Key: $TENANT_ADMIN_KEY" \
-d '{
"name": "Checkout Transfers",
"applicationId": "app_01JQHXYZ...",
"authMode": "hmac",
"scopes": ["transfers:create", "wallets:read", "request_logs:read"],
"environment": "live",
"restrictions": {
"allowedOrigins": ["https://checkout.example.com"],
"allowedIps": ["203.0.113.10"],
"requireActorHeaders": true,
"requireRequestSigning": true
}
}'

Initial bootstrap keys can still be created via the system endpoint:

Terminal window
curl -X POST https://api.fwallet.co.ug/v1/tenants/tn_01JQHXYZ.../api-keys \
-H "Content-Type: application/json" \
-H "X-System-Key: $SYSTEM_KEY" \
-d '{
"name": "Production Key",
"scopes": [
"ledger:read",
"ledger:write",
"wallet:transfer",
"wallet:deposit",
"tenant:manage"
],
"environment": "test"
}'

Response:

{
"id": "ak_01JQHXYZ...",
"name": "Production Key",
"key": "fwk_test_a1b2c3d4e5f6g7h8i9j0...",
"scopes": [
"ledger:read",
"ledger:write",
"wallet:transfer",
"wallet:deposit",
"tenant:manage"
],
"environment": "test",
"createdAt": "2026-03-18T10:00:01.000Z"
}

Key Format

API keys follow a predictable prefix format:

fwk_{environment}_{random}
  • fwk_test_... — test environment key
  • fwk_live_... — live environment key

The prefix makes it easy to identify the environment a key belongs to and to detect accidental use of test keys in production (or vice versa).

Scopes

Each API key has a set of scopes that control what operations it can perform:

ScopePermits
wallets:readList wallets and balances.
wallets:createCreate wallets.
wallets:updateUpdate wallet status and metadata.
transfers:readList and inspect transfers.
transfers:createCreate transfers between wallets.
deposits:readList deposits.
deposits:createCreate or simulate deposit events.
deposits:verifyVerify bank-slip deposits.
payouts:readList payout requests and approval cases.
payouts:createCreate payout requests.
payouts:approveApprove payout requests.
payouts:rejectReject payout requests.
ledger:readRead journal entries and journal lines.
ledger:writePost journal entries.
fees:readRead fee schedules.
fees:manageManage fee schedules and fee rules.
team:readRead tenant team members.
team:manageCreate and manage tenant team members.
api_keys:readList developer applications and API key metadata.
api_keys:manageCreate, rotate, revoke, and restrict API keys.
request_logs:readSearch API request logs.
webhooks:readList webhook endpoints and deliveries.
webhooks:manageManage webhook endpoints.

Principle of Least Privilege

Create keys with only the scopes they need:

  • A mobile money integration needs deposits:create and maybe wallets:read
  • A read-only reporting job needs ledger:read, wallets:read, and request_logs:read
  • A checkout transfer service needs transfers:create and wallets:read
  • A tenant developer console needs api_keys:read, api_keys:manage, and request_logs:read
Terminal window
# Key for a read-only reporting service
curl -X POST https://api.fwallet.co.ug/v1/developer/api-keys \
-H "Content-Type: application/json" \
-H "X-API-Key: $TENANT_ADMIN_KEY" \
-d '{
"name": "Reporting Dashboard",
"scopes": ["ledger:read", "wallets:read", "request_logs:read"],
"environment": "live"
}'

Response:

{
"id": "ak_02ABCDEF...",
"name": "Reporting Dashboard",
"key": "fwk_live_x9y8z7w6v5u4...",
"scopes": ["ledger:read"],
"environment": "live",
"createdAt": "2026-03-18T10:00:02.000Z"
}

Restrictions

API key restrictions narrow where and how a key can be used:

RestrictionEffect
allowedOriginsAllows browser-originated requests only from the listed Origin header values.
allowedIpsAllows requests only from the listed source IPs.
allowedCurrenciesLimits money-moving requests to specific currencies.
allowedOwnerTypesLimits wallet owner types such as user, branch, or company.
allowedWalletIdsLimits a key to specific wallets.
maxAmountMinorCaps per-request amount in the smallest currency unit.
requireActorHeadersRequires X-FWallet-Actor-Type and X-FWallet-Actor-Id.
requireRequestSigningRequires HMAC signed requests. Only valid for keys with authMode: "hmac".

Request Logs

Tenant admins can inspect request metadata through GET /v1/developer/request-logs or the dashboard Developers area. Logs include tenant, API key id, application id, endpoint, status code, timing, origin, IP, actor headers, idempotency key, correlation id, request body hash, and signature verification status.

Request logs do not store raw API keys, signing secrets, or full request bodies.

If a key attempts an operation outside its scopes, the API returns 403 Forbidden:

{
"error": "forbidden",
"message": "API key does not have the required scope: wallet:transfer"
}

Environments

API keys are created in one of two environments:

EnvironmentPurpose
testDevelopment and testing. May have relaxed validation, simulated provider webhooks.
liveProduction. Full validation, real provider integrations.

The environment is set at key creation time and cannot be changed. This prevents accidental use of test infrastructure in production.

Endpoint Authentication Summary

Endpoint PatternRequired HeaderDescription
POST /v1/tenantsX-System-KeyCreate a new tenant
POST /v1/tenants/{id}/api-keysX-System-KeyProvision an API key for a tenant
/v1/system/*X-System-KeyPlatform administration endpoints
/v1/wallets/*X-API-KeyWallet operations
/v1/transfers/*X-API-KeyTransfer operations
/v1/deposits/*X-API-KeyDeposit operations
/v1/journal-entries/*X-API-KeyLedger queries
/v1/admin/*X-API-Key (with tenant:manage)Tenant admin operations

Error Responses

StatusMeaning
401 UnauthorizedMissing or invalid API key / system key
403 ForbiddenValid key, but insufficient scopes for the requested operation
{
"error": "unauthorized",
"message": "Missing or invalid X-API-Key header"
}