Documentation

Tenant Management

Complete tenant lifecycle management for platform administrators. Create tenants, manage users, configure entitlements, set fees and limits, and monitor tenant health.

Overview

What is a Tenant?

A tenant represents a business entity (merchant, fintech, or enterprise) that uses the platform. Each tenant has isolated data, users, accounts, and configurations. Platform administrators manage tenants through dedicated endpoints.

Tenant Architecture

ComponentDescriptionExample
TenantTop-level business entity with isolated resourcesAcme Payments Ltd
PartnerOwner/contact information for the tenantJohn Doe (john@acme.com)
UsersPeople who access the tenant's dashboardAdmin, Finance, Support staff
AccountsLedger accounts (wallets) belonging to tenant's customersCustomer wallets, merchant wallets
EntitlementsFeature flags controlling what the tenant can doPOS access, virtual accounts, payouts
API KeysProgrammatic access credentials for integrationsServer-to-server API calls
WebhooksEvent notification endpointsTransaction completed, KYC approved

Tenant Lifecycle States

StatusDescriptionAllowed Actions
activeTenant is fully operationalAll operations allowed
suspendedTemporarily disabled, data preservedRead-only, cannot process transactions
inactivePermanently disabledRead-only, pending deletion

Tenant Tiers

Tenants are classified into tiers that may affect rate limits, support levels, and available features.

TierDescriptionTypical Use Case
freeTrial or basic tier with limited featuresStartups, evaluation
paidStandard commercial tierGrowing businesses
enterprisePremium tier with enhanced supportLarge organizations, banks

API Base Path

text
/api/v1/admin/tenants

Required Permission

All tenant management endpoints require platform admin authentication with appropriate permissions.

OperationRequired Permission
List/View tenantsview_tenants
Create/Update tenantsmanage_tenants
Manage entitlementsmanage_tenant_entitlements
Manage usersmanage_tenant_users
Manage API keysmanage_tenant_api_keys
Manage webhooksmanage_tenant_webhooks

Tenant Lifecycle

Create Tenant

POST/api/v1/admin/tenants

Creates a new tenant with partner information. This initializes the tenant's isolated environment and creates default configurations.

Headers

ParameterTypeRequiredDescription
AuthorizationstringYesBearer {admin_access_token}
Content-TypestringYesapplication/json

Response- The created tenant object

json
{
  "id": "tnt_550e8400-e29b-41d4-a716-446655440000",
  "name": "Acme Payments Ltd",
  "status": "active",
  "default_currency": "NGN",
  "is_active": true,
  "metadata": {},
  "created_at": "2024-01-15T09:00:00Z",
  "updated_at": "2024-01-15T09:00:00Z",
  "partner": {
    "id": "prt_f47ac10b-58cc-4372-a567-0e02b2c3d479",
    "name": "John Doe",
    "email": "john@acmepayments.com",
    "tier": "paid",
    "is_active": true
  }
}

Request Payload

json
{
  "name": "Acme Payments Ltd",
  "status": "active",
  "default_currency": "NGN",
  "is_active": true,
  "metadata": {
    "industry": "fintech",
    "onboarding_source": "sales_team",
    "contract_id": "CNT-2024-001"
  },
  "partner": {
    "name": "John Doe",
    "email": "john@acmepayments.com",
    "tier": "paid"
  }
}

List Tenants

GET/api/v1/admin/tenants

Retrieves a paginated list of all tenants with optional filtering.

Headers

ParameterTypeRequiredDescription
AuthorizationstringYesBearer {admin_access_token}

Response- Paginated list of tenants

json
{
  "tenants": [
    {
      "id": "tnt_550e8400-e29b-41d4-a716-446655440000",
      "name": "Acme Payments Ltd",
      "status": "active",
      "default_currency": "NGN",
      "is_active": true,
      "created_at": "2024-01-15T09:00:00Z",
      "partner": {
        "name": "John Doe",
        "email": "john@acmepayments.com",
        "tier": "paid"
      }
    }
  ],
  "pagination": {
    "limit": 50,
    "offset": 0,
    "total_count": 125
  }
}

Get Tenant

GET/api/v1/admin/tenants/{tenantID}

Retrieves detailed information about a specific tenant.

Headers

ParameterTypeRequiredDescription
AuthorizationstringYesBearer {admin_access_token}

Response- Complete tenant object with all details

json
{
  "id": "tnt_550e8400-e29b-41d4-a716-446655440000",
  "name": "Acme Payments Ltd",
  "status": "active",
  "default_currency": "NGN",
  "is_active": true,
  "metadata": {
    "industry": "fintech"
  },
  "created_at": "2024-01-15T09:00:00Z",
  "updated_at": "2024-01-20T14:30:00Z",
  "partner": {
    "id": "prt_f47ac10b-58cc-4372-a567-0e02b2c3d479",
    "name": "John Doe",
    "email": "john@acmepayments.com",
    "tier": "paid",
    "is_active": true
  }
}

Update Tenant

PATCH/api/v1/admin/tenants/{tenantID}

