Skip to main content

Users

This section contains 1 subgroups.

Get Current User

Platform & Access / Users
GET/users/me?language=en
Send a bearer token in the Authorization header for an authenticated OnDi user session.
Request
curl
1curl --request GET "$ONDI_BASE_URL/users/me?language=en" \2  --header "Authorization: Bearer {{access_token}}"

Query parameters

languageOptional
query string

en

Language code (Optional)

Headers

AuthorizationOptional
header string

Bearer {{access_token}}

Responses

Success200
Response body
json
1{2  "success": true,3  "message": "Users retrieved successfully",4  "user": {5    "id": "user-uuid",6    "email": "user@example.com",7    "first_name": "John",8    "last_name": "Doe",9    "status": "active",10    "notifications_enabled": true,11    "is_system_admin": false,12    "is_staff": true,13    "is_market_user": true,14    "market_id": "market-uuid",15    "is_restaurant_user": false,16    "restaurant_location_id": null,17    "login_country": {18      "code": "IN",19      "name": "India",20      "dial_code": "+91"21    },22    "role": {23      "id": "role-uuid",24      "name": "restaurant_staff",25      "scope": "tenant"26    },27    "panel_type": "dispatcher",28    "warehouse_staff": [],29    "restaurant_staff": {30      "id": "staff-uuid",31      "location_id": "location-uuid",32      "staff_role": "cashier",33      "location": {34        "id": "location-uuid",35        "name": {},36        "code": 1000,37        "tenant_id": "tenant-uuid",38        "active": true39      }40    }41  }42}

Update My Context

Platform & Access / Users
POST/users/me/context?language=en
Send a bearer token in the Authorization header for an authenticated OnDi user session.
Request
curl
1curl --request POST "$ONDI_BASE_URL/users/me/context?language=en" \2  --header "Authorization: Bearer {{access_token}}" \3  --header "Content-Type: application/json" \4  --header "Content-Type: application/json" \5  --data '{6  "portal": "market",7  "market_id": "{{market_id}}"8}'
Request body
json
1{2  "portal": "market",3  "market_id": "{{market_id}}"4}

Query parameters

languageOptional
query string

en

Language code (Optional)

Request body fields

portalExample
string

Example field from the request body.

market_idExample
string

Example field from the request body.

Headers

AuthorizationOptional
header string

Bearer {{access_token}}

Content-TypeOptional
header string

application/json

Responses

Success - Market200
Response body
json
1{2  "success": true,3  "message": "User Updated Successfully",4  "data": {5    "id": "user-uuid",6    "is_market_user": true,7    "market_id": "market-uuid",8    "is_restaurant_user": false,9    "restaurant_location_id": null10  }11}
Success - Restaurant200
Response body
json
1{2  "success": true,3  "message": "User Updated Successfully",4  "data": {5    "id": "user-uuid",6    "is_market_user": true,7    "market_id": "market-uuid",8    "is_restaurant_user": true,9    "restaurant_location_id": "restaurant-location-uuid"10  }11}
Error - Market Not Found404
Response body
json
1{2  "success": false,3  "message": "Market not found",4  "data": null5}

Get List Users

Platform & Access / Users
GET/users?language=en&page=1&limit=10&status=active&search=&tenant_id=&role_id=&startDate=&endDate=&role=driver,manager&is_business=&show_all=true&include_customer=true&exclude_customers=&is_market_user=&market_id=&is_restaurant_user=&restaurant_location_id=&sort_by=&sort_order=&column_filters={"role_id":"role-uuid"}

Lists users with pagination, search, sorting, advanced column filters, and tenant KPI stats. Existing top-level filters continue to work. Authentication: - Requires valid authentication token Query Parameters: - language, page, limit, status, search, tenant_id, role_id, role, is_business, startDate, endDate, show_all, include_customer, exclude_customers, is_market_user, market_id, is_restaurant_user, restaurant_location_id - role_id: exact role-ID filter - role: exact role-name filter. Supports comma-separated values such as driver,manager - sort_by: full_name, email, phone, status, role_name, user_type, created_at, last_login_at - sort_order: asc or desc (defaults to desc when sort_by is provided) - column_filters: JSON string with keys full_name, email, phone, status, role, role_id, role_name, role_scope, user_type, is_market_user, is_restaurant_user, created_at, last_login_at - column_filters.role_id: exact role-ID filter, for example {"role_id":"e103e9a4-8c78-4c95-a27a-893d278ac590"} - column_filters.role: exact role-name filter with comma-separated values such as driver,manager - When both top-level role_id and column_filters.role_id are provided, both filters must match. Frontend integration: send the selected role UUID either as top-level role_id or as column_filters.role_id. Continue using column_filters.role only for role names. No navigation behavior changes. Invalid filter types return HTTP 400. Response: includes stats (totalUsers, activeUsers, pendingUsers, recentlyJoined) plus the existing statusCounts block.

Send a bearer token in the Authorization header for an authenticated OnDi user session.
Request
curl
1curl --request GET "$ONDI_BASE_URL/users?language=en&page=1&limit=10&status=active&search=&tenant_id=&role_id=&startDate=&endDate=&role=driver,manager&is_business=&show_all=true&include_customer=true&exclude_customers=&is_market_user=&market_id=&is_restaurant_user=&restaurant_location_id=&sort_by=&sort_order=&column_filters={"role_id":"role-uuid"}" \2  --header "Authorization: Bearer {{access_token}}"

Query parameters

languageOptional
query string

en

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

pageOptional
query string

1

Page number for pagination (Optional, default: 1)

limitOptional
query string

10

Number of records per page (Optional, default: 10)

statusOptional
query string

active

