Admin
2 API calls in this section.
Admin endpoints for querying wallets for other users within the same tenant.
Get User Wallet
/wallets/user-walletGet User Wallet (Admin)
Returns wallet + transaction history for a specific user (same tenant). data.wallet.balance is usable funds and data.wallet.reserved is the total held for draft deliveries. Currency is not returned; the frontend displays it from tenant configuration.
Requires Bearer Token authentication:
Authorization: Bearer {{access_token}}(or API key)Requires permission:
tenant:wallet:management
Response
Returns
data.user,data.wallet,data.transactions,data.summary,data.pagination.data.summary.total_count— Total filtered transactions across all pages.data.summary.total_credited— Sum of all positive amounts (full filtered ledger).data.summary.total_debited— Sum of absolute negative amounts (full filtered ledger).
Stored transaction context
Each transaction also includes source: string | null and recorded_by: { id: string | null, name: string | null } | null. These values come only from saved transaction metadata (source, actor_user_id, actor_name), with empty or missing values returned as null. Historical names are not looked up or invented. Customer manual adjustment rows also include manual_transaction with saved type, reason, reference: string | null, notes: string | null, and actor: {id, name}. Reference and Notes are null for older records without those fields; non-manual rows omit this object. Existing permissions and query filters for this endpoint are unchanged. Source/Recorded By column filtering is available on GET /users/:userId/wallet/transactions using source and actor_name.
Query parameters
| Parameter | Type | Description |
|---|---|---|
user_idRequired | string | Target user UUID (required) Example: |
page | string | Page number for pagination (default: 1) Example: |
limit | string | Number of items per page (default: 20, max: 100) Example: |
type | string | Filter by transaction type: topup, transfer, payment, earning |
from_date | string | Filter from date (ISO format: 2024-01-01T00:00:00Z) |
to_date | string | Filter to date (ISO format: 2024-12-31T23:59:59Z) |
search | string | Search in description/reference fields and by exact amount when numeric |
languageOptional | string | Language code for response localization (Optional, default: en) . Example: |
Headers
| Parameter | Type | Description |
|---|---|---|
Authorization | string | Example: |
1curl --globoff --request GET "https://staging-api.ondi.io/functions/v1/wallets/user-wallet?user_id=${USER_ID}&page=1&limit=20&type=&from_date=&to_date=&search=&language=en" \2 --header "Authorization: Bearer ${ONDI_ACCESS_TOKEN}"Response examples
1{2 "success": false,3 "message": "Unauthorized"4}List Tenant Wallet Transactions
/wallets/tenant-transactionsRead-only, tenant-wide wallet ledger for the Financial Dashboard's Transactions and Adjustments tabs. The primary entity is one persisted wallet_transactions entry. This does not return cash COD collections, payment attempts, or reserved draft funds that have not become ledger entries.
Authentication and authorization
Requires Bearer token authentication (Authorization: Bearer {{access_token}}) or an authorized X-API-Key. The resolved user must be a system administrator, have the exact tenant_admin role, or hold at least one of manage:operations:tenant, view:finance:tenant, view:financial_reports, or manage:wallets. Ordinary viewers use their authenticated tenant context; a supplied tenant_id must match it or the request returns 403. System administrators authenticated by JWT or a system-scoped API key may select a tenant with tenant_id; tenant-scoped API keys remain bound to their tenant even when their owner is a system administrator. Every supplied tenant ID is validated as a UUID.
Column filters
| Key | Value | Meaning |
|---|---|---|
account_name | string | Literal case-insensitive name substring |
account_type | driver, customer, company, staff | Wallet account category |
customer_type | individual, business, institution | Customer subtype; implies account_type=customer |
direction | credit, debit | Wallet movement direction |
type | string | Exact stored ledger type selected from data.type_options |
amount | {"min": 10, "max": 100} | Inclusive range of absolute transaction amounts; either bound is optional and must be nonnegative and less than 1,000,000,000,000,000 |
description | string | Literal substring in reason or description |
reason | string | Literal reason substring |
actor_name | string | Literal substring of the returned administrator name |
created_at | {"from": "2026-10-01", "to": "2026-10-17"} | Inclusive UTC dates; either bound is optional. Full ISO timestamps mean exact instants |
source | string | Exact stored source selected from data.source_options |
reference | string | Literal saved-reference substring |
notes | string | Literal notes substring |
currency_code | three-letter string | Exact saved currency code; input is normalized to uppercase |
delivery_code | string | Literal linked-delivery code substring |
external_reference_id | string | Literal linked-delivery external-reference substring |
Example column_filters:
A customer subtype combined with an explicit non-customer account type is invalid. Unknown column/range keys, malformed JSON, unsupported enum values, reversed ranges, invalid dates, and oversized text values return HTTP 400. Text/search values are limited to 500 characters. Text filter characters such as % and _ are ordinary text rather than wildcard instructions. An omitted or cleared filter does not restrict results.
Response and business rules
data.transactionscontains the requested page;pagination.totalandtotal_pagesdescribe the same complete filtered population.accountcontainsuser_id,name,account_type,customer_type, anddriver_id. Company/staff accounts are included in Transactions when present; customer subtype comes from the current tenant membership and is null for non-customers.typeis the raw persisted ledger type.amountis the signed saved amount.directioniscreditordebit; zero amounts andcurrency_adjustment,frozen, andunfrozenrows have null direction. The amount-range filter uses the absolute magnitude.currency_codeis the saved transaction currency, or null when unavailable. It is not reconstructed from the tenant's current currency setting.descriptionis the stored description.reason,reference, andnotesare separate saved metadata values, null when absent. Manual reference is distinct fromdelivery.external_reference_id.is_manualis true only for saved sourcesmanual_credit,manual_debit, andcustomer_manual_adjustment, including manual rows with a linked delivery.manual_only=truefixes that scope regardless of other filters.recorded_byis{id, name}when saved actor context exists, otherwise null. A saved actor-name snapshot is preferred; older rows with only a saved actor ID can use that user's current profile name. Savedprocessed_by_user_idis used whenactor_user_idis absent (for example, payouts). Missing actors are not inferred from the wallet owner or labelled as System.source_options,type_options, andcurrency_optionscontain sorted distinct saved values from the full current tenant/tab scope, independently of column filters, search, and pagination, so options remain available for an empty filtered result. Source/type filters are exact, case-sensitive raw strings, not a closed enum.deliveryis null or{id, delivery_code, barcode, external_reference_id}.balance_snapshotis the saved balance after that entry, or null.This endpoint does not create adjustments or alter wallets. Existing driver/customer manual-transaction actions remain on their detail pages.
Frontend integration contract
Both tabs call this endpoint. Transactions sends manual_only=false; Adjustments always sends manual_only=true. Use the existing grid's column filters and reset to page 1 when filters, search, or page size change. Selecting a customer subtype selects Customer; switching to another account type clears the customer subtype. Render stored currency alongside the amount and preserve reference/notes in the table or transaction details. Link Driver accounts with account.driver_id, Customer accounts with account.user_id, and linked deliveries with delivery.id; do not send Company/Staff accounts to a customer detail page. No transaction action values are returned by this read endpoint.
Errors
400 invalid_query: malformed tenant UUID or invalid query/column filters. The localizedmessagesummarizes the first issue;detailscontains{field, message}for each issue. For example,column_filters.customer_typeconflicts with an explicit Driver account filter.400 tenant_id_required: no tenant was resolved from the authorized context.401: missing authentication; the authentication middleware returns a localized message. Invalid or inactive authentication can return403.403 insufficient_permissions: the authenticated user lacks finance access or attempted a tenant selection outside the allowed context.405 method_not_allowed: this route accepts GET only;Allow: GETis returned.500 internal_server_error: the ledger query failed; no partial list is returned. Frontend clients should show the localized message and use the stablecodeanddetails[].fieldvalues for handling; do not branch on translated message text. Do not render a read failure as an empty successful table.
Performance
The handler uses one read-only RPC for the ledger result. Ownership, filters, matching-row count, sorting, page selection, and source options run in the database, with no per-row API lookups or frontend filtering of a partial page. Pagination and its total share one database snapshot.
Query parameters
| Parameter | Type | Description |
|---|---|---|
tenant_id | string | Optional tenant UUID; ordinary viewers and tenant-scoped API keys must match authenticated tenant context. Authorized system admins may select a tenant. optional tenant UUID. Defaults to the authenticated tenant. Required when an authorized system administrator has no tenant context; otherwise it must follow the tenant-selection rules above. Example: |
manual_only | string | false: all wallet entries; true: saved manual driver/customer adjustments only. Example: |
page | string | Positive page number. Default 1. positive integer, default Example: |
limit | string | Rows per page. Default 25, maximum 100. positive integer, default Example: |
sort_by | string |
Example: |
sort_order | string | asc or desc. Example: |
searchOptional | string | Literal case-insensitive text search. optional literal, case-insensitive text search across account name, description, reason, actor name, reference, notes, delivery code, and delivery external reference. |
column_filtersOptional | string | JSON column filters; see the documented schema. Apply before pagination. optional JSON object; URL-encode it once through Example: |
language | string | Response language: en, ar, fa, ku. response localization language ( Example: |
Headers
| Parameter | Type | Description |
|---|---|---|
Authorization | string | Example: |
More examples
1{2 "account_type": "customer",3 "customer_type": "business",4 "direction": "credit",5 "amount": {6 "min": 10,7 "max": 1008 },9 "created_at": {10 "from": "2026-10-01",11 "to": "2026-10-17"12 }13}1curl --globoff --request GET "https://staging-api.ondi.io/functions/v1/wallets/tenant-transactions?tenant_id=${TENANT_ID}&manual_only=false&page=1&limit=25&sort_by=created_at&sort_order=desc&language=en" \2 --header "Authorization: Bearer ${ONDI_ACCESS_TOKEN}"Response examples
1{2 "success": true,3 "message": "Wallet transactions retrieved successfully",4 "data": {5 "transactions": [6 {7 "id": "10000000-0000-4000-8000-000000000001",8 "wallet_id": "20000000-0000-4000-8000-000000000001",9 "account": {10 "user_id": "30000000-0000-4000-8000-000000000001",11 "name": "Example Driver",12 "account_type": "driver",13 "customer_type": null,14 "driver_id": "40000000-0000-4000-8000-000000000001"15 },16 "type": "earning",17 "direction": "credit",18 "amount": 50,19 "currency_code": "USD",20 "description": "Manual credit: Performance bonus - Approved for September",21 "reason": "Performance bonus",22 "reference": "BONUS-2026-09",23 "notes": "Approved for September",24 "source": "manual_credit",25 "is_manual": true,26 "recorded_by": {27 "id": "50000000-0000-4000-8000-000000000001",28 "name": "Example Administrator"29 },30 "created_at": "2026-10-17T10:00:00Z",31 "balance_snapshot": 250,32 "delivery": null33 }34 ],35 "source_options": [36 "manual_credit"37 ],38 "pagination": {39 "page": 1,40 "limit": 25,41 "total": 1,42 "total_pages": 143 },44 "type_options": [45 "earning"46 ],47 "currency_options": [48 "USD"49 ]50 }51}