Updates tenant details. All fields are optional; only provided fields are updated.

Headers

ParameterTypeRequiredDescription
AuthorizationstringYesBearer {admin_access_token}
Content-TypestringYesapplication/json

Response- Updated tenant object

json
{
  "id": "tnt_550e8400-e29b-41d4-a716-446655440000",
  "name": "Acme Payments International",
  "status": "active",
  "updated_at": "2024-01-25T10:00:00Z"
}

Request Payload (Update)

json
{
  "name": "Acme Payments International",
  "metadata": {
    "industry": "fintech",
    "region": "west_africa"
  },
  "partner": {
    "tier": "enterprise"
  }
}

Update Tenant Status

PATCH/api/v1/admin/tenants/{tenantID}/status

Changes the tenant's operational status. Use this to suspend or reactivate tenants.

Headers

ParameterTypeRequiredDescription
AuthorizationstringYesBearer {admin_access_token}
Content-TypestringYesapplication/json

Response- Updated tenant with new status

json
{
  "id": "tnt_550e8400-e29b-41d4-a716-446655440000",
  "name": "Acme Payments Ltd",
  "status": "suspended",
  "is_active": false,
  "updated_at": "2024-01-25T10:00:00Z"
}

Request Payload (Status Change)

json
{
  "status": "suspended",
  "is_active": false
}

Status Change Effects

FromToEffect
activesuspendedBlocks all transactions, users can still login (read-only)
suspendedactiveRestores full functionality
activeinactivePermanently disables tenant (data retained)
suspendedinactiveMarks for eventual deletion
inactiveactiveReactivates tenant (if within retention period)

Tenant Users & Invites

User Roles

Tenant users are assigned roles that control their access level within the tenant's dashboard.

RoleDescriptionTypical Access
ownerPrimary account ownerFull access, billing, delete tenant
adminAdministratorFull access except billing/deletion
operatorDay-to-day operationsTransactions, accounts, KYC
financeFinancial operationsTransactions, reports, settlements
supportCustomer supportView accounts, view transactions
viewerRead-only accessView dashboards and reports
memberBasic accessLimited view access

User Statuses

StatusDescription
invitedInvitation sent, pending acceptance
activeUser has accepted and can access
suspendedTemporarily blocked from access
revokedAccess permanently removed

Invite User

POST/api/v1/admin/tenants/{tenantID}/invitations

Sends an invitation email to a new user to join the tenant. The user will receive a link to set up their account.

Headers

ParameterTypeRequiredDescription
AuthorizationstringYesBearer {admin_access_token}
Content-TypestringYesapplication/json

Response- Created user invitation

json
{
  "user": {
    "id": "usr_a8b9c0d1-e2f3-4a5b-6c7d-8e9f0a1b2c3d",
    "tenant_id": "tnt_550e8400-e29b-41d4-a716-446655440000",
    "email": "jane@acmepayments.com",
    "full_name": "Jane Smith",
    "role": "admin",
    "status": "invited",
    "invited_at": "2024-01-20T10:00:00Z"
  },
  "invitation_expires_at": "2024-01-27T10:00:00Z"
}

Request Payload (Invite User)

json
{
  "email": "jane@acmepayments.com",
  "full_name": "Jane Smith",
  "role": "admin",
  "metadata": {
    "department": "operations",
    "employee_id": "EMP-001"
  }
}

List Tenant Users

GET/api/v1/admin/tenants/{tenantID}/users

Retrieves all users associated with a tenant.

Headers

ParameterTypeRequiredDescription
AuthorizationstringYesBearer {admin_access_token}

Response- Paginated list of tenant users

json
{
  "users": [
    {
      "id": "usr_a8b9c0d1-e2f3-4a5b-6c7d-8e9f0a1b2c3d",
      "email": "jane@acmepayments.com",
      "full_name": "Jane Smith",
      "role": "admin",
      "status": "active",
      "last_login_at": "2024-01-25T08:30:00Z"
    }
  ],
  "pagination": {
    "limit": 50,
    "offset": 0,
    "total_count": 12
  }
}

Get Tenant User

GET/api/v1/admin/tenants/{tenantID}/users/{userID}

Retrieves detailed information about a specific tenant user.

Headers

ParameterTypeRequiredDescription
AuthorizationstringYesBearer {admin_access_token}

Response- User details

json
{
  "id": "usr_a8b9c0d1-e2f3-4a5b-6c7d-8e9f0a1b2c3d",
  "tenant_id": "tnt_550e8400-e29b-41d4-a716-446655440000",
  "email": "jane@acmepayments.com",
  "full_name": "Jane Smith",
  "role": "admin",
  "status": "active",
  "metadata": {
    "department": "operations"
  },
  "invited_at": "2024-01-10T10:00:00Z",
  "accepted_at": "2024-01-10T14:30:00Z",
  "last_login_at": "2024-01-25T08:30:00Z"
}

Update Tenant User

PATCH/api/v1/admin/tenants/{tenantID}/users/{userID}

Updates a tenant user's role, status, or metadata.

Headers

