Programmatic access to SARA — your glass-box Co-Analyst. Drop in via the OpenAI-compatible endpoint, enrich IOCs, triage alerts, drive the Self-Driving SOC. Looking for the analyst surface? See /help.
POST /api/feedback now tags thumbs feedback as explicit; SARA's per-tenant bandit learns which response styles your team actually prefers and can also infer signals from session behaviour.POST /api/chat (multipart) now rejects requests that exceed attachments_per_message for the caller's plan (free 2 / registered 3 / pro 5 / team 10) with a 400 before any LLM call.SARA Open exposes three auth tiers. The right one depends on which surface you're calling.
| Tier | Header | Use for |
|---|---|---|
| API key | x-api-key: sara_… | Public /api/v1/* endpoints. Generate in Settings → API. Pro+ only. |
| Session | cookie (OAuth) | In-browser endpoints under /api/chat, /api/feedback, /api/agents. Sign in with Google. |
| Anonymous | none | Free-tools endpoints under /api/free-tools/* and read-only Pulse / CVE lookups. Hard-rate-limited. |
curl -H "x-api-key: sara_your_key_here" \
https://sara-open.sirp.io/api/v1/chat
Keys start with sara_. They are returned once at creation — save them immediately. Listed keys show only a prefix.
Per-plan limits are defined in sara/security/feature_gate.py. The same gate enforces messages-per-hour, max API keys, attachment counts, and combined attachment text injection.
| Plan | Chat /hr | API keys | Attachments / msg | Combined text cap | API access |
|---|---|---|---|---|---|
| Free | 10 | 0 | 2 | 40 K chars | — |
| Registered | 50 | 0 | 3 | 60 K chars | — |
| Pro | 200 | 3 | 5 | 120 K chars | Yes |
| Team | 500 / seat | 10 | 10 | 200 K chars | Yes |
Rate-limit headers on every response: X-RateLimit-Remaining, X-RateLimit-Limit, X-RateLimit-Reset (Unix seconds).
/api/v1 endpointsAPI-key auth. Defined in sara/routes/api_v1.py.
/api/v1/chat.{
"model": "sara",
"messages": [
{"role": "user", "content": "What is CVE-2024-3400?"}
]
}
{
"id": "chatcmpl-abc123",
"object": "chat.completion",
"created": 1711000000,
"model": "sara",
"choices": [{
"index": 0,
"message": {"role": "assistant", "content": "..."},
"finish_reason": "stop"
}],
"usage": {"prompt_tokens": 150, "completion_tokens": 200, "total_tokens": 350}
}
from openai import OpenAI
client = OpenAI(
base_url="https://sara-open.sirp.io/api/v1",
api_key="sara_your_key_here",
)
resp = client.chat.completions.create(
model="sara",
messages=[{"role": "user", "content": "Analyze IP 185.220.101.34"}],
)
print(resp.choices[0].message.content)
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
base_url="https://sara-open.sirp.io/api/v1",
api_key="sara_your_key_here",
model="sara",
)
print(llm.invoke("What is APT29?").content)
mode, sources, detected IOCs, and remaining rate-limit window. Same pipeline as chat/completions; use this when you want the structured fields.{
"message": "What is CVE-2024-3400?",
"web_browse": true
}
{
"messages": [
{"role": "user", "content": "Tell me about APT28"},
{"role": "assistant", "content": "APT28 is..."},
{"role": "user", "content": "What TTPs do they use?"}
]
}
{
"response": "CVE-2024-3400 is a critical vulnerability in PAN-OS...",
"mode": "threat_intel",
"sources": ["Knowledge Base", "NVD"],
"iocs_detected": [],
"trace_id": "trc_8f3a...",
"remaining_this_hour": 499,
"hourly_limit": 500
}
| Field | Type | Description |
|---|---|---|
response | string | SARA's full analysis (Markdown) |
mode | string | Selected response mode (see Response Modes) |
sources | array | Data sources used (KB, NVD, EPSS, KEV, Web, OmniSense) |
iocs_detected | array | IOCs SARA extracted from the query |
trace_id | string | Opaque turn identifier — quote this in support requests if you need SARA's quality team to inspect the run |
{
"iocs": [
{"value": "185.220.101.34", "type": "ip"},
{"value": "44d88612fea8a8f36de82e1278abb02f", "type": "hash"}
]
}
Max 20 IOCs per request. Types: ip, hash, domain, url.
{
"results": "### 185.220.101.34\n**Verdict:** SUSPICIOUS...",
"ioc_count": 2,
"verdicts": [
{"value": "185.220.101.34", "type": "ip", "verdict": "SUSPICIOUS", "score": 60},
{"value": "44d886...", "type": "hash", "verdict": "MALICIOUS", "score": 90}
]
}
Verdict floors: KEV / abuse.ch confirmed-malicious feeds set a deterministic MALICIOUS floor that an LLM cannot override (see sara/core/observation_decoder.py).
// Alert triage {"content": "EventID=4625 LogonType=3 TargetUserName=admin...", "type": "alert"} // Phishing email {"content": "From: [email protected]\nReply-To: [email protected]...", "type": "email"} // CVE lookup {"content": "CVE-2024-3400", "type": "cve"} // Auto-detect {"content": "CEF:0|Palo Alto|Cortex XDR|...", "type": "auto"}
Types: alert (CEF, syslog, Kibana, JSON, Windows Event Log), email (phishing), cve, auto.
{
"analysis": "## Facts\n- Observed: EventID 4625...",
"type": "windows_event"
}
{"name": "My SOAR Integration"}
The full key is returned once in the response — save it immediately. After this call the prefix is the only thing the API ever returns.
Anonymous, hard-rate-limited surfaces that back the public free tools. No API key required. Defined in sara/routes/free_tools_*.py.
{"ioc": "185.220.101.34"}
Also supports GET /api/free-tools/ioc-check?ioc=… for embed-friendly use.
{"description": "Detect PowerShell with encoded command"}
{"raw_email": "From: …\nSubject: …\n\n…"}
Runs 25+ checks (SPF / DKIM / DMARC, signing-domain mismatch, RFC 2047 encoding, invisible Unicode, Base64 URL decoding) and auto-generates a matching Sigma rule.
/cve/{cve_id}./kev/{cve_id}.Agents are pluggable analysis units (Remediation, Alert Triage, IOC Enrichment, Phishing, Incident Orchestrator) registered in sara/agents/registry.py and surfaced under /api/agents. Session-auth.
CRITICAL (hard-block) vs. optional._AGENT_CRITICAL_REQUIREMENTS — missing upstream returns UPSTREAM_UNAVAILABLE after a one-shot retry rather than soft-proceeding.{"input": { /* agent-shape varies */ },
"incident_id": "266279"}
.eml to PhishingAgent).reward_source = "explicit_thumbs".{
"message_id": "msg_abc123",
"feedback": "up", // "up" | "down"
"comment": "Citation was spot-on", // optional, max 2000 chars
"mode": "threat_intel",
"agent": ""
}
SARA's mode resolver (sara/core/pipeline/resolve.py) picks a mode per turn. Each mode is a distinct prompt template + formatting contract; the chosen mode is returned on every response and bandit-tracked.
| Mode | Selected when |
|---|---|
definition | "What is X?" — short, plain-English glossary |
generic_guidance | "How do I…?" / "Steps to…" workflows |
brief_conversational | Greetings, meta questions, very short answers |
comparison | "X vs Y" — side-by-side framing |
product_explainer | Tool / vendor capability questions |
threat_intel | CVE lookups, threat-actor profiles, vulnerability research |
ioc_enrichment | IP / hash / domain / URL detected — per-IOC verdict tables |
url_analysis | Single URL deep-dive (defang, reputation, redirect chain) |
phishing_analysis | Email headers + body pasted; 25+ checks |
alert_triage | Alert payload (CEF, syslog, Kibana, JSON, Windows Event Log) |
detection_engineering | Sigma / KQL / Splunk rule authoring |
case_analysis | Real incident with enrichment + doctrine, structured Facts / Assessment / Recommendation |
action_proposal | Containment actions awaiting confirmation |
tenant_query | "Show me my incidents" — OmniSense list / filter |
tenant_overview | SOC briefing — MTTR / MTTD / SLA / workload roll-up |
threat_pulse | Daily threat-pulse briefing surface |
| Code | Meaning |
|---|---|
400 | Bad request — missing or invalid parameters, oversized comment, attachment-count or text-cap exceeded |
401 | Invalid or missing API key / session |
403 | Plan doesn't support this endpoint, or tenant binding missing |
413 | Payload too large (single attachment over 5 MB) |
422 | Schema validation failed (FastAPI Pydantic) |
429 | Rate limit exceeded — wait until X-RateLimit-Reset |
503 | LLM, retrieval, or upstream agent temporarily unavailable |
UPSTREAM_UNAVAILABLE | Agent error payload — a CRITICAL upstream (e.g. IntelOwl) was unreachable after retry; no soft-proceed |
import requests resp = requests.post( "https://sara-open.sirp.io/api/v1/chat", headers={"x-api-key": "sara_your_key"}, json={"message": "What is CVE-2024-3400?"}, ) data = resp.json() print(data["response"]) print("trace_id:", data["trace_id"]) # quote in support requests
const resp = await fetch("https://sara-open.sirp.io/api/v1/enrich", { method: "POST", headers: { "x-api-key": "sara_your_key", "Content-Type": "application/json" }, body: JSON.stringify({ iocs: [{ value: "185.220.101.34", type: "ip" }] }), }); const data = await resp.json(); console.log(data.verdicts);
curl -X POST https://sara-open.sirp.io/api/free-tools/phishing-analyze \
-H "Content-Type: application/json" \
-d '{"raw_email": "From: ..."}'
For the analyst-facing surface (chat, agents in the UI, workspaces, Pulse), see /help. For the standalone free tools, see /free-tools/*.