> ## Documentation Index
> Fetch the complete documentation index at: https://jesse-7a8b4a1d.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart

> Start a search, then stream its events or poll the run.

A search is asynchronous. `POST /v1/searches` reserves the money, writes the run, and answers `202` with an id before any searching happens. From there you have two ways to follow it, and they read the same run: stream `/events` for live stages, or poll the run and wait for a terminal state.

A run can take many minutes. Nothing holds a request open for the whole run any more, so a long timeout is only needed on the stream.

To keep a run on particular websites, send `sites` as a comma-separated list such as `linkedin.com, x.com`. Leave it out to search the web.

## 1. Start the search

```bash theme={null}
curl -s -X POST https://eniac.floworks.ai/v1/searches \
  -H "Authorization: Bearer $ENIAC_CREDENTIAL" \
  -H "Content-Type: application/json" \
  -d '{
        "q": "US fintech companies hiring ML engineers in the last 3 months",
        "target": 50,
        "speed": "fast",
        "relax": true
      }'
```

```json theme={null}
{ "id": "6f1c0c5b9a1e4b7b8d2f3a4c5e6d7f80", "status": "running" }
```

That is the whole body: `202`, an `id` and a `status`. If your balance cannot cover the \$5.00 reservation the call is `402` instead and no run is started. See [Errors](/errors).

## 2a. Stream the events

```bash theme={null}
curl -N --max-time 3600 \
  -H "Authorization: Bearer $ENIAC_CREDENTIAL" \
  "https://eniac.floworks.ai/v1/searches/6f1c0c5b9a1e4b7b8d2f3a4c5e6d7f80/events"
```

Each record is `id: <seq>` then `data: {json}` then a blank line. Lines beginning with `:` are keepalives and carry nothing. The server closes the stream once the run is terminal and you have caught up, so the connection ending is not by itself a failure, and nor is it proof the run finished cleanly. Keep the last `id` you saw: it is what lets you reconnect without a gap or a repeat, which [Streaming](/streaming) works through in full.

## 2b. Or poll the run

```python theme={null}
import os, time, requests

BASE = "https://eniac.floworks.ai"
AUTH = {"Authorization": f"Bearer {os.environ['ENIAC_CREDENTIAL']}"}

# The five terminal states. Anything else means the run is still going.
TERMINAL = {"done", "stopped", "budget_exhausted", "interrupted", "error"}

def search(query: str, target: int = 50) -> dict:
    start = requests.post(
        f"{BASE}/v1/searches",
        headers=AUTH,
        json={"q": query, "target": target, "speed": "fast", "relax": True},
        timeout=30,
    )
    if start.status_code == 402:
        # Out of funds. A retry fails the same way until the wallet is topped up.
        raise SystemExit(start.json()["detail"]["message"])
    start.raise_for_status()
    run_id = start.json()["id"]

    while True:
        run = requests.get(f"{BASE}/v1/searches/{run_id}", headers=AUTH, timeout=30).json()
        if run["status"] in TERMINAL:
            return run
        time.sleep(5)

run = search("US fintech companies hiring ML engineers in the last 3 months")

# A terminal run can carry a partial table, and `result` is null when the run
# never produced one, so neither the status nor the field can be assumed.
rows = (run["result"] or {}).get("table") or []
print(run["status"], run["usdDisplay"], len(rows), "rows")
```

Poll every few seconds, not every few hundred milliseconds. `result` holds the `final` event once the run is terminal, which is the table to store; see [Result row](/result).

## 3. Stop a run, if you need to

```bash theme={null}
curl -s -X POST \
  -H "Authorization: Bearer $ENIAC_CREDENTIAL" \
  "https://eniac.floworks.ai/v1/searches/6f1c0c5b9a1e4b7b8d2f3a4c5e6d7f80/stop"
```

```json theme={null}
{ "id": "6f1c0c5b9a1e4b7b8d2f3a4c5e6d7f80", "status": "running", "stopRequested": true }
```

The flag is raised immediately; the run unwinds within seconds and lands as `stopped` with whatever had already passed the funnel. Dropping the event stream is not a stop: the run keeps going on the server and keeps costing money.

<Tip>
  Read until `type` is `done`, but do not rely on it arriving. The rows you store are in the `final` event, which arrives just before `cost`, `usage` and `done`. A run that was interrupted can end without any of the four, which is why the run's `status` is the authority on whether it is over. See [The run](/run).
</Tip>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.