ParameterTypeRequiredDescription
AuthorizationstringYesBearer {admin_access_token}
Content-TypestringYesapplication/json

Response- Updated user object

json
{
  "id": "usr_a8b9c0d1-e2f3-4a5b-6c7d-8e9f0a1b2c3d",
  "role": "finance",
  "status": "active",
  "updated_at": "2024-01-25T10:00:00Z"
}

Request Payload (Update User)

json
{
  "role": "finance",
  "metadata": {
    "department": "finance",
    "promoted_from": "operator"
  }
}

Resend User Invite

POST/api/v1/admin/tenants/{tenantID}/users/{userID}/resend-invite

Resends the invitation email to a user who hasn't accepted yet. Generates a new invitation token.

Headers

ParameterTypeRequiredDescription
AuthorizationstringYesBearer {admin_access_token}

Response- New invitation details

json
{
  "user_id": "usr_a8b9c0d1-e2f3-4a5b-6c7d-8e9f0a1b2c3d",
  "invitation_expires_at": "2024-02-01T10:00:00Z",
  "message": "Invitation resent successfully"
}

Tenant API Keys

API Key Concepts

API keys allow tenants to integrate programmatically with the platform. Keys have scopes that control what operations they can perform.

ConceptDescription
Key IDPublic identifier for the key (can be shared/logged)
Full KeySecret key shown ONLY at creation time (store securely)
ScopesPermissions granted to the key
Rate LimitsRequests allowed per minute/day
ExpirationOptional expiry date for time-limited access

Available Scopes

ScopeDescription
accounts:readView account information
accounts:writeCreate and update accounts
transactions:readView transaction history
transactions:writeInitiate transactions
virtual_accounts:readView virtual accounts
virtual_accounts:writeCreate virtual accounts
kyc:readView KYC submissions
kyc:writeSubmit KYC data
pos:readView POS terminals and transactions
pos:writeManage POS operations
webhooks:manageManage webhook endpoints

Create API Key

POST/api/v1/admin/tenants/{tenantID}/api-keys

Creates a new API key for the tenant. The full key is returned ONLY in this response - store it securely.

Headers

ParameterTypeRequiredDescription
AuthorizationstringYesBearer {admin_access_token}
Content-TypestringYesapplication/json

Response- Created key with full secret (shown only once)

json
{
  "full_key": "wc_prod_sk_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
  "key": {
    "key_id": "key_550e8400-e29b-41d4-a716-446655440000",
    "scopes": [
      "accounts:read",
      "transactions:read"
    ],
    "rate_limit_per_min": 100,
    "rate_limit_per_day": 10000,
    "hash_version": 1,
    "is_active": true,
    "created_at": "2024-01-20T10:00:00Z",
    "expires_at": "2025-01-20T10:00:00Z"
  }
}

Request Payload (Create Key)

json
{
  "prefix": "prod",
  "scopes": [
    "accounts:read",
    "accounts:write",
    "transactions:read",
    "transactions:write",
    "virtual_accounts:read",
    "virtual_accounts:write"
  ],
  "rate_limit_per_min": 200,
  "rate_limit_per_day": 50000,
  "expires_at": "2025-12-31T23:59:59Z"
}

List API Keys

GET/api/v1/admin/tenants/{tenantID}/api-keys

Retrieves all API keys for a tenant. Keys are returned without the secret portion.

Headers

ParameterTypeRequiredDescription
AuthorizationstringYesBearer {admin_access_token}

Response- List of API keys

json
{
  "keys": [
    {
      "key_id": "key_550e8400-e29b-41d4-a716-446655440000",
      "scopes": [
        "accounts:read",
        "transactions:read"
      ],
      "rate_limit_per_min": 100,
      "rate_limit_per_day": 10000,
      "is_active": true,
      "last_used_at": "2024-01-25T14:30:00Z",
      "created_at": "2024-01-20T10:00:00Z"
    }
  ]
}

Get API Key

GET/api/v1/admin/tenants/{tenantID}/api-keys/{keyID}

Retrieves details of a specific API key.

Headers

ParameterTypeRequiredDescription
AuthorizationstringYesBearer {admin_access_token}

Response- API key details

json
{
  "key_id": "key_550e8400-e29b-41d4-a716-446655440000",
  "scopes": [
    "accounts:read",
    "transactions:read"
  ],
  "rate_limit_per_min": 100,
  "rate_limit_per_day": 10000,
  "hash_version": 1,
  "is_active": true,
  "last_used_at": "2024-01-25T14:30:00Z",
  "created_at": "2024-01-20T10:00:00Z",
  "expires_at": "2025-01-20T10:00:00Z"
}

Update API Key

PATCH/api/v1/admin/tenants/{tenantID}/api-keys/{keyID}

Updates rate limits, expiration, or active status of an API key. Scopes cannot be modified after creation.

Headers

ParameterTypeRequiredDescription
AuthorizationstringYesBearer {admin_access_token}
Content-TypestringYesapplication/json

Response- Updated API key