Filter users by status (Optional, values: active, inactive, pending, blocked)

searchOptional
query string

Search term to filter users by email, first name, or last name (Optional)

tenant_idOptional
query string

Filter users by tenant ID (Optional)

role_idOptional
query string

Filter users by role ID (Optional)

startDateOptional
query string

Filter users created after this date (ISO format, optional)

endDateOptional
query string

Filter users created before this date (ISO format, optional)

roleOptional
query string

driver,manager

Filter users by exact role name. Supports comma-separated values for multiple roles, e.g. driver,manager (Optional)

is_businessOptional
query string

Filter by business type: 'true' for business users, 'false' for individual users (Optional)

show_allOptional
query string

true

Show all users regardless of filters (Optional, default: true)

include_customerOptional
query string

true

Include users without any assigned roles (customers) in the results (Optional, default: true). Set to 'false' to exclude users without roles.

exclude_customersOptional
query string

Alias for excluding customer rows. Set to 'true' to force include_customer=false.

is_market_userOptional
query string

Filter users by market-context flag (true or false) (Optional)

market_idOptional
query string

Filter users by market ID (Optional)

is_restaurant_userOptional
query string

Filter users by restaurant-context flag (true or false) (Optional)

restaurant_location_idOptional
query string

Filter users by restaurant location ID (Optional)

sort_byOptional
query string

Sort by one of: full_name, email, phone, status, role_name, user_type, created_at, last_login_at

sort_orderOptional
query string

Sort order: asc or desc. Defaults to desc when sort_by is provided.

column_filtersOptional
query string

{"role_id":"role-uuid"}

JSON string with column filters. Supported keys: full_name, email, phone, status, role, role_id, role_name, role_scope, user_type, is_market_user, is_restaurant_user, created_at, last_login_at

Headers

AuthorizationOptional
header string

Bearer {{access_token}}

Responses

Success Response200
Response body
json
1{2  "success": true,3  "message": "Users retrieved successfully",4  "users": [5    {6      "id": "user-uuid",7      "email": "user@example.com",8      "first_name": "John",9      "last_name": "Doe",10      "full_name": "John Doe",11      "phone": "+1234567890",12      "avatar_url": "https://example.com/avatar.jpg",13      "status": "active",14      "is_market_user": true,15      "market_id": "market-uuid",16      "is_restaurant_user": false,17      "restaurant_location_id": null,18      "user_type": "business",19      "roles": {20        "id": "role-uuid",21        "name": "admin",22        "scope": "tenant"23      },24      "tenant": {25        "id": "tenant-uuid",26        "name": "Example Tenant"27      },28      "created_at": "2023-01-01T00:00:00Z",29      "last_login_at": "2023-01-15T10:30:00Z"30    }31  ],32  "stats": {33    "totalUsers": 42,34    "activeUsers": 30,35    "pendingUsers": 8,36    "recentlyJoined": [37      {38        "id": "user-uuid",39        "full_name": "John Doe",40        "avatar_url": "https://example.com/avatar.jpg",41        "created_at": "2025-09-20T10:42:09.258391+00:00"42      }43    ]44  },45  "page": 1,46  "limit": 10,47  "total": 42,48  "statusCounts": {49    "active": 30,50    "inactive": 8,51    "pending": 4,52    "total": 4253  }54}
Error - Unauthorized401
Response body
json
1{2  "error": "Unauthorized",3  "message": "Authentication required",4  "status": 4015}
Error - Forbidden403
Response body
json
1{2  "error": "Forbidden",3  "message": "Insufficient permissions",4  "status": 4035}
Error - Server Error500
Response body
json
1{2  "success": false,3  "message": "Error retrieving users"4}

Get User by ID

Platform & Access / Users
GET/users/:id?language=en&response_type=full

Retrieves a specific user by their ID. Query params: - response_type: full (default) | basic - full: returns user with roles, permissions, teams, tenant_info, driver_details, warehouse_staff, and stats - basic: lightweight response with only profile fields (id, name, email, phone, status, avatar, user_type, last_login_at, created_at). Use for popups/cards where full detail is not needed. Success response includes: - user: user payload (varies by response_type) - stats: top-level KPI block (only in full mode) stats fields (full only): - wallet_balance - total_orders - pending_payouts - active_api_keys Permissions and error responses follow the existing endpoint behavior.

Send a bearer token in the Authorization header for an authenticated OnDi user session.
Request
curl
1curl --request GET "$ONDI_BASE_URL/users/:id?language=en&response_type=full" \2  --header "Authorization: Bearer {{access_token}}"

Path parameters

idRequired
path string

user-uuid

UUID of the user to retrieve (Required)

Query parameters

languageOptional
query string

en

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

response_typeOptional
query string

full

Response detail level: 'full' (default) returns all data including roles, permissions, teams, stats; 'basic' returns only essential profile info (id, name, email, phone, status, avatar, user_type, last_login, created_at)

Headers

AuthorizationOptional
header string

Bearer {{access_token}}

Responses

