Endpoints
The endpoint surface - Search synchronously, Evals as a graded report card - plus the async Agents door, and how the verbs chain into one motion
Amdahl's public API is a small set of endpoints: synchronous primitives that answer in one blocking call, an async graded report card, plus the async Agents door for anything that needs a real investigation. Reach for an endpoint when you already know the shape of the answer — a filtered slice, a meaning-based ranking, a grade on a draft — and for Chat when you want Amdahl to figure out the shape for you.
- Search —
search.query, one routed door over your warehouse with a typed-filter lane, an NL→SQL lane, and a meaning-based semantic lane, plus thesearch.fieldsvocabulary catalog. - Evals —
evals.run, a graded report card over content: hand it a prompt and/or a drafted message and it grades them against verbatim quotes retrieved from your own calls and emails, then produces and grades an improved reusable prompt. Async — it returns a handle you poll. The one place the API judges your writing rather than answering a question, which is why it is also the natural gate before an agent sends. - Agents — the async surface: the Chat ask-door, the reusable agent library, and cron Routines.
Every endpoint at a glance
| Endpoint | Operation | REST | MCP tool + action | Scope | Stability | Typical latency |
|---|---|---|---|---|---|---|
| Routed search | search.query | POST /search/query | search → query | data:read | beta | ~2s |
| Field catalog | search.fields | GET /search/fields | search → fields | data:read | beta | sub-second |
| Graded report card | evals.run | POST /evals/run | evals → run | evals:execute | beta | async (handles now) |
| What-if projection | simulate.run | POST /simulate | simulate → run | data:read | coming soon | — |
| Start a Chat | chat.start | POST /chat | agents → start_chat | conversations:write | stable | async (handles now) |
| Agent library CRUD | agents.*_agent | /agents[...] | agents → *_agent | agents:read / agents:write | stable | sub-second |
| Routines CRUD + fire | routines.* | /routines[...] | agents → *_routine | routines:read / routines:write | stable | sub-second |
The simulate endpoint is not live yet: its page documents the planned shape so you can design against it, and it is deliberately absent from the OpenAPI spec and tool catalog until launch.
Every synchronous endpoint shares the same contract style: past parameter validation it returns success: true with typed fields for every degradation (a missing scope, an unmaterialized index, an empty corpus) — partial and honest beats a 500. That covers degradations, not failures, so there is still a real non-2xx set to handle:
| Status | Codes | What it means |
|---|---|---|
| 400 | invalid_argument | A named bad field, operator, or identifier. The details name the offending field and the allowed set. Fix the payload; do not retry. |
| 401 | unauthenticated | The key is missing, malformed, or expired. |
| 403 | forbidden, not_on_public_api | The key is valid but lacks the scope, or the operation is console-only. Both are terminal for that credential. |
| 429 | rate_limited, quota_exceeded | Back off on the first, honoring Retry-After; the second is an exhausted monthly verb cap and is terminal until the month rolls. |
| 5xx | internal_error, query_failed | The call faulted server-side rather than being refused — the spec declares a 500 on every operation on this page. Unlike the terminal rows above this one IS retryable: resend the same request with exponential backoff and jitter, and quote the X-Request-Id if it persists. |
The 429 is the one most integrations meet first and plan for last. POST /search/query carries its own 10 queries per minute per user budget underneath the global 60-per-minute per-IP limit, so pacing against 60 will exhaust it — see Rate limits for the budget, the X-RateLimit-* headers, and why the global limiter's 429 body is plain text while this one is the JSON envelope. The full envelope and per-code retry guidance are in Pagination and errors; the gate codes not_on_public_api and quota_exceeded carry the extra detail on their details payloads.
How the endpoints chain
Each endpoint is one blocking call, which makes them composable — the canonical chain is find the cohort, then read what it said:
Structured search
"Closed-won deals this year, largest first" - real pipeline company ids.
mode=filter
Semantic search
The objections those accounts already raised, scoped to those ids.
mode=semantic
1. structured search POST /search/query "closed-won deals this year, largest first"
│ → real pipeline company ids
▼
2. semantic search POST /search/query mode=semantic + company_id IN (ids)
→ the objections those accounts already raisedTwo synchronous calls, no agent run — a cohort with its own words attached. Both lanes go through one door, so the second call is the first one with a different mode. When a step's answer needs judgment rather than retrieval ("which of these should we actually pursue and why"), or outside market signal, hand the thread to Chat: the async lane exists precisely for the asks the endpoints cannot settle in one call.
Two more chains worth knowing:
- Discovery-first search:
GET /search/fields→ compose typed filters →POST /search/query. The catalog is derived from the same schema the compiler validates against, so it cannot drift — and a wrong field name comes back as a typedinvalid_argumentnaming the allowed set. - Grade before you send: whatever wrote the message — a rep, a sequence, an agent —
POST /evals/rungrades it against what your buyers actually said, and you gate on the verdict. It is read-pure by construction, so it is always safe to put in that path. See Use it as a gate.
Prerequisites
An API key with the right scopes
Mint a key in the console (Settings → Developer, see Authentication) and send it as X-API-Key — or as Authorization: Bearer — on every request; one key works on both transports. The base URL is:
https://app.amdahl.ai/api/platform/v1Per family:
| Family | Scope |
|---|---|
search.query / search.fields | data:read |
| Fire an eval | evals:execute |
| Poll an eval run / browse evals / compare runs | evals:read |
| Start / rename a Chat | conversations:write |
| Read a Chat / poll a run | conversations:read |
| Answer a pause / cancel a run | workflows:write |
| Agent library read / write | agents:read / agents:write |
| Routines read / write | routines:read / routines:write |
A read-only key can call every synchronous endpoint on this page, read Chats, and browse + poll evals — but cannot start a Chat, fire an eval, answer a pause, or write an agent or routine.
See also
- Search — the routed endpoint — the per-endpoint guide.
- Evals — the graded report card over your workspace's answers.
- Simulate — the coming-soon what-if projection, documented ahead of launch.
- Search and Chat — the two "ask Amdahl" doors.
- Tool catalog — the generated per-operation reference.