json
{
  "key_id": "key_550e8400-e29b-41d4-a716-446655440000",
  "rate_limit_per_min": 500,
  "is_active": true,
  "updated_at": "2024-01-25T10:00:00Z"
}

Request Payload (Update Key)

json
{
  "rate_limit_per_min": 500,
  "rate_limit_per_day": 100000,
  "expires_at": "2026-12-31T23:59:59Z"
}

Deactivate Key Example

json
{
  "is_active": false
}

Tenant Accounts

Account Management

Platform admins can view and manage ledger accounts (wallets) belonging to a tenant's customers. This includes blocking, unblocking, and closing accounts.

Account Statuses

StatusDescriptionCan Transact
activeNormal operational stateYes
frozenTemporarily blocked (compliance, fraud)No
closedPermanently closedNo

Wallet Types

TypeDescription
customerIndividual customer wallet
businessBusiness/corporate wallet
merchantMerchant settlement wallet
agentAgent float wallet
floatPlatform float/operational wallet

List Tenant Accounts

GET/api/v1/admin/tenants/{tenantID}/accounts

Retrieves paginated list of all accounts belonging to a tenant's customers.

Headers

ParameterTypeRequiredDescription
AuthorizationstringYesBearer {admin_access_token}

Response- Paginated list of accounts

json
{
  "accounts": [
    {
      "id": "acc_550e8400-e29b-41d4-a716-446655440000",
      "account_code": "WLT-001234567",
      "account_name": "John Doe",
      "wallet_type": "customer",
      "status": "active",
      "currency": "NGN",
      "balance": 150000,
      "available_balance": 145000,
      "kyc_tier": "tier2",
      "created_at": "2024-01-10T10:00:00Z"
    }
  ],
  "pagination": {
    "limit": 50,
    "offset": 0,
    "total_count": 1250
  }
}

Block Account

PUT/api/v1/admin/tenants/{tenantID}/accounts/{accountID}/block

Blocks an account, preventing any transactions. Use for compliance or fraud investigations.

Headers

ParameterTypeRequiredDescription
AuthorizationstringYesBearer {admin_access_token}
Content-TypestringYesapplication/json

Response- Account status change confirmation with affected child accounts

json
{
  "account": {
    "id": "acc_550e8400-e29b-41d4-a716-446655440000",
    "status": "frozen",
    "post_no_debit": true,
    "post_no_credit": true,
    "updated_at": "2024-01-25T10:00:00Z"
  },
  "child_accounts": []
}

Request Payload (Block)

json
{
  "reason": "Suspicious activity detected - multiple failed transactions from different locations",
  "source": "fraud_detection",
  "block_debits": true,
  "block_credits": true,
  "metadata": {
    "ticket_id": "FRAUD-2024-001",
    "detected_by": "automated_system"
  }
}

Unblock Account

PUT/api/v1/admin/tenants/{tenantID}/accounts/{accountID}/unblock

Removes the block from an account, restoring normal operations.

Headers

ParameterTypeRequiredDescription
AuthorizationstringYesBearer {admin_access_token}
Content-TypestringYesapplication/json

Response- Account status change confirmation with affected child accounts

json
{
  "account": {
    "id": "acc_550e8400-e29b-41d4-a716-446655440000",
    "status": "active",
    "post_no_debit": false,
    "post_no_credit": false,
    "updated_at": "2024-01-26T15:00:00Z"
  },
  "child_accounts": []
}

Request Payload (Unblock)

json
{
  "reason": "Investigation completed - legitimate activity confirmed",
  "source": "compliance_cleared",
  "unblock_debits": true,
  "unblock_credits": true,
  "metadata": {
    "ticket_id": "FRAUD-2024-001",
    "cleared_by": "compliance_officer",
    "resolution": "false_positive"
  }
}

Close Account

PUT/api/v1/admin/tenants/{tenantID}/accounts/{accountID}/close

Permanently closes an account. The account must have zero balance. This action cannot be undone.

Headers

ParameterTypeRequiredDescription
AuthorizationstringYesBearer {admin_access_token}
Content-TypestringYesapplication/json

Response- Closed account confirmation

json
{
  "id": "acc_550e8400-e29b-41d4-a716-446655440000",
  "status": "closed",
  "account_code": "WLT-001234567",
  "account_name": "John Doe",
  "updated_at": "2024-01-27T10:00:00Z"
}

Request Payload (Close)

json
{
  "reason": "Customer requested account closure - all funds have been withdrawn",
  "confirmation": "CLOSE_ACCOUNT",
  "source": "customer_request",
  "metadata": {
    "support_ticket": "SUP-2024-001",
    "requested_by": "customer_email@example.com"
  }
}

Entitlements

Understanding Entitlements

Entitlements are feature flags that control what capabilities a tenant has access to. They are organized by category and can include optional configuration parameters.

Entitlement Categories