Success - Full (default)200
Response body
json
1{2  "success": true,3  "message": "User retrieved successfully",4  "user": {5    "id": "a1b2c3d4-e5f6-7890-1234-567890abcdef",6    "avatar_url": "https://example.com/avatars/a1b2c3d4.png",7    "email": "user@example.com",8    "first_name": "John",9    "last_name": "Doe",10    "full_name": "John Doe",11    "phone": "+15551234567",12    "status": "active",13    "user_type": "member",14    "role": {15      "id": "role-uuid-789",16      "name": "tenant_member",17      "scope": "tenant"18    },19    "tenant_info": {20      "id": "tenant-uuid-abc",21      "name": "Example Tenant Inc.",22      "slug": "example-tenant-inc",23      "status": "active",24      "metadata": {25        "industry": "tech"26      },27      "contact_info": {28        "address": "123 Main St"29      }30    },31    "panel_type": "customer",32    "permissions": [33      "view_deliveries",34      "create_deliveries"35    ],36    "teams": [37      {38        "id": "team-uuid",39        "name": "Team A"40      }41    ],42    "all_teams": false,43    "created_at": "2023-01-15T10:30:00Z",44    "updated_at": "2023-10-20T14:45:00Z",45    "last_login_at": "2023-11-01T09:00:00Z",46    "requires_driver_setup": false47  },48  "stats": {49    "wallet_balance": 150.5,50    "total_orders": 42,51    "pending_payouts": 2,52    "active_api_keys": 153  }54}
Success - Basic200
Response body
json
1{2  "success": true,3  "message": "User retrieved successfully",4  "user": {5    "id": "a1b2c3d4-e5f6-7890-1234-567890abcdef",6    "email": "user@example.com",7    "phone": "+15551234567",8    "full_name": "John Doe",9    "first_name": "John",10    "last_name": "Doe",11    "status": "active",12    "avatar_url": "https://example.com/avatars/a1b2c3d4.png",13    "user_type": "member",14    "last_login_at": "2023-11-01T09:00:00Z",15    "created_at": "2023-01-15T10:30:00Z"16  }17}
Error - Unauthorized401
Response body
json
1{2  "error": "Unauthorized",3  "message": "Authentication token is missing or invalid",4  "status": 4015}
Error - Forbidden403
Response body
json
1{2  "success": false,3  "message": "Unauthorized to access this resource"4}
Error - Not Found404
Response body
json
1{2  "success": false,3  "message": "User not found"4}
Error - Server Error500
Response body
json
1{2  "success": false,3  "message": "Internal server error",4  "error": {5    "message": "Details of the internal error if available..."6  }7}

Get User Accounting

Platform & Access / Users
GET/users/:userId/accounting?tenant_id=&from_date=&to_date=&language=en

Returns the accounting summary used by the user-detail Accounting tab. This endpoint is driver-linked: the user must have a driver record in the tenant. Includes: - Balance summary for selected period (creditor/debtor) - Cash collected (COD + order fee) - Earnings (cash vs online/credit) - Order costs (cash/paid-by-receiver/card/wallet) - Company earnings - Paid withdrawals - From support buckets Auth: - Self OR tenant permissions (finance/operations/tenant view).

Send a bearer token in the Authorization header for an authenticated OnDi user session.
Request
curl
1curl --request GET "$ONDI_BASE_URL/users/:userId/accounting?tenant_id=&from_date=&to_date=&language=en" \2  --header "Authorization: Bearer {{access_token}}"

Path parameters

userIdRequired
path string

{{user_id}}

User UUID (required)

Query parameters

tenant_idOptional
query string

Tenant ID (optional, defaults to auth context)

from_dateOptional
query string

From date (ISO8601, optional)

to_dateOptional
query string

To date (ISO8601, optional)

languageOptional
query string

en

Language code (optional)

Headers

AuthorizationOptional
header string

Bearer {{access_token}}

Responses

Success200
Response body
json
1{2  "success": true,3  "message": "user_accounting_retrieved_successfully",4  "data": {5    "period": {6      "from_date": null,7      "to_date": null8    },9    "currency": "IQD",10    "balance_summary": {11      "amount": 0,12      "type": "creditor",13      "description": "Account is settled."14    },15    "cash_collected": {16      "total": 0,17      "breakdown": {18        "cod": 0,19        "order_fee": 020      }21    },22    "earnings": {23      "total": 0,24      "breakdown": {25        "cash": 0,26        "online_credit": 027      }28    },29    "order_costs": {30      "total": 0,31      "breakdown": {32        "cash": 0,33        "paid_by_receiver": 0,34        "card": 0,35        "wallet": 036      }37    },38    "company_earnings": 0,39    "paid_withdrawals": 0,40    "from_support": {41      "cod_type_creditor": 0,42      "cod_type_debtor": 0,43      "support_type_creditor": 0,44      "support_type_debtor": 045    }46  }47}

Invite User

Platform & Access / Users
POST/users?language=en

Invites a new user to the system via email. User receives an invitation email to set their password. Required: email, first_name, last_name. Optional: avatar_url, role_id. If role_id is provided, the role is automatically assigned based on caller's context: - tenant_admin: assigns as tenant role - system_admin: assigns as system role User status will be 'pending' until they confirm email and set password. Error responses: On failure, data is null and details may include a step (e.g. invite_redirect_config, auth_invite_user_by_email, lookup_existing_user_by_email, tenant_membership_lookup, tenant_users_insert, unhandled_exception) plus provider-safe fields such as redirect_to, PostgREST code/message, or Auth API status/message.

Send a bearer token in the Authorization header for an authenticated OnDi user session.
Request
curl
1curl --request POST "$ONDI_BASE_URL/users?language=en" \2  --header "Authorization: Bearer {{access_token}}" \3  --header "Content-Type: application/json" \4  --header "Content-Type: application/json" \5  --data '{6  "email": "new.user@example.com",7  "first_name": "John",8  "last_name": "Doe",9  "avatar_url": "https://example.com/avatar.png",10  "role_id": "role-uuid-optional"11}'
Request body
json
1{2  "email": "new.user@example.com",3  "first_name": "John",4  "last_name": "Doe",5  "avatar_url": "https://example.com/avatar.png",6  "role_id": "role-uuid-optional"7}

Query parameters

languageOptional
query string

en

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

Request body fields

emailExample
string

