Documentation menu
Reference / v0.1

REST API reference

The current v1 contract, from endpoint discovery to query results and audit events.

Reviewed September 16, 2026 · Current implementation

Base URL and requests

Base URL
https://api.recursift.app/v1

Send an Authorization bearer header on every data request, and Content-Type: application/json for query creation. Responses are JSON. Unknown fields in query bodies are rejected. The /health route is outside /v1 and requires no key.

Routes

Method / routeRequired scopeResponse
GET /meAny valid keykey_id, customer_id, scopes
GET /agentsagents:readagents, next_cursor
POST /queriesquery:write202 receipt: id, status, agent_total, deadline
GET /queriesquery:readqueries, next_cursor
GET /queries/{id}query:readJob, findings, counts, unanswered_agents
POST /queries/{id}/cancelquery:writeReceipt; terminal jobs remain unchanged
GET /findingsquery:readfindings, coverage, next_cursor
GET /audit/eventsaudit:readevents, next_cursor
POST /resource-queriesresources:query202: id and status running. The question is not saved.
GET /resource-queries/{id}resources:queryStatus and coverage. Result rows are empty.
POST /resource-queries/{id}/cancelresources:queryid and status. A finished query is unchanged.

Saved questions use /queries and keep the question and answer. Ephemeral resource queries use /resource-queries, require persistence_mode ephemeral, and do not keep the question, parameters, results or idempotency key. customer_history is refused with 422. See Data flows and retention.

Create a query

JSON body
{
  "question": "What operating system are you running?",
  "target": {
    "agent_ids": [
      "YOUR_ENDPOINT_ID"
    ]
  },
  "timeout_seconds": 120
}
FieldConstraint
question1–500 characters after trimming
target.agent_ids1–100 unique, accessible endpoint IDs
timeout_seconds5–120 seconds; omitted or 0 defaults to 120
Idempotency-Key headerOptional, at most 128 characters; preserve for retries
Request bodyAt most 16 KiB

Any unknown or inaccessible target rejects the whole query with 404. An empty target never means the whole fleet. Reusing an idempotency key with a different normalized request returns 409; matching requests return the same job.

Job and finding fields

ObjectFields
Agentid, hostname, platform, last_seen_at, status
Jobid, status, question, created_at, deadline, agent_total, agent_answered, agent_failed, findings, unanswered_agents
Findingagent_id, hostname, status, answer, error, answered_at, query_id
Audit eventseq, event_json, prev_hash, hash

Finding answer, error and answered_at may be null. GET /queries/{id} materializes newly received findings. Answer text is bounded to 4,000 characters; raw evidence rows are not exposed by this API.

Pagination and finding search

List routes accept limit (1–100, default 50) and cursor. Pass the returned next_cursor unchanged and stop when it is empty. Ordering follows stable IDs, not creation time. Audit cursors are sequence numbers.

Findings example
curl --fail-with-body --get "https://api.recursift.app/v1/findings" \
  -H "Authorization: Bearer $RECURSIFT_API_KEY" \
  --data-urlencode "search=macOS" \
  --data-urlencode "limit=20"

Detection routes

Method / routeRequired scopePurpose
GET /detection/catalogdetection:readAtomic catalog metadata; filter by platform or technique
GET /detection/bundlesdetection:readInstalled rule packs and per-rule attribution
POST /detection/bundlesdetection:scanInstall a signed rule pack
POST /detection/bundles/{id}/activatedetection:scanMake a pack active for its format
DELETE /detection/bundles/{id}detection:scanRevoke a pack
GET /detection/capabilitiesdetection:readPer-endpoint readiness as reported
GET /detection/jobsdetection:readRecent jobs with their endpoint results
GET /detection/jobs/{id}detection:readOne job and its denominator
POST /detection/jobsdetection:scanFile scan, path scan or event replay on 1–100 endpoints
POST /detection/jobs/{id}/canceldetection:scanCancel a job

The API checks the scope, records an audit event, and forwards the request with your key, which the console validates again for scope and customer ownership. A missing scope returns 403 naming the required scope. Requests are limited to 256 KiB. An endpoint with no report reads as no detection capability reported, and an unknown result is never shown as no match.

Errors

JSON error envelope
{
  "error": {
    "code": "not_found",
    "message": "Route not found"
  }
}
StatusMeaning
400Invalid request, target, cursor or limit
401Missing or invalid customer key
403Insufficient scope or refused browser origin
404Unknown route or resource unavailable to this customer
409Idempotency conflict
429Key, customer or endpoint limit; honor Retry-After
500 / 503Service or storage failure; retain request identifiers

MCP transport errors do not use this REST JSON envelope. The OpenAPI download describes the REST surface.

Continue readingConnect through MCP →