CategoryEntitlementsDescription
Identityidentity.readAccess to identity/customer profiles
Accountsaccounts.read, accounts.write, accounts.manageLedger account operations
Balancesbalances.readView account balances
Transactionstransactions.read, transactions.writeTransaction history and initiation
Reservationsreservations.read, reservations.writeBalance reservation management
Limitslimits.read, limits.evaluateTransaction limit configuration
Statementsstatements.read, statements.export, statements.emailAccount statement generation
KYCkyc.submit, kyc.readKnow Your Customer operations
Virtual Accountsvirtual_accounts.read, virtual_accounts.issue_static, virtual_accounts.issue_dynamic, virtual_accounts.sessions.readVirtual account management
Payoutspayouts.writeFunds transfer/payout operations
Webhookswebhooks.manageWebhook endpoint configuration
POSpos.profiles.read/write, pos.terminals.read/manage, pos.transactions.read/write, pos.processor_transactions.write, pos.settlements.read, pos.metrics.readPoint of Sale operations
Cardscards.nfc.read, cards.nfc.manage, cards.nfc.assignments.manage, cards.nfc.limits.manageNFC card management
Liquidityliquidity.readLiquidity monitoring

Get Entitlements

GET/api/v1/admin/tenants/{tenantID}/entitlements

Retrieves all entitlements for a tenant with their current enabled/disabled status.

Headers

ParameterTypeRequiredDescription
AuthorizationstringYesBearer {admin_access_token}

Response- Tenant entitlements map

json
{
  "tenant_id": "tnt_550e8400-e29b-41d4-a716-446655440000",
  "entitlements": {
    "accounts.read": {
      "enabled": true
    },
    "accounts.write": {
      "enabled": true
    },
    "transactions.read": {
      "enabled": true
    },
    "pos.terminals.manage": {
      "enabled": true,
      "config": {
        "max_terminals": 100
      }
    },
    "virtual_accounts.issue_static": {
      "enabled": false
    }
  }
}

Update Entitlements

PATCH/api/v1/admin/tenants/{tenantID}/entitlements

Updates tenant entitlements. Only provided entitlements are modified; others remain unchanged.

Headers

ParameterTypeRequiredDescription
AuthorizationstringYesBearer {admin_access_token}
Content-TypestringYesapplication/json

Response- Updated entitlements

json
{
  "tenant_id": "tnt_550e8400-e29b-41d4-a716-446655440000",
  "entitlements": {
    "pos.terminals.manage": {
      "enabled": true,
      "config": {
        "max_terminals": 500
      }
    },
    "virtual_accounts.issue_static": {
      "enabled": true
    }
  }
}

Request Payload (Update Entitlements)

json
{
  "entitlements": {
    "pos.terminals.manage": {
      "enabled": true,
      "config": {
        "max_terminals": 500
      }
    },
    "pos.transactions.write": {
      "enabled": true
    },
    "virtual_accounts.issue_static": {
      "enabled": true
    },
    "virtual_accounts.issue_dynamic": {
      "enabled": true,
      "config": {
        "max_daily_issuance": 1000
      }
    },
    "payouts.write": {
      "enabled": true
    }
  }
}

Common Entitlement Configurations

EntitlementConfig KeyTypeDescription
pos.terminals.managemax_terminalsintegerMaximum POS terminals allowed
virtual_accounts.issue_dynamicmax_daily_issuanceintegerMaximum VAs per day
transactions.writemax_single_transactionnumberMaximum single transaction amount
payouts.writeallowed_destinationsarrayPermitted payout banks/channels

Tenant Fees

Fee Structure

Fees are rules that determine charges for various transaction types. Each fee rule specifies the channel, calculation method, and who pays/receives the fee.

Fee Channels

ChannelDescription
va_wallet_fundingVirtual account to wallet funding
va_paymentVirtual account payment
va_pos_paymentVirtual account POS payment
funds_transferBank transfer/payout
pos_card_presentPOS card transaction
pos_nfc_cardNFC card tap payment
nin_lookupNIN verification lookup
bvn_lookupBVN verification lookup

Fee Payers

PayerDescription
platformPlatform absorbs the fee
merchantMerchant pays the fee
customerCustomer pays the fee
tenantTenant pays the fee
processorProcessor pays the fee

Get Tenant Fees

GET/api/v1/admin/tenants/{tenantID}/fees

Retrieves all fee rules configured for a tenant.

Headers

ParameterTypeRequiredDescription
AuthorizationstringYesBearer {admin_access_token}

Response- List of fee rules

json
{
  "fees": [
    {
      "id": "fee_550e8400-e29b-41d4-a716-446655440000",
      "tenant_id": "tnt_550e8400-e29b-41d4-a716-446655440000",
      "channel": "pos_card_present",
      "currency": "NGN",
      "flat_amount": 5000,
      "percentage_rate": 0.015,
      "who_pays": "merchant",
      "who_gets_paid": "platform",
      "effective_from": "2024-01-01T00:00:00Z",
      "created_at": "2024-01-01T00:00:00Z"
    }
  ]
}

Update Tenant Fees

PUT/api/v1/admin/tenants/{tenantID}/fees

Replaces all fee rules for a tenant. This is a full replacement - include all rules you want to keep.

Headers

ParameterTypeRequiredDescription
AuthorizationstringYesBearer {admin_access_token}
Content-TypestringYesapplication/json