Example field from the request body.

first_nameExample
string

Example field from the request body.

last_nameExample
string

Example field from the request body.

avatar_urlExample
string

Example field from the request body.

role_idExample
string

Example field from the request body.

Headers

AuthorizationOptional
header string

Bearer {{access_token}}

Content-TypeOptional
header string

application/json

Responses

Created201
Response body
json
1{2  "success": true,3  "message": "invitation_sent_successfully",4  "data": {5    "user": {6      "id": "new-user-uuid",7      "email": "new.user@example.com"8    }9  }10}
Conflict - Already Exists409
Response body
json
1{2  "success": false,3  "message": "user_already_exists",4  "data": null5}
Bad Request - Auth invite failed400
Response body
json
1{2  "success": false,3  "message": "invitation_failed",4  "data": null,5  "details": {6    "step": "auth_invite_user_by_email",7    "redirect_to": "https://admin.example.com/update-password",8    "name": "AuthApiError",9    "message": "Error message from Auth API",10    "status": 40011  }12}
Server Error - Config or lookup500
Response body
json
1{2  "success": false,3  "message": "Internal Server Error",4  "data": null,5  "details": {6    "step": "invite_redirect_config",7    "reason": "ADMIN_WEB_URL secret is missing or empty; cannot build invite redirect URL"8  }9}

Add User (auto-confirm)

Platform & Access / Users
POST/users/add?language=en

Creates a new user with auto-confirmation. At least one of email or phone is required. If provided, email and phone are auto-confirmed. Required: password. Optional: first_name, last_name, phone, email, avatar_url, is_staff, role_id. If role_id is provided, the role is automatically assigned based on caller's context: - tenant_admin: assigns as tenant role - system_admin: assigns as system role User is immediately active and can login with the provided password.

Send a bearer token in the Authorization header for an authenticated OnDi user session.
Request
curl
1curl --request POST "$ONDI_BASE_URL/users/add?language=en" \2  --header "Authorization: Bearer {{access_token}}" \3  --header "Content-Type: application/json" \4  --header "Content-Type: application/json" \5  --data '{6  "email": "new.user@example.com",7  "phone": "+1234567890",8  "password": "SecurePassword123!",9  "first_name": "New",10  "last_name": "User",11  "avatar_url": "https://example.com/avatar.png",12  "is_staff": false,13  "role_id": "role-uuid-optional"14}'
Request body
json
1{2  "email": "new.user@example.com",3  "phone": "+1234567890",4  "password": "SecurePassword123!",5  "first_name": "New",6  "last_name": "User",7  "avatar_url": "https://example.com/avatar.png",8  "is_staff": false,9  "role_id": "role-uuid-optional"10}

Query parameters

languageOptional
query string

en

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

Request body fields

emailExample
string

Example field from the request body.

phoneExample
string

Example field from the request body.

passwordExample
string

Example field from the request body.

first_nameExample
string

Example field from the request body.

last_nameExample
string

Example field from the request body.

avatar_urlExample
string

Example field from the request body.

is_staffExample
boolean

Example field from the request body.

role_idExample
string

Example field from the request body.

Headers

AuthorizationOptional
header string

Bearer {{access_token}}

Content-TypeOptional
header string

application/json

Responses

Created201
Response body
json
1{2  "success": true,3  "message": "user_created_successfully",4  "data": {5    "user": {6      "id": "new-user-uuid",7      "email": "new.user@example.com",8      "phone": "+1234567890"9    }10  }11}
Bad Request - Contact Missing400
Response body
json
1{2  "success": false,3  "message": "email_or_phone_required"4}
Conflict - Already Exists409
Response body
json
1{2  "success": false,3  "message": "user_already_exists"4}

Add Customer (auto-confirm phone)

Platform & Access / Users
POST/users/add-customer?language=en

Creates a customer user with phone and name. Phone is auto-confirmed; email is optional. Password is generated automatically.

Send a bearer token in the Authorization header for an authenticated OnDi user session.
Request
curl
1curl --request POST "$ONDI_BASE_URL/users/add-customer?language=en" \2  --header "Authorization: Bearer {{access_token}}" \3  --header "Content-Type: application/json" \4  --header "Content-Type: application/json" \5  --data '{6  "name": "Jane Customer",7  "phone": "+1234567890",8  "email": "optional@example.com"9}'
Request body
json
1{2  "name": "Jane Customer",3  "phone": "+1234567890",4  "email": "optional@example.com"5}

Query parameters

languageOptional
query string

en

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

Request body fields

nameExample
string

Example field from the request body.

phoneExample
string

Example field from the request body.

emailExample
string

Example field from the request body.

Headers

AuthorizationOptional
header string

Bearer {{access_token}}

Content-TypeOptional
header string

application/json

Responses

Created201
Response body
json
1{2  "success": true,3  "message": "user_created_successfully",4  "data": {5    "user": {6      "id": "customer-uuid",7      "phone": "+1234567890",8      "email": "optional@example.com"9    }10  }11}
Conflict - Already Exists409
Response body
json
1{2  "success": false,3  "message": "user_already_exists"4}

Resend User Invitation

Platform & Access / Users
POST/users/resend-invitation?language=en

Resends an invitation email to a user who was previously invited but may not have received or acted on the original invitation. Authentication: - Requires valid authentication token - Must have appropriate permissions to invite users Endpoint: POST /users/resend-invitation Required Fields: - email: Valid email address of the user to resend invitation to

Send a bearer token in the Authorization header for an authenticated OnDi user session.
Request
curl
1curl --request POST "$ONDI_BASE_URL/users/resend-invitation?language=en" \2  --header "Authorization: Bearer {{access_token}}" \3  --header "Content-Type: application/json" \4  --header "Content-Type: application/json" \5  --data '{6  "email": "user@example.com"7}'
Request body
json
1{2  "email": "user@example.com"3}

