Search API
The list endpoints answer "show me recent X". Search answers investigative questions: everything that ever touched one order, every refusal by one rule, every action a given operator proposed against one asset last week. One endpoint queries across events, plans, actions, and receipts with a compact filter grammar and returns typed hits. Search is part of the v1.0 surface.
Shared conventions, including authentication, pagination, and the error envelope, are defined in the API overview. Error codes are catalogued in Errors.
Results reflect the search index, which trails writes by a few seconds. For compliance-grade reads of the audit trail, use the Receipts API directly; for a complete extract, use the receipts export. Search is for finding things, not for proving them.
Run a search
search:readExecutes one query. Results are ordered newest first by the hit's own timestamp and cursor-paginated with the standard limit and cursor parameters. A hit is only returned if the calling key could read the underlying object directly, so search never widens what a key can see; workspace-pinned keys search their workspace only.
The query string, in the filter grammar below. Maximum 512 characters.
Comma-separated object types to search: event, plan, action, receipt. Defaults to all four.
Page size, 1–100. Defaults to 20.
Pagination cursor from a previous response's next_cursor.
The filter grammar
A query is a sequence of terms separated by spaces. All terms must match (implicit AND). Three kinds of terms exist:
| Term | Form | Example |
|---|---|---|
| Field filter | field:value | entity:order:SO-10884 |
| Range filter | field>=value, field<value | at>=2026-07-01, value>250 |
| Free text | bare word or "quoted phrase" | "promised ship date" |
Free text matches over reasoning strings, payload values, and error messages. Values containing spaces or colons beyond the first are quoted: entity:"room:12 west". Prefix a term with - to negate it: -disposition:DEDUP. OR is not supported in v1.0; run two queries.
Filterable fields, by the object types they apply to:
| Field | Applies to | Matches |
|---|---|---|
entity | plan, action, receipt, event | The entity_key of an action; events match through the plans they triggered. |
type | event | The envelope event_type, exact or glob: type:order.*. |
source | event | The envelope source. |
operator | plan, action, receipt | Operator name or op_ id. |
connector | action, receipt | Connector instance id or listing slug. |
tool | action, receipt | The tool called, for example tool:order.hold. |
disposition | action | ALLOW, ALERT, BLOCK, or DEDUP. |
verdict | receipt | The trust decision recorded on the receipt. |
outcome | receipt | applied, blocked, deduped, failed, undone. |
status | plan | proposed, executed, vetoed, expired. |
correlation | all | The correlation_id threading a loop together. |
request | receipt | The request_id that produced the receipt. |
value | action | The numeric value; range operators apply. |
at | all | The object's own timestamp; range operators apply, RFC 3339 or YYYY-MM-DD. |
The search response
Hits arrive in the standard list envelope. Each hit wraps the matched object with its type and timestamp so mixed-type results sort and render without inspection.
curl -G https://api.fibric.io/v1/search \
-H "Authorization: Bearer $FIBRIC_KEY" \
--data-urlencode 'q=entity:order:SO-10884 at>=2026-07-01' \
--data-urlencode 'limit=50'
{
"object": "list",
"data": [
{
"object": "search_hit",
"type": "receipt",
"at": "2026-07-02T15:04:41Z",
"hit": {
"id": "rc_5b21",
"object": "receipt",
"tool": "order.hold",
"entity_key": "order:SO-10884",
"outcome": "applied"
}
},
{
"object": "search_hit",
"type": "plan",
"at": "2026-07-02T15:02:09Z",
"hit": {
"id": "pl_7c1a",
"object": "execution_plan",
"operator_id": "op_8f2a1c",
"status": "executed"
}
},
{
"object": "search_hit",
"type": "event",
"at": "2026-07-02T14:58:01Z",
"hit": {
"id": "ev_3a91c7",
"object": "event",
"source": "magento",
"event_type": "order.updated"
}
}
],
"has_more": false,
"next_cursor": null
}
Hits carry summary objects; retrieve the id on its own reference endpoint for the full record. The mixed-type, newest-first result reads as a timeline: the example above is the envelope-to-receipt chain for one order, reconstructed in one call.
Worked examples
| Question | Query |
|---|---|
| Every refusal this week, anywhere | types=receipt · q=outcome:blocked at>=2026-06-29 |
| What did the order-risk operator do to this order? | q=operator:order-risk entity:order:SO-10884 |
| High-value actions awaiting or given approval | types=action · q=disposition:ALERT value>=250 |
| Everything in one reasoning loop | q=correlation:co_51d2e8 |
| The receipt a failing request wrote | types=receipt · q=request:req_9b3e21f0 |
| Dedup hits proving a retry storm was absorbed | types=action · q=disposition:DEDUP entity:order:SO-10884 |
| HVAC fault events that never produced a plan | types=event · q=type:hvac.zone.* "no matching operator" |
curl -G https://api.fibric.io/v1/search \
-H "Authorization: Bearer $FIBRIC_KEY" \
--data-urlencode 'q=verdict:BLOCK tool:order.refund at>=2026-06-01' \
--data-urlencode 'types=receipt'
Limits and behavior
- Queries are bounded to 512 characters and at most 12 terms; longer queries fail with
400 invalid_parameter. - Search draws from the read budget of its own route class; see Rate limits & quotas.
- The index covers the same retention window as the underlying objects. Events and receipts are retained for the life of the tenant during early access.
- Free-text matching is case-insensitive on whole words; there is no fuzzy matching in v1.0.
- The grammar is additive within the major version: new filterable fields may appear, existing fields keep their meaning.
Errors
| Status | Code | When |
|---|---|---|
400 | missing_parameter | q is absent or empty. |
400 | invalid_parameter | The query exceeds its bounds, names an unknown field, uses a range operator on a non-range field, or types names an unknown type. |
400 | invalid_cursor | The cursor is malformed, expired, or was issued for a different query. |
429 | rate_limited | The search budget is exhausted. Honor Retry-After. |
Malformed-query errors name the offending term in message. As everywhere, branch on code; see Errors.