Docs

Quickstart

Get from nothing to your first live answers in under five minutes: mint an API key, ask your warehouse a plain-language question, pull a deterministic filtered slice, and fast-enrich a company — three real calls against your own data.

All consumer endpoints live under one base URL:

code
https://app.amdahl.co/api/platform/v1

Every request sends your API key in the X-API-Key header. Everything below is plain HTTPS with JSON bodies, so the same flow works from a CLI, a backend service, or a long-running agent.

Prerequisites

  • A workspace on Agent Platform v2 (the agent_v2 flag). If a call below returns 403 with error.code: "feature_disabled", ask your Amdahl admin to enable it for the workspace — see Endpoints: prerequisites.
  • curl, and optionally jq for readable output.

Step 1: Get an API key

Go to console.amdahl.co, open the workspace you want to operate against, and head to Settings -> Developer -> Create key. Scope the key to at least data:read, then copy the plaintext value the instant it is shown — the server stores only a hash and will never display it again; a lost key must be replaced, not recovered. Full details (OAuth, JWT, the scope matrix) are in authentication.md.

Export it so the rest of the examples stay short:

bash
export AMDAHL_KEY="amdhl_your_key_here"
export AMDAHL_BASE="https://app.amdahl.co/api/platform/v1"

Step 2: Ask your first question

POST /search is the fast lane: one blocking call that turns a plain-language ask into SQL over your interactions warehouse, runs it, and returns the rows and the SQL it ran. It needs only data:read.

bash
curl -s -X POST "$AMDAHL_BASE/search" \
  -H "X-API-Key: $AMDAHL_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "query": "how many calls did we have in the last 30 days?" }' \
  | jq

Expected response shape (trimmed — the Search guide documents every field):

json
{
  "success": true,
  "query": "how many calls did we have in the last 30 days?",
  "mode": "internal",
  "internal": {
    "status": "ok",
    "sql": "SELECT COUNT(DISTINCT interaction_id) AS calls FROM interactions WHERE …",
    "rows": [{ "calls": 214 }],
    "row_count": 1
  },
  "message": "Found 1 result over your interactions.",
  "coverage": { "latest_event_at": "2026-07-21T05:01:50Z", "days_behind": 1, "is_stale": false }
}

Three things to notice: past parameter validation the fast lane always returns success: true (every failure mode is a typed field like internal.status, never a raw error); internal.sql is the receipt for what actually ran; and coverage tells you how current your warehouse data is. A 401 here means the key is missing or wrong; a 403 with feature_disabled means the workspace is not on Agent Platform v2 yet.

Step 3: Pull a deterministic slice

When you want predicates instead of prose — the same slice every run, no model interpreting your wording — use the routed endpoint POST /search/query with typed filters. The open pipeline over $50k, largest first:

bash
curl -s -X POST "$AMDAHL_BASE/search/query" \
  -H "X-API-Key: $AMDAHL_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "surface": "deals",
    "filters": [
      { "field": "deal_stage_status", "op": "eq", "value": "open" },
      { "field": "deal_amount", "op": "gte", "value": 50000 }
    ],
    "order_by": { "field": "deal_amount", "dir": "desc" },
    "limit": 10
  }' | jq
json
{
  "success": true,
  "mode_ran": "filter",
  "results": [
    { "deal_id": "9214…", "deal_name": "Northwind expansion", "deal_amount": 180000, "deal_stage_status": "open" }
  ],
  "compiled": { "sql": "SELECT … FROM deals WHERE `deal_stage_status` = 'open' AND `deal_amount` >= 50000 …" }
}

Field names are never guessed: GET /search/fields lists every filterable field per surface with its type and operators, and a wrong one comes back as a typed invalid_argument naming the allowed set. The full filter DSL (plus the fuzzy and semantic lanes behind the same door) is in the Search endpoint guide.

Step 4: Enrich a company

POST /enrich/company returns intelligence on one account fast by default: a fresh cached brief instantly, or — on a cache miss — your own first-party conversation evidence now while the full web-fused brief rebuilds in the background:

bash
curl -s -X POST "$AMDAHL_BASE/enrich/company" \
  -H "X-API-Key: $AMDAHL_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "domain": "stripe.com" }' | jq

Branch on tier: cached carries the stored brief with its captured_at; first_party carries the evidence envelope (what this account said to you) with refresh_enqueued: true — re-call the same domain later and you land on the cache. The tier ladder, person and topic subjects, and the scope-degradation contract are in the Enrich guide.

What's next

You now have working auth and three live reads against your own data. Common next stops:

  • Endpoints — the whole synchronous surface (Search, Enrich, Lookalike) and how the verbs chain into the expansion motion.
  • Chat — hand a multi-step, server-side investigation to an agent and poll for the answer.
  • Routines — schedule a Chat to run itself on a cadence.
  • API reference — the operation catalog and OpenAPI spec.

If something breaks, start with pagination-errors.md to decode the error envelope, then check rate-limits.md if you are seeing rate_limited.