Query parameters

languageOptional
query string

en

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

Request body fields

emailExample
string

Example field from the request body.

Headers

AuthorizationOptional
header string

Bearer {{access_token}}

Content-TypeOptional
header string

application/json

Responses

Success Response200
Response body
json
1{2  "success": true,3  "message": "Invitation resent successfully",4  "data": {5    "user": {6      "id": "user-uuid",7      "email": "user@example.com",8      "invited_at": "2023-01-01T00:00:00Z"9    }10  }11}
Error - Bad Request400
Response body
json
1{2  "success": false,3  "message": "Invitation failed"4}
Error - Not Found404
Response body
json
1{2  "success": false,3  "message": "User not found"4}
Error - Already Confirmed409
Response body
json
1{2  "success": false,3  "message": "User already confirmed"4}
Error - Server Error500
Response body
json
1{2  "success": false,3  "message": "Internal server error"4}

List Customers

Platform & Access / Users
GET/users/customers?language=en&page=1&limit=10&tenant_id={{tenant_id}}&is_business=&is_market_user=&market_id=&is_restaurant_user=&restaurant_location_id=&search=&sort_by=&sort_order=&column_filters=

Lists customers (users without assigned roles) with pagination, search, sorting, column filters, and KPI stats. Legacy top-level is_business still works. Authentication: - Requires valid authentication token - Requires tenant context Query Parameters: - language, page, limit, tenant_id, is_business, is_market_user, market_id, is_restaurant_user, restaurant_location_id, search - sort_by: name, email, created_at, last_login_at - sort_order: asc or desc - column_filters: JSON string with keys full_name, email, phone, status, user_type, is_market_user, is_restaurant_user, created_at, last_login_at

Send a bearer token in the Authorization header for an authenticated OnDi user session.
Request
curl
1curl --request GET "$ONDI_BASE_URL/users/customers?language=en&page=1&limit=10&tenant_id={{tenant_id}}&is_business=&is_market_user=&market_id=&is_restaurant_user=&restaurant_location_id=&search=&sort_by=&sort_order=&column_filters=" \2  --header "Authorization: Bearer {{access_token}}"

Query parameters

languageOptional
query string

en

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

pageOptional
query string

1

Page number for pagination (Optional, default: 1)

limitOptional
query string

10

Number of records per page (Optional, default: 10)

tenant_idOptional
query string

{{tenant_id}}

Tenant ID to filter customers (Optional, uses context if not provided)

is_businessOptional
query string

Filter by customer type: true for business, false for individual (Optional)

is_market_userOptional
query string

Filter customers by market-context flag (true or false) (Optional)

market_idOptional
query string

Filter customers by market ID (Optional)

is_restaurant_userOptional
query string

Filter customers by restaurant-context flag (true or false) (Optional)

restaurant_location_idOptional
query string

Filter customers by restaurant location ID (Optional)

searchOptional
query string

Toolbar search across first_name, last_name, full_name, email, and phone

sort_byOptional
query string

Sort by one of: name, email, created_at, last_login_at

sort_orderOptional
query string

Sort order: asc or desc. Defaults to desc when sort_by is provided.

column_filtersOptional
query string

JSON string with keys: full_name, email, phone, status, user_type, is_market_user, is_restaurant_user, created_at, last_login_at

Headers

AuthorizationOptional
header string

Bearer {{access_token}}

Responses

Success Response200
Response body
json
1{2  "success": true,3  "message": "Users retrieved successfully",4  "users": [5    {6      "id": "user-uuid",7      "email": "customer@example.com",8      "first_name": "Jane",9      "last_name": "Doe",10      "full_name": "Jane Doe",11      "user_type": "individual",12      "is_market_user": false,13      "market_id": null,14      "is_restaurant_user": false,15      "restaurant_location_id": null,16      "roles": {17        "id": null,18        "name": "customer",19        "scope": "tenant"20      },21      "tenant": {22        "id": "tenant-uuid",23        "name": "Example Tenant"24      }25    }26  ],27  "stats": {28    "totalUsers": 25,29    "activeUsers": 20,30    "pendingUsers": 3,31    "recentlyJoined": [32      {33        "id": "user-uuid",34        "first_name": "Jane",35        "last_name": "Doe",36        "email": "customer@example.com",37        "avatar_url": null,38        "created_at": "2025-09-20T10:42:09.258391+00:00"39      }40    ]41  },42  "page": 1,43  "limit": 10,44  "total": 2545}

Update User

Platform & Access / Users
PUT/users/:id?language=en

Updates a user's information. Users can update their own information, while system administrators can update any user. Authentication: - Requires valid authentication token - Users can update their own profile (including status) - System administrators / tenant administrators can update any user profile (email change is self-only) Path Parameters: - id: UUID of the user to update (Required) Query Parameters: - language (optional): Language code for localized response messages (e.g., 'en') Updatable Fields: - email: Change login email (self-only). Triggers a confirmation email and redirects to sign-in after confirmation. - first_name: User's first name - last_name: User's last name - status: User account status (self or admin) - phone: User's phone number - avatar_url: URL to user's profile image - profile_data: Object containing additional profile information - customer_delivery_preferences: Object containing delivery preferences Notes: - Only provided fields will be updated. Fields not included in the request will remain unchanged. - Email change sends a confirmation email via Supabase Auth and is allowed only when updating your own user. - When email is updated, the API returns immediately with requires_email_confirmation: true and new_email. The frontend should display the message instructing the user to check their new email inbox to confirm.

