# 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:

```
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](./endpoints.md#prerequisites).
- `curl`, and optionally `jq` for readable output.

## Step 1: Get an API key

Go to [console.amdahl.co](https://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](./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](./search.md) 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](./endpoints/search.md).

## 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](./endpoints/enrich.md).

## What's next

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

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

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