Response- Updated fee rules

json
{
  "fees": [
    {
      "id": "fee_new_550e8400",
      "channel": "pos_card_present",
      "currency": "NGN",
      "flat_amount": 5000,
      "percentage_rate": 0.012,
      "who_pays": "merchant",
      "effective_from": "2024-02-01T00:00:00Z"
    }
  ]
}

Request Payload (Update Fees)

json
{
  "rules": [
    {
      "channel": "pos_card_present",
      "currency": "NGN",
      "flat_amount": 5000,
      "percentage_rate": 0.012,
      "who_pays": "merchant",
      "who_gets_paid": "platform",
      "effective_from": "2024-02-01T00:00:00Z"
    },
    {
      "channel": "funds_transfer",
      "currency": "NGN",
      "flat_amount": 2500,
      "percentage_rate": 0,
      "min_amount": 10000,
      "max_amount": 50000000,
      "who_pays": "customer",
      "who_gets_paid": "platform",
      "effective_from": "2024-02-01T00:00:00Z"
    },
    {
      "channel": "va_wallet_funding",
      "currency": "NGN",
      "flat_amount": 0,
      "percentage_rate": 0.005,
      "who_pays": "customer",
      "who_gets_paid": "platform",
      "effective_from": "2024-02-01T00:00:00Z"
    }
  ]
}

Transaction Limits

Limit Structure

Transaction limits control the maximum amounts users can transact based on their KYC tier. Limits are defined per direction (inbound/outbound) and time window (daily/monthly).

KYC Tiers

TierDescriptionTypical Limits
tier1Basic verification (phone only)Low limits, suitable for basic use
tier2Standard verification (ID + photo)Medium limits for regular users
tier3Full verification (address proof)High limits for premium users

Limit Parameters

ParameterDescription
directioninbound (deposits) or outbound (withdrawals/payments)
windowdaily or monthly accumulation period
amountMaximum cumulative amount in the window
max_balanceMaximum account balance allowed (optional)

Get Tenant Limits

GET/api/v1/admin/tenants/{tenantID}/limits

Retrieves all transaction limits configured for a tenant.

Headers

ParameterTypeRequiredDescription
AuthorizationstringYesBearer {admin_access_token}

Response- List of transaction limits by KYC tier

json
{
  "limits": [
    {
      "tenant_id": "tnt_550e8400-e29b-41d4-a716-446655440000",
      "kyc_level": "tier1",
      "direction": "inbound",
      "window": "daily",
      "amount": 50000,
      "max_balance": 200000,
      "updated_at": "2024-01-15T10:00:00Z"
    },
    {
      "tenant_id": "tnt_550e8400-e29b-41d4-a716-446655440000",
      "kyc_level": "tier2",
      "direction": "inbound",
      "window": "daily",
      "amount": 500000,
      "max_balance": 2000000,
      "updated_at": "2024-01-15T10:00:00Z"
    }
  ]
}

Update Tenant Limits

PUT/api/v1/admin/tenants/{tenantID}/limits

Updates transaction limits for a tenant. Replaces all limits with the provided configuration.

Headers

ParameterTypeRequiredDescription
AuthorizationstringYesBearer {admin_access_token}
Content-TypestringYesapplication/json

Response- Updated limits

json
{
  "limits": [
    {
      "kyc_level": "tier1",
      "direction": "inbound",
      "window": "daily",
      "amount": 100000,
      "updated_at": "2024-01-25T10:00:00Z"
    }
  ]
}

Request Payload (Update Limits)

json
{
  "limits": [
    {
      "kyc_level": "tier1",
      "direction": "inbound",
      "window": "daily",
      "amount": 100000,
      "max_balance": 300000
    },
    {
      "kyc_level": "tier1",
      "direction": "outbound",
      "window": "daily",
      "amount": 50000
    },
    {
      "kyc_level": "tier2",
      "direction": "inbound",
      "window": "daily",
      "amount": 1000000,
      "max_balance": 5000000
    },
    {
      "kyc_level": "tier2",
      "direction": "outbound",
      "window": "daily",
      "amount": 500000
    },
    {
      "kyc_level": "tier3",
      "direction": "inbound",
      "window": "daily",
      "amount": 10000000,
      "max_balance": 50000000
    },
    {
      "kyc_level": "tier3",
      "direction": "outbound",
      "window": "daily",
      "amount": 5000000
    }
  ]
}

Tenant Webhooks

Webhook System

Webhooks allow tenants to receive real-time notifications when events occur. Platform admins can manage webhook endpoints on behalf of tenants.

Available Events

EventDescription
account.createdNew account created
account.updatedAccount details modified
account.blockedAccount was blocked
account.unblockedAccount was unblocked
account.closedAccount was permanently closed
transaction.completedTransaction successfully processed
transaction.failedTransaction failed
transaction.reversedTransaction was reversed
kyc.submittedKYC application submitted
kyc.approvedKYC application approved
kyc.rejectedKYC application rejected
virtual_account.createdVirtual account created
virtual_account.expiredVirtual account expired
pos.transaction.completedPOS transaction completed
pos.settlement.completedPOS settlement batch completed