Send a bearer token in the Authorization header for an authenticated OnDi user session.
Request
curl
1curl --request PUT "$ONDI_BASE_URL/users/:id?language=en" \2  --header "Authorization: Bearer {{access_token}}" \3  --header "Content-Type: application/json" \4  --header "Content-Type: application/json" \5  --data '{6  "email": "new.email@example.com",7  "first_name": "Updated",8  "last_name": "Name",9  "status": "inactive",10  "phone": "+9876543210",11  "avatar_url": "https://example.com/avatar.jpg",12  "profile_data": {13    "bio": "Updated user bio",14    "preferences": {15      "theme": "dark",16      "notifications": true17    }18  },19  "customer_delivery_preferences": {20    "preferred_time": "evening",21    "special_instructions": "Leave at the door"22  }23}'
Request body
json
1{2  "email": "new.email@example.com",3  "first_name": "Updated",4  "last_name": "Name",5  "status": "inactive",6  "phone": "+9876543210",7  "avatar_url": "https://example.com/avatar.jpg",8  "profile_data": {9    "bio": "Updated user bio",10    "preferences": {11      "theme": "dark",12      "notifications": true13    }14  },15  "customer_delivery_preferences": {16    "preferred_time": "evening",17    "special_instructions": "Leave at the door"18  }19}

Path parameters

idRequired
path string

user-uuid

UUID of the user to update (Required)

Query parameters

languageOptional
query string

en

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

Request body fields

emailExample
string

Example field from the request body.

first_nameExample
string

Example field from the request body.

last_nameExample
string

Example field from the request body.

statusExample
string

Example field from the request body.

phoneExample
string

Example field from the request body.

avatar_urlExample
string

Example field from the request body.

profile_dataExample
object

Example field from the request body.

profile_data.bioExample
string

Example field from the request body.

profile_data.preferencesExample
object

Example field from the request body.

profile_data.preferences.themeExample
string

Example field from the request body.

profile_data.preferences.notificationsExample
boolean

Example field from the request body.

customer_delivery_preferencesExample
object

Example field from the request body.

customer_delivery_preferences.preferred_timeExample
string

Example field from the request body.

customer_delivery_preferences.special_instructionsExample
string

Example field from the request body.

Headers

AuthorizationOptional
header string

Bearer {{access_token}}

Content-TypeOptional
header string

application/json

Responses

Success Response - Regular Update200
Response body
json
1{2  "success": true,3  "message": "User updated successfully",4  "user": {5    "id": "user-uuid",6    "email": "user@example.com",7    "first_name": "Updated",8    "last_name": "Name",9    "status": "inactive",10    "phone": "+9876543210",11    "avatar_url": "https://example.com/avatar.jpg",12    "profile_data": {13      "bio": "Updated user bio",14      "preferences": {15        "theme": "dark",16        "notifications": true17      }18    },19    "customer_delivery_preferences": {20      "preferred_time": "evening",21      "special_instructions": "Leave at the door"22    },23    "created_at": "2023-01-01T00:00:00Z",24    "updated_at": "2023-01-01T00:00:00Z"25  }26}
Success Response - Email Change (requires confirmation)200
Response body
json
1{2  "success": true,3  "message": "Please check your inbox at new.email@example.com to confirm the email change",4  "requires_email_confirmation": true,5  "new_email": "new.email@example.com"6}
Error - Unauthorized401
Response body
json
1{2  "success": false,3  "message": "Unauthorized"4}
Error - Bad Request400
Response body
json
1{2  "success": false,3  "message": "Failed to update user"4}
Success (200 OK) - Regular update200
Response body
json
1{2  "success": true,3  "message": "User updated successfully",4  "user": { ... }5}

Update My Password

Platform & Access / Users
PUT/users/me/password?language=en

Updates the current authenticated user's password. Authentication: - Requires valid authenticated user bearer token - API key authentication is not allowed Query Parameters: - language (optional): Language code for localized response messages (e.g., 'en') Required Fields: - new_password: New password (min: 8, max: 128 characters) Optional Fields: - current_password: Required when the user already has a password. Omit it only when setting a password for the first time after OTP or magic link sign-in. Notes: - The authenticated user is always the target user - Users with an existing password must provide the correct current password - Users without an existing password can set one by providing only new_password

Send a bearer token in the Authorization header for an authenticated OnDi user session.
Request
curl
1curl --request PUT "$ONDI_BASE_URL/users/me/password?language=en" \2  --header "Authorization: Bearer {{access_token}}" \3  --header "Content-Type: application/json" \4  --header "Content-Type: application/json" \5  --data '{6  "current_password": "CurrentSecurePassword123!",7  "new_password": "NewSecurePassword123!"8}'
Request body
json
1{2  "current_password": "CurrentSecurePassword123!",3  "new_password": "NewSecurePassword123!"4}

Query parameters

languageOptional
query string

en

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

Request body fields

current_passwordExample
string

Example field from the request body.

new_passwordExample
string

Example field from the request body.

Headers

AuthorizationOptional
header string

Bearer {{access_token}}

Content-TypeOptional
header string

application/json

Responses

Success Response200
Response body
json
1{2  "success": true,3  "message": "Password updated successfully",4  "data": {5    "user_id": "user-uuid"6  }7}
Error - Bad Request400
Response body
json
1{2  "success": false,3  "message": "Current password is required"4}
Error - Unauthorized403
Response body
json
1{2  "success": false,3  "message": "Unauthorized"4}
Error - Not Found404
Response body
json
1{2  "success": false,3  "message": "User not found"4}
Error - Server Error500
Response body
json
1{2  "success": false,3  "message": "Internal server error"4}

