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.
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/*.
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:
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" }'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:
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 keyfwk_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:
| Scope | Permits |
|---|---|
wallets:read | List wallets and balances. |
wallets:create | Create wallets. |
wallets:update | Update wallet status and metadata. |
transfers:read | List and inspect transfers. |
transfers:create | Create transfers between wallets. |
deposits:read | List deposits. |
deposits:create | Create or simulate deposit events. |
deposits:verify | Verify bank-slip deposits. |
payouts:read | List payout requests and approval cases. |
payouts:create | Create payout requests. |
payouts:approve | Approve payout requests. |
payouts:reject | Reject payout requests. |
ledger:read | Read journal entries and journal lines. |
ledger:write | Post journal entries. |
fees:read | Read fee schedules. |
fees:manage | Manage fee schedules and fee rules. |
team:read | Read tenant team members. |
team:manage | Create and manage tenant team members. |
api_keys:read | List developer applications and API key metadata. |
api_keys:manage | Create, rotate, revoke, and restrict API keys. |
request_logs:read | Search API request logs. |
webhooks:read | List webhook endpoints and deliveries. |
webhooks:manage | Manage webhook endpoints. |
Principle of Least Privilege
Create keys with only the scopes they need:
- A mobile money integration needs
deposits:createand maybewallets:read - A read-only reporting job needs
ledger:read,wallets:read, andrequest_logs:read - A checkout transfer service needs
transfers:createandwallets:read - A tenant developer console needs
api_keys:read,api_keys:manage, andrequest_logs:read
# Key for a read-only reporting servicecurl -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:
| Restriction | Effect |
|---|---|
allowedOrigins | Allows browser-originated requests only from the listed Origin header values. |
allowedIps | Allows requests only from the listed source IPs. |
allowedCurrencies | Limits money-moving requests to specific currencies. |
allowedOwnerTypes | Limits wallet owner types such as user, branch, or company. |
allowedWalletIds | Limits a key to specific wallets. |
maxAmountMinor | Caps per-request amount in the smallest currency unit. |
requireActorHeaders | Requires X-FWallet-Actor-Type and X-FWallet-Actor-Id. |
requireRequestSigning | Requires 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:
| Environment | Purpose |
|---|---|
test | Development and testing. May have relaxed validation, simulated provider webhooks. |
live | Production. 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 Pattern | Required Header | Description |
|---|---|---|
POST /v1/tenants | X-System-Key | Create a new tenant |
POST /v1/tenants/{id}/api-keys | X-System-Key | Provision an API key for a tenant |
/v1/system/* | X-System-Key | Platform administration endpoints |
/v1/wallets/* | X-API-Key | Wallet operations |
/v1/transfers/* | X-API-Key | Transfer operations |
/v1/deposits/* | X-API-Key | Deposit operations |
/v1/journal-entries/* | X-API-Key | Ledger queries |
/v1/admin/* | X-API-Key (with tenant:manage) | Tenant admin operations |
Error Responses
| Status | Meaning |
|---|---|
401 Unauthorized | Missing or invalid API key / system key |
403 Forbidden | Valid key, but insufficient scopes for the requested operation |
{ "error": "unauthorized", "message": "Missing or invalid X-API-Key header"}