Create Webhook Endpoint

POST/api/v1/admin/tenants/{tenantID}/webhooks/endpoints

Creates a new webhook endpoint for the tenant. A signing secret is automatically generated.

Headers

ParameterTypeRequiredDescription
AuthorizationstringYesBearer {admin_access_token}
Content-TypestringYesapplication/json

Response- Created webhook endpoint with signing secret

json
{
  "id": "wh_550e8400-e29b-41d4-a716-446655440000",
  "url": "https://api.acme.com/webhooks/walletcore",
  "events": [
    "transaction.completed",
    "transaction.failed"
  ],
  "description": "Production transaction events",
  "is_active": true,
  "secret_masked": "wh_sec_****abcd",
  "signing_secret": "wh_sec_a1b2c3d4e5f6g7h8i9j0",
  "created_at": "2024-01-20T10:00:00Z"
}

Request Payload (Create Webhook)

json
{
  "url": "https://api.acme.com/webhooks/walletcore",
  "events": [
    "transaction.completed",
    "transaction.failed",
    "transaction.reversed",
    "account.created",
    "kyc.approved",
    "kyc.rejected"
  ],
  "description": "Production webhook for all critical events"
}

List Webhook Endpoints

GET/api/v1/admin/tenants/{tenantID}/webhooks/endpoints

Retrieves all webhook endpoints for a tenant.

Headers

ParameterTypeRequiredDescription
AuthorizationstringYesBearer {admin_access_token}

Response- List of webhook endpoints

json
{
  "endpoints": [
    {
      "id": "wh_550e8400-e29b-41d4-a716-446655440000",
      "url": "https://api.acme.com/webhooks/walletcore",
      "events": [
        "transaction.completed",
        "transaction.failed"
      ],
      "is_active": true,
      "secret_masked": "wh_sec_****abcd",
      "created_at": "2024-01-20T10:00:00Z"
    }
  ]
}

Get Webhook Endpoint

GET/api/v1/admin/tenants/{tenantID}/webhooks/endpoints/{id}

Retrieves details of a specific webhook endpoint.

Headers

ParameterTypeRequiredDescription
AuthorizationstringYesBearer {admin_access_token}

Response- Webhook endpoint details

json
{
  "id": "wh_550e8400-e29b-41d4-a716-446655440000",
  "url": "https://api.acme.com/webhooks/walletcore",
  "events": [
    "transaction.completed",
    "transaction.failed"
  ],
  "description": "Production transaction events",
  "is_active": true,
  "secret_masked": "wh_sec_****abcd",
  "created_at": "2024-01-20T10:00:00Z"
}

Update Webhook Endpoint

PATCH/api/v1/admin/tenants/{tenantID}/webhooks/endpoints/{id}

Updates a webhook endpoint. Can modify URL, events, description, or rotate the signing secret.

Headers

ParameterTypeRequiredDescription
AuthorizationstringYesBearer {admin_access_token}
Content-TypestringYesapplication/json

Response- Updated webhook endpoint (includes new secret if rotated)

json
{
  "id": "wh_550e8400-e29b-41d4-a716-446655440000",
  "url": "https://api.acme.com/webhooks/v2/walletcore",
  "events": [
    "transaction.completed",
    "transaction.failed",
    "kyc.approved"
  ],
  "is_active": true,
  "signing_secret": "wh_sec_new_secret_here"
}

Request Payload (Update Webhook)

json
{
  "url": "https://api.acme.com/webhooks/v2/walletcore",
  "events": [
    "transaction.completed",
    "transaction.failed",
    "kyc.approved",
    "kyc.rejected"
  ],
  "rotate_secret": true
}

Delete Webhook Endpoint

DELETE/api/v1/admin/tenants/{tenantID}/webhooks/endpoints/{id}

Permanently deletes a webhook endpoint.

Headers

ParameterTypeRequiredDescription
AuthorizationstringYesBearer {admin_access_token}

Response- Empty response with 204 No Content

json

Get Webhook Stats

GET/api/v1/admin/tenants/{tenantID}/webhooks/endpoints/{id}/stats

Retrieves delivery statistics for a webhook endpoint.

Headers

ParameterTypeRequiredDescription
AuthorizationstringYesBearer {admin_access_token}

Response- Webhook delivery statistics

json
{
  "total_deliveries": 15420,
  "success_count": 15350,
  "failure_count": 70,
  "success_rate": 99.55,
  "avg_response_time_ms": 145,
  "last_success": "2024-01-25T14:30:00Z",
  "last_failure": "2024-01-24T08:15:00Z"
}

Test Webhook Endpoint

POST/api/v1/admin/tenants/{tenantID}/webhooks/endpoints/{id}/test

Sends a test event to the webhook endpoint to verify connectivity.

Headers

ParameterTypeRequiredDescription
AuthorizationstringYesBearer {admin_access_token}
Content-TypestringYesapplication/json

Response- Test delivery result

