Search across invoices, customers, tasks, conversations, documents, and knowledge documents within your organization.
Supports two modes:
search (default) — text search with ILIKE matching, requires a query of at least 2 characters.
suggest — returns recent entities without a text query, ordered by each type’s natural recency column.
Query parameters
Operating mode. One of: search, suggest.
search — requires q (minimum 2 characters), applies text matching
suggest — ignores q, returns recent entities by recency
Search text (minimum 2 characters). Required when mode=search, ignored when mode=suggest. Matches against:
- Invoices: invoice number, customer name, total amount
- Customers: name, address
- Tasks: title, description, status
- Conversations: subject, channel, status
- Documents: filename, document name
- Knowledge: filename
Comma-separated entity types to search. When omitted, all types are searched. Valid values: invoice, customer, task, conversation, document, knowledge.types=invoice,customer,task
Maximum results to return. Range: 1–50. Results are distributed across the requested types using round-robin ordering.
UUID of the organization to search within. Optional — when omitted, the organization is resolved automatically using the fallback chain described below.
Result distribution
Results are distributed across entity types using round-robin ordering. Each type gets an equal share of the limit (rounded up), and results alternate between types so no single type dominates the response.
Suggest mode recency ordering
When mode=suggest, entities are ordered by their natural recency column:
| Type | Ordered by |
|---|
invoice | Issue date (newest first) |
customer | Last updated (most recent first) |
task | Created date (newest first) |
conversation | Created date (newest first) |
document | Last modified (newest first) |
knowledge | Timestamp (newest first) |
Response
Returns 200 with a data array of matching entities. Each item has the same shape regardless of mode.
Example: search mode
GET /api/search?q=acme&types=invoice,customer&limit=5
{
"status": "success",
"status_code": 200,
"data": {
"data": [
{
"entity_uid": "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90",
"entity_type": "invoice",
"label": "INV-2026-0042",
"subtitle": "Acme Corp - $1,500.00"
},
{
"entity_uid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"entity_type": "customer",
"label": "Acme Corp",
"subtitle": "123 Main St, New York, NY"
}
]
}
}
Example: suggest mode
GET /api/search?mode=suggest&types=customer&limit=5
{
"status": "success",
"status_code": 200,
"data": {
"data": [
{
"entity_uid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"entity_type": "customer",
"label": "Acme Corp",
"subtitle": "123 Main St, New York, NY"
},
{
"entity_uid": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"entity_type": "customer",
"label": "Globex Corporation",
"subtitle": null
}
]
}
}
Response fields
| Field | Type | Description |
|---|
entity_uid | string | Entity UUID |
entity_type | string | One of invoice, customer, task, conversation, document, knowledge |
label | string | Display name (invoice number, party name, task title, etc.) |
subtitle | string | null | Secondary info (customer + amount for invoices, address for customers, status + due date for tasks, channel + status for conversations, filename for documents, content type for knowledge) |
Organization scoping
Results are scoped to a single organization. The organization is resolved using this fallback chain:
- Explicit parameter —
?organization_uid=<uuid> (validated against the user’s memberships)
- Default organization — the authenticated user’s
default_organization
- First organization — the first organization the user belongs to (sorted alphabetically by UID)
If none of the above resolve, a 400 error is returned.
Errors
| Status | Reason |
|---|
400 | Invalid organization_uid, user has no organizations, or invalid types / mode parameter |
403 | User is not a member of the requested organization |