Skip to main content

Admin

2 API calls in this section.

Admin endpoints for querying wallets for other users within the same tenant.

Get User Wallet​

Billing & Subscriptions / Wallets / Admin
GET/wallets/user-wallet

Get 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

ParameterTypeDescription
user_idRequiredstring

Target user UUID (required)

Example: {{user_id}}

pagestring

Page number for pagination (default: 1)

Example: 1

limitstring

Number of items per page (default: 20, max: 100)

Example: 20

typestring

Filter by transaction type: topup, transfer, payment, earning

from_datestring

Filter from date (ISO format: 2024-01-01T00:00:00Z)

to_datestring

Filter to date (ISO format: 2024-12-31T23:59:59Z)

searchstring

Search in description/reference fields and by exact amount when numeric

languageOptionalstring

Language code for response localization (Optional, default: en) .

Example: en

Headers

ParameterTypeDescription
Authorizationstring

Example: Bearer {{access_token}}

Staging
Request
curl
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

403Forbidden
Response body
json
1{2  "success": false,3  "message": "Unauthorized"4}

List Tenant Wallet Transactions​

Billing & Subscriptions / Wallets / Admin
GET/wallets/tenant-transactions

Read-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

KeyValueMeaning
account_namestringLiteral case-insensitive name substring
account_typedriver, customer, company, staffWallet account category
customer_typeindividual, business, institutionCustomer subtype; implies account_type=customer
directioncredit, debitWallet movement direction
typestringExact 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
descriptionstringLiteral substring in reason or description
reasonstringLiteral reason substring
actor_namestringLiteral 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
sourcestringExact stored source selected from data.source_options
referencestringLiteral saved-reference substring
notesstringLiteral notes substring
currency_codethree-letter stringExact saved currency code; input is normalized to uppercase
delivery_codestringLiteral linked-delivery code substring
external_reference_idstringLiteral 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.transactions contains the requested page; pagination.total and total_pages describe the same complete filtered population.

  • account contains user_id, name, account_type, customer_type, and driver_id. Company/staff accounts are included in Transactions when present; customer subtype comes from the current tenant membership and is null for non-customers.

  • type is the raw persisted ledger type. amount is the signed saved amount. direction is credit or debit; zero amounts and currency_adjustment, frozen, and unfrozen rows have null direction. The amount-range filter uses the absolute magnitude.

  • currency_code is the saved transaction currency, or null when unavailable. It is not reconstructed from the tenant's current currency setting.

  • description is the stored description. reason, reference, and notes are separate saved metadata values, null when absent. Manual reference is distinct from delivery.external_reference_id.

  • is_manual is true only for saved sources manual_credit, manual_debit, and customer_manual_adjustment, including manual rows with a linked delivery. manual_only=true fixes that scope regardless of other filters.

  • recorded_by is {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. Saved processed_by_user_id is used when actor_user_id is absent (for example, payouts). Missing actors are not inferred from the wallet owner or labelled as System.

  • source_options, type_options, and currency_options contain 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.

  • delivery is null or {id, delivery_code, barcode, external_reference_id}. balance_snapshot is 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 localized message summarizes the first issue; details contains {field, message} for each issue. For example, column_filters.customer_type conflicts 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 return 403.

  • 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: GET is returned.

  • 500 internal_server_error: the ledger query failed; no partial list is returned. Frontend clients should show the localized message and use the stable code and details[].field values 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

ParameterTypeDescription
tenant_idstring

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: {{tenant_id}}

manual_onlystring

false: all wallet entries; true: saved manual driver/customer adjustments only. false by default for Transactions; true for Adjustments.

Example: false

pagestring

Positive page number. Default 1. positive integer, default 1.

Example: 1

limitstring

Rows per page. Default 25, maximum 100. positive integer, default 25, maximum 100.

Example: 25

sort_bystring

created_at, amount, or account_name. created_at (default), amount (absolute magnitude), or account_name (case-insensitive). Ties use created_at DESC, then id DESC.

Example: created_at

sort_orderstring

asc or desc. desc (default) or asc.

Example: desc

searchOptionalstring

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_filtersOptionalstring

JSON column filters; see the documented schema. Apply before pagination. optional JSON object; URL-encode it once through URLSearchParams or the equivalent client query builder. Every populated filter is combined with AND and applied before pagination.

Example: {"account_type":"customer","customer_type":"business","direction":"credit","amount":{"min":10,"max":100}}

languagestring

Response language: en, ar, fa, ku. response localization language (en, ar, fa, ku).

Example: en

Headers

ParameterTypeDescription
Authorizationstring

Example: Bearer {{access_token}}

More examples
Example column_filters
json
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}
Staging
Request
curl
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

200OK
Response body
json
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}