The FSQL API
Introduction
The FSQL REST API lets you execute FSQL queries programmatically and receive results as JSON or as a Server-Sent Events (SSE) stream. This is the interface you'll use when integrating FSQL into SOAR playbooks, scripts, notebooks, or custom tooling.
Authentication
All requests require an API key passed in the x-token-authorization header.
To generate an API key:
- Log in to Query as an administrative user at https://go.query.ai.
- Click the Settings icon in the left navigation bar.
- Go to Organization → select your team → Integrations.
- Click Create to generate a new API key. Save it securely.
Request Format
- Endpoint:
https://api.query.ai/search/translation/fsql - Method:
POST - Content-Type:
application/json - Body: A JSON object with a
qproperty containing your FSQL query.
{
"q": "YOUR FSQL QUERY HERE"
}To receive streaming results, add the Accept: text/event-stream header.
Examples with curl
Run a search query (JSON response)
curl -X POST https://api.query.ai/search/translation/fsql \
-H "Content-Type: application/json" \
-H "x-token-authorization: YOUR_API_KEY" \
-d '{"q": "QUERY authentication.time, authentication.user.username, authentication.src_endpoint.ip WITH authentication.status_id = FAILURE SINCE 24hrs LIMIT 100"}'Run a search query (SSE stream)
curl -X POST https://api.query.ai/search/translation/fsql \
-H "Content-Type: application/json" \
-H "Accept: text/event-stream" \
-H "x-token-authorization: YOUR_API_KEY" \
-d '{"q": "QUERY authentication.** WITH authentication.status_id = FAILURE SINCE 24hrs"}'Explore the schema
curl -X POST https://api.query.ai/search/translation/fsql \
-H "Content-Type: application/json" \
-H "x-token-authorization: YOUR_API_KEY" \
-d '{"q": "EXPLAIN ATTRIBUTES network_activity.%ip"}'List connectors
curl -X POST https://api.query.ai/search/translation/fsql \
-H "Content-Type: application/json" \
-H "x-token-authorization: YOUR_API_KEY" \
-d '{"q": "EXPLAIN CONNECTORS"}'Validate a query before running it
curl -X POST https://api.query.ai/search/translation/fsql \
-H "Content-Type: application/json" \
-H "x-token-authorization: YOUR_API_KEY" \
-d '{"q": "VALIDATE QUERY authentication.** WITH authentication.status_id = FAILURE"}'Response Formats
JSON
When you do not include the Accept: text/event-stream header, the API returns a single JSON response. All responses include a command property. If there is an error, an error property is included.
{
"command": "EXPLAIN VERSION",
"fsql": "fsql-0.5.0",
"qdm": "qdm-1.4.1+ocsf-1.4.0"
}Server-Sent Events (SSE)
For QUERY commands, SSE is the recommended response format. Results stream as they arrive from each connector, so you can begin processing without waiting for all data sources to finish.
An SSE response consists of a sequence of typed events:
command
commandIdentifies the FSQL command that was invoked. There is always exactly one command event per request.
event: command
data: {"command": "query authentication.** with authentication.status_id = FAILURE after 24hrs limit 100"}
metadata
metadataContains metadata about the request, such as the trace ID for debugging.
event: metadata
data: {"trace_id": "abc123-def456-789"}
data
dataContains result records. There is one data event per result row. Each row is a hierarchical JSON object following the OCSF schema. Results arrive as they are returned from each connector, so rows from different connectors may be interleaved.
event: data
data: {"time":"2026-03-30T14:22:01.000000+00:00","status_id":"FAILURE","activity_id":"LOGON","severity_id":"INFORMATIONAL","user":{"username":"jsmith","email_addr":"[email protected]","uid":"a1b2c3d4-5678-90ab-cdef-1234567890ab"},"src_endpoint":{"ip":"10.100.1.16","hostname":"WORKSTATION07"},"metadata":{"product":{"name":"Active Directory","vendor_name":"Microsoft"},"version":"1.5.0"},"__event":"authentication"}
event: data
data: {"time":"2026-03-30T15:03:44.000000+00:00","status_id":"FAILURE","activity_id":"LOGON","severity_id":"INFORMATIONAL","user":{"username":"admin","email_addr":"[email protected]"},"src_endpoint":{"ip":"192.168.1.50"},"metadata":{"product":{"name":"Okta Identity Cloud","vendor_name":"Okta"},"version":"1.5.0"},"__event":"authentication"}
Note: Real results contain significantly more fields than shown here, including
device,actor,observables,unmappedconnector-specific data, and more. The examples above are trimmed for readability.
warning
warningReports advisories that don't stop the query, such as a note that results are partial. There may be zero or more warning events per request. Each carries a list of warnings. When a query's TIMEOUT cuts it short, the event also carries "timed_out": true:
event: warning
data: {"warnings": ["Results are partial because the 30s TIMEOUT was reached. Records returned: 412."], "timed_out": true}
error
errorReports errors. There may be zero or more error events per request. Errors from downstream data sources are reported per-connector — a failure in one connector does not stop results from flowing from others.
event: error
data: {"error": "Connector 'Palo Alto Firewall' timed out after 300 seconds"}
End of stream
The SSE connection closes when all connectors have finished (or timed out) and all results have been delivered.
Timeouts
API requests have a default timeout of 5 minutes. If your query spans many connectors or a wide time range, some connectors may not return results before the timeout. When a connector times out, an error event is emitted for that connector but results from other connectors are still returned.
If you regularly need longer timeouts, contact your Query account manager.
Time-limiting a query with TIMEOUT
To get an answer within a fixed time, add a TIMEOUT clause to a QUERY or SUMMARIZE. When the deadline passes, FSQL stops the query and returns the records that arrived before it, instead of waiting for every connector to finish. A SUMMARIZE answers with the statistic calculated over those records:
curl -X POST https://api.query.ai/search/translation/fsql \
-H "Content-Type: application/json" \
-H "Accept: text/event-stream" \
-H "x-token-authorization: YOUR_API_KEY" \
-d '{"q": "QUERY authentication.** WITH authentication.status_id = FAILURE SINCE 7d TIMEOUT 30"}'A query cut short by its TIMEOUT still completes normally. It isn't reported as an error. To tell partial results from complete ones:
- SSE: look for a
warningevent with"timed_out": true. It arrives after the lastdataevent, just before the stream closes. - JSON: check the
timed_outfield, which istruewhen theTIMEOUTwas reached. The warning text is in thewarningslist:
{
"command": "QUERY",
"results": [ ... ],
"warnings": ["Results are partial because the 30s TIMEOUT was reached. Records returned: 412."],
"timed_out": true
}A SUMMARIZE response carries the same two fields. Its warning counts the records summarized:
{
"command": "ANALYZE",
"operation": "count",
"value": 41822,
"warnings": ["Results are partial because the 30s TIMEOUT was reached. Records summarized: 41822."],
"timed_out": true
}In an SSE stream, a SUMMARIZE sends its warning event just before the data event that carries the statistic.
Time the query spends queued before it starts running counts toward its TIMEOUT. A TIMEOUT can't be longer than your environment's query execution timeout (300 seconds by default). See Query Syntax for the full rules, and Analytics Functions for how a partial statistic should be read.
Tips for avoiding timeouts
- Use
FROMto limit the connectors searched. - Use tight time ranges (
SINCE 24hrsinstead ofSINCE 30d). - Use
LIMITto stop early once you have enough results. - Use
TIMEOUTto stop at a deadline and keep the results gathered so far. - Use specific field selections instead of
**to reduce per-connector response size.
See Best Practices for more on query performance.
Pagination
The API does not paginate results. For SSE responses, results stream continuously until the query completes. To control the volume of results:
- Use
LIMITto cap the number of rows returned. - Use
ORDER BYwithLIMITto get the top or bottom N results (e.g., most recent events). - Use
WITHfilters to narrow the result set before it reaches you.
Rate Limits
There are no rate limits on the FSQL API today. Query reserves the right to introduce rate limits in the future. Note that rate limits on downstream data sources vary by connector and platform.
Error Handling
Authentication errors
If your API key is missing or invalid, the request will fail before any query is executed.
Query errors
If your FSQL query has a syntax error, the response will include an error property:
{
"command": "...",
"error": "Parse error: unexpected token 'WTIH' at position 30"
}Use VALIDATE QUERY to check your query for errors before running it.
Connector errors
Errors from individual data sources (timeouts, permission issues, etc.) are reported per-connector. A connector error does not fail the entire query — results from other connectors are still returned.
In SSE mode, connector errors appear as error events in the stream alongside data events from the connectors that succeeded.
Tips for Using the API
-
Start with EXPLAIN commands. Use
EXPLAIN CONNECTORSto see what's available andEXPLAIN ATTRIBUTESto verify field paths before writing queries. -
Use SSE for QUERY commands. JSON responses buffer the entire result set before returning, which can be slow for large queries. SSE lets you process results as they arrive.
-
Use VALIDATE before automating. When building queries programmatically, use
VALIDATE QUERYto catch syntax errors before submitting the real search. -
Pair ORDER BY with LIMIT. Since there's no pagination,
ORDER BY authentication.time DESC LIMIT 100is the way to get the most recent N results without pulling everything. Note thatORDER BYdefers result delivery until every data source has started sending records (the slowest source gates time-to-first-result), so omit it when you want records to stream as soon as they arrive. -
Handle SSE events by type. Your client should dispatch on the event type (
command,metadata,data,warning,error) rather than assuming all events are data rows.
Updated about 1 month ago