Update My Notification Settings

Platform & Access / Users
PUT/users/me/notifications?language=en

Enable or disable in-app/push/email/SMS notifications for the current user. When notifications_enabled is false, new rows in notifications are stored with status skipped_disabled_notification and are not delivered; they do not appear in GET /messaging/notifications (which only returns status: sent). Authentication: Bearer token only (API key not supported). Request body: - notifications_enabled (boolean, required) Response (200): { success, message, data: { user_id, notifications_enabled } }

Send a bearer token in the Authorization header for an authenticated OnDi user session.
Request
curl
1curl --request PUT "$ONDI_BASE_URL/users/me/notifications?language=en" \2  --header "Authorization: Bearer {{access_token}}" \3  --header "Content-Type: application/json" \4  --header "Content-Type: application/json" \5  --data '{6  "notifications_enabled": true7}'
Request body
json
1{2  "notifications_enabled": true3}

Query parameters

languageOptional
query string

en

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

Request body fields

notifications_enabledExample
boolean

Example field from the request body.

Headers

AuthorizationOptional
header string

Bearer {{access_token}}

Content-TypeOptional
header string

application/json

Responses

Success Response200
Response body
json
1{2  "success": true,3  "message": "Notification settings updated successfully",4  "data": {5    "user_id": "user-uuid",6    "notifications_enabled": true7  }8}
Error - Bad Request400
Response body
json
1{2  "success": false,3  "message": "field_required"4}
Error - Unauthorized401
Response body
json
1{2  "success": false,3  "message": "Unauthorized"4}

Reset User Password by ID

Platform & Access / Users
PUT/users/:id/reset-password?language=en

Resets a user's password by user ID. Authentication: - Requires valid authentication token - Only system admins and tenant admins can use this endpoint Path Parameters: - id: UUID of the user whose password to reset (Required) Query Parameters: - language (optional): Language code for localized response messages (e.g., 'en') Required Fields: - password: New password (min: 8, max: 128 characters) Notes: - Use this endpoint for admin-managed password reset only - Password must be between 8 and 128 characters - User is identified by the ID in the URL path

Send a bearer token in the Authorization header for an authenticated OnDi user session.
Request
curl
1curl --request PUT "$ONDI_BASE_URL/users/:id/reset-password?language=en" \2  --header "Authorization: Bearer {{access_token}}" \3  --header "Content-Type: application/json" \4  --header "Content-Type: application/json" \5  --data '{6  "password": "NewSecurePassword123!"7}'
Request body
json
1{2  "password": "NewSecurePassword123!"3}

Path parameters

idRequired
path string

user-uuid

UUID of the user whose password to reset (Required)

Query parameters

languageOptional
query string

en

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

Request body fields

passwordExample
string

Example field from the request body.

Headers

AuthorizationOptional
header string

Bearer {{access_token}}

Content-TypeOptional
header string

application/json

Responses

Success Response200
Response body
json
1{2  "success": true,3  "message": "User updated successfully",4  "data": {5    "user_id": "user-uuid",6    "email": "user@example.com",7    "phone": "+1234567890"8  }9}
Error - Bad Request400
Response body
json
1{2  "success": false,3  "message": "Validation error"4}
Error - Unauthorized403
Response body
json
1{2  "success": false,3  "message": "Unauthorized"4}
Error - Not Found404
Response body
json
1{2  "success": false,3  "message": "User not found"4}
Error - Server Error500
Response body
json
1{2  "success": false,3  "message": "Internal server error"4}

Delete User

Platform & Access / Users
DELETE/users/:id?language=en

Delete a user. This operation may be permanent or may mark the user as deleted depending on implementation.

Send a bearer token in the Authorization header for an authenticated OnDi user session.
Request
curl
1curl --request DELETE "$ONDI_BASE_URL/users/:id?language=en" \2  --header "Authorization: Bearer {{access_token}}"

Path parameters

idRequired
path string

user-uuid

UUID of the user to delete (Required)

Query parameters

languageOptional
query string

en

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

Headers

AuthorizationOptional
header string

Bearer {{access_token}}

Responses

Success Response204
Error - Not Found404
Response body
json
1{2  "error": "Not Found",3  "message": "User not found",4  "status": 4045}
Error - Forbidden403
Response body
json
1{2  "error": "Forbidden",3  "message": "Cannot delete own account",4  "status": 4035}

Assign User Role

Platform & Access / Users
POST/users/:userId/roles?language=en

Assigns a role to a user. A user can only have one role assignment at a time. The role can be either a system-level role or a tenant-specific role. Business Rules: 1. A user can only have one role assignment at a time 2. System roles cannot be associated with a tenant 3. Tenant roles must specify a tenant ID 4. If a user already has a role assigned, the request will update it 5. A user cannot change their own role 6. Cannot change the role of the last tenant_admin for a tenant 7. Cannot change the role of the last system_admin

Send a bearer token in the Authorization header for an authenticated OnDi user session.
Request
curl
1curl --request POST "$ONDI_BASE_URL/users/:userId/roles?language=en" \2  --header "Authorization: Bearer {{access_token}}" \3  --header "Content-Type: application/json" \4  --header "Content-Type: application/json" \5  --data '{6  "role_id": "role-uuid",7  "role_type": "tenant",8  "tenant_id": "tenant-uuid"9}'
Request body
json
1{2  "role_id": "role-uuid",3  "role_type": "tenant",4  "tenant_id": "tenant-uuid"5}

Path parameters

userIdRequired
path string

The unique identifier of the user to assign the role to

Query parameters

languageOptional
query string

en

Language code for response messages (default: en)

Request body fields

role_idExample
string

Example field from the request body.