json
{
  "test_event_id": "evt_550e8400-e29b-41d4-a716-446655440000",
  "delivered": true,
  "http_status": 200,
  "response_time_ms": 125,
  "message": "Webhook test event delivered successfully"
}

Request Payload (Test Webhook)

json
{
  "event_type": "transaction.completed"
}

KYC & Liquidity

KYC Summary

View aggregate KYC statistics for a tenant's customers.

Get KYC Summary

GET/api/v1/admin/tenants/{tenantID}/kyc/summary

Retrieves KYC application counts by status for the tenant.

Headers

ParameterTypeRequiredDescription
AuthorizationstringYesBearer {admin_access_token}

Response- KYC status summary

json
{
  "tenant_id": "tnt_550e8400-e29b-41d4-a716-446655440000",
  "counts": {
    "pending": 45,
    "approved": 1250,
    "rejected": 23
  },
  "updated_at": "2024-01-25T10:00:00Z"
}

Liquidity Monitoring

Liquidity snapshots track the relationship between customer liabilities (what you owe customers) and available funds (what you have). This helps ensure you can honor all withdrawal requests.

Liquidity Metrics

MetricDescriptionHealthy Range
total_customer_liabilitiesSum of all customer balancesBaseline
total_available_liquidityFunds available to cover liabilities>= liabilities
liquidity_shortfallGap when liquidity < liabilitiesShould be 0
liquidity_surplusExcess when liquidity > liabilitiesPositive
coverage_ratioLiquidity / Liabilities * 100>= 100%
buffer_percentExtra cushion above requirements5-10% recommended

Get Latest Liquidity Snapshot

GET/api/v1/admin/tenants/{tenantID}/liquidity/snapshots/latest

Retrieves the most recent liquidity snapshot for each currency.

Headers

ParameterTypeRequiredDescription
AuthorizationstringYesBearer {admin_access_token}

Response- Latest liquidity snapshots by currency

json
{
  "snapshots": [
    {
      "snapshot_id": "liq_550e8400-e29b-41d4-a716-446655440000",
      "currency": "NGN",
      "snapshot_at": "2024-01-25T10:00:00Z",
      "total_customer_liabilities": 125000000,
      "total_available_liquidity": 132500000,
      "liquidity_shortfall": 0,
      "liquidity_surplus": 7500000,
      "coverage_ratio": 106,
      "buffer_percent": 6,
      "created_at": "2024-01-25T10:00:00Z"
    }
  ]
}

List Liquidity Snapshots

GET/api/v1/admin/tenants/{tenantID}/liquidity/snapshots

Retrieves historical liquidity snapshots with filtering and pagination.

Headers

ParameterTypeRequiredDescription
AuthorizationstringYesBearer {admin_access_token}

Response- Paginated liquidity snapshots

json
{
  "snapshots": [
    {
      "snapshot_id": "liq_550e8400",
      "currency": "NGN",
      "snapshot_at": "2024-01-25T10:00:00Z",
      "coverage_ratio": 106
    }
  ],
  "pagination": {
    "limit": 50,
    "offset": 0,
    "total_count": 720
  }
}

Get Liquidity Snapshot Detail

GET/api/v1/admin/tenants/{tenantID}/liquidity/snapshots/{snapshotID}

Retrieves detailed breakdown of a specific liquidity snapshot.

Headers

ParameterTypeRequiredDescription
AuthorizationstringYesBearer {admin_access_token}

Response- Detailed liquidity snapshot with breakdown

json
{
  "snapshot": {
    "snapshot_id": "liq_550e8400-e29b-41d4-a716-446655440000",
    "currency": "NGN",
    "snapshot_at": "2024-01-25T10:00:00Z",
    "total_customer_liabilities": 125000000,
    "total_available_liquidity": 132500000,
    "coverage_ratio": 106
  },
  "breakdown": {
    "by_wallet_type": {
      "customer": 85000000,
      "business": 30000000,
      "merchant": 10000000
    }
  }
}

Best Practices

Tenant Onboarding Checklist

StepActionNotes
1Create tenant with partner detailsVerify email address is correct
2Configure entitlementsStart with minimal permissions, expand as needed
3Set up transaction limitsConsider business type and expected volume
4Configure feesAlign with commercial agreement
5Invite initial usersStart with owner/admin roles
6Create API keysProduction and test keys with appropriate scopes
7Set up webhooksCritical events: transactions, KYC
8Verify integrationTest API calls and webhook delivery

Security Recommendations

AreaRecommendation
API KeysSet expiration dates, use least-privilege scopes
WebhooksAlways validate signatures, use HTTPS only
User AccessRegular access reviews, revoke inactive users
EntitlementsGrant only necessary permissions
Account OperationsDocument reasons for block/unblock actions

Monitoring Alerts

Key metrics to monitor for tenant health.

MetricWarning ThresholdAction
Coverage ratio< 105%Review liquidity position
Webhook failure rate> 5%Check endpoint health
KYC rejection rate> 20%Review submission quality
API rate limit hits> 100/dayConsider increasing limits
Blocked accounts> 10/dayInvestigate fraud patterns