role_typeExample
string

Example field from the request body.

tenant_idExample
string

Example field from the request body.

Headers

AuthorizationOptional
header string

Bearer {{access_token}}

Content-TypeOptional
header string

application/json

Responses

Success Response201Created
Response body
json
1{2  "success": true,3  "message": "Role assigned successfully"4}
Error - User Already Has Role400Bad Request
Response body
json
1{2  "success": false,3  "message": "User already has role"4}
Error - Invalid Role Type400Bad Request
Response body
json
1{2  "success": false,3  "message": "System role cannot be assigned to tenant"4}
Error - Cannot Change Own Role403Forbidden
Response body
json
1{2  "success": false,3  "message": "You cannot change your own role"4}
Error - Last Admin Quorum Violation409Conflict
Response body
json
1{2  "success": false,3  "message": "Cannot remove the last admin of this tenant. Assign another admin first."4}

Get User Role

Platform & Access / Users
GET/users/:userId/roles?language=en

Retrieves roles assigned to a user. This endpoint returns all roles associated with the specified user, including role name, scope, role type, and tenant ID.

Send a bearer token in the Authorization header for an authenticated OnDi user session.
Request
curl
1curl --request GET "$ONDI_BASE_URL/users/:userId/roles?language=en" \2  --header "Authorization: Bearer {{access_token}}"

Path parameters

userIdRequired
path string

ID of the user to get roles for

Query parameters

languageOptional
query string

en

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

Headers

AuthorizationOptional
header string

Bearer {{access_token}}

Responses

Success Response200OK
Response body
json
1{2  "success": true,3  "message": "Role retrieved successfully",4  "roles": [5    {6      "id": "role-123",7      "name": "Admin",8      "scope": "global",9      "role_type": "admin",10      "tenant_id": "tenant-456"11    },12    {13      "id": "role-789",14      "name": "Editor",15      "scope": "tenant",16      "role_type": "user",17      "tenant_id": "tenant-456"18    }19  ]20}
Error Response400Bad Request
Response body
json
1{2  "success": false,3  "message": "Failed to get role"4}

Remove User Role

Platform & Access / Users
DELETE/users/:userId/roles/:roleId?language=en

Removes a specific role assignment from a user. This endpoint deletes the association between a user and a role in the system. Business Rules: 1. Only tenant_admin or system_admin can remove roles 2. A user cannot remove their own role 3. tenant_admin can only remove roles within their own tenant 4. Cannot remove the last tenant_admin of a tenant 5. Cannot remove the last system_admin

Send a bearer token in the Authorization header for an authenticated OnDi user session.
Request
curl
1curl --request DELETE "$ONDI_BASE_URL/users/:userId/roles/:roleId?language=en" \2  --header "Authorization: Bearer {{access_token}}"

Path parameters

userIdRequired
path string

ID of the user to remove the role from

roleIdRequired
path string

ID of the role to be removed from the user

Query parameters

languageOptional
query string

en

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

Headers

AuthorizationOptional
header string

Bearer {{access_token}}

Responses

Success Response200OK
Response body
json
1{2  "success": true,3  "message": "Role removed successfully"4}
Error Response400Bad Request
Response body
json
1{2  "success": false,3  "message": "Failed to remove role"4}
Error - Cannot Remove Own Role403Forbidden
Response body
json
1{2  "success": false,3  "message": "You cannot change your own role"4}
Error - Last Admin Quorum Violation409Conflict
Response body
json
1{2  "success": false,3  "message": "Cannot remove the last admin of this tenant. Assign another admin first."4}

Get User Addresses

Platform & Access / Users
GET/users/:userId/addresses?language=en&page=1&limit=10

Lists addresses belonging to a specific user with pagination. Users can only access their own addresses, while system administrators can access any user's addresses. Authentication: - Requires valid authentication token - Users can only access their own addresses - System administrators can access any user's addresses Path Parameters: - userId: UUID of the user whose addresses to retrieve (Required) Query Parameters: - language (optional): Language code for localized response messages (e.g., 'en') - page (optional): Page number for pagination (default: 1) - limit (optional): Number of records per page (default: 10)

Send a bearer token in the Authorization header for an authenticated OnDi user session.
Request
curl
1curl --request GET "$ONDI_BASE_URL/users/:userId/addresses?language=en&page=1&limit=10" \2  --header "Authorization: Bearer {{access_token}}"

Path parameters

userIdRequired
path string

user-uuid

UUID of the user whose addresses to retrieve (Required)

Query parameters

languageOptional
query string

en

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

pageOptional
query string

1

Page number for pagination (Optional, default: 1)

limitOptional
query string

10

Number of records per page (Optional, default: 10)

Headers

AuthorizationOptional
header string

Bearer {{access_token}}

Responses

Success Response200
Response body
json
1{2  "success": true,3  "message": "Addresses retrieved successfully",4  "addresses": [5    {6      "id": "address-uuid",7      "user_id": "user-uuid",8      "title": "Home",9      "address_line1": "123 Main St",10      "address_line2": "Apt 4B",11      "city": "New York",12      "state": "NY",13      "postal_code": "10001",14      "country": "US",15      "is_primary": true,16      "is_active": true,17      "latitude": 40.7128,18      "longitude": -74.006,19      "created_at": "2023-01-01T00:00:00Z",20      "updated_at": "2023-01-01T00:00:00Z"21    }22  ],23  "total": 5,24  "page": 1,25  "limit": 1026}
Error - Unauthorized403
Response body
json
1{2  "success": false,3  "message": "Unauthorized"4}
Error - Bad Request400
Response body
json
1{2  "success": false,3  "message": "Error retrieving addresses"4}