# Make a first call (/docs/getting-started/first-call)



The base URL is `https://api.gridrouter.io`. Send your key as a bearer token and a JSON body whose
`input` matches the endpoint's input schema. Money is always integer **micro-USD**
(1,000,000 = $1).

## Call one endpoint [#call-one-endpoint]

`POST /v1/call/{provider}/{endpoint}` runs exactly the endpoint you name. This one is Hunter's
email finder, so add a Hunter key first.

<Tabs items="[&#x22;curl&#x22;, &#x22;TypeScript&#x22;, &#x22;Python&#x22;]">
  <Tab value="curl">
    ```bash
    curl https://api.gridrouter.io/v1/call/hunter/email.find \
      -H "Authorization: Bearer $GRID_API_KEY" \
      -H "Content-Type: application/json" \
      -H "Idempotency-Key: lead-8841" \
      -d '{"input": {"first_name": "Ada", "last_name": "Lovelace", "domain": "example.com"}}'
    ```
  </Tab>

  <Tab value="TypeScript">
    ```ts
    const res = await fetch("https://api.gridrouter.io/v1/call/hunter/email.find", {
      method: "POST",
      headers: {
        Authorization: `Bearer ${process.env.GRID_API_KEY}`,
        "Content-Type": "application/json",
        "Idempotency-Key": "lead-8841",
      },
      body: JSON.stringify({
        input: { first_name: "Ada", last_name: "Lovelace", domain: "example.com" },
      }),
    });
    const call = await res.json();
    if (!res.ok) throw new Error(`${call.error.code}: ${call.error.message}`);
    console.log(call.hit, call.data.email);
    ```
  </Tab>

  <Tab value="Python">
    ```python
    import os
    import requests

    res = requests.post(
        "https://api.gridrouter.io/v1/call/hunter/email.find",
        headers={
            "Authorization": f"Bearer {os.environ['GRID_API_KEY']}",
            "Idempotency-Key": "lead-8841",
        },
        json={"input": {"first_name": "Ada", "last_name": "Lovelace", "domain": "example.com"}},
        timeout=60,
    )
    call = res.json()
    if not res.ok:
        raise RuntimeError(f"{call['error']['code']}: {call['error']['message']}")
    print(call["hit"], call["data"].get("email"))
    ```
  </Tab>
</Tabs>

The response is a call object:

```json
{
  "object": "call",
  "id": "call_…",
  "endpoint_id": "hunter/email.find",
  "provider": "hunter",
  "status": "succeeded",
  "hit": true,
  "cost_micro": 0,
  "latency_ms": 640,
  "credential": "byok",
  "data": { "email": "ada@example.com", "confidence": 94 },
  "attempts": [
    { "endpoint_id": "hunter/email.find", "provider": "hunter", "outcome": "hit", "cost_micro": 0, "latency_ms": 640 }
  ]
}
```

* `status` is whether the vendor answered; `hit` is whether it found what the capability promises
  (here an email). A miss is a successful call with `hit: false`, not an error.
* `data` holds the endpoint's normalized output fields. Add `"include_raw": true` for the vendor's
  own response in `raw`.
* `cost_micro` is what GridRouter charged: always `0` on your own key.
* The same `Idempotency-Key` with the same body replays the first answer; with a different body it
  is `422 idempotency_mismatch`.

## Let GridRouter pick the vendor [#let-gridrouter-pick-the-vendor]

`POST /v1/run/{capability}` takes the capability instead of one endpoint and tries the vendors
you have connected until one hits. Every try is listed in `attempts`.

```bash
curl https://api.gridrouter.io/v1/run/people.email.find \
  -H "Authorization: Bearer $GRID_API_KEY" \
  -H "Content-Type: application/json" \
  -H "X-Grid-Max-Cost: 0.05" \
  -d '{
    "input": {"first_name": "Ada", "last_name": "Lovelace", "domain": "example.com"},
    "provider": {"order": ["prospeo", "hunter"]}
  }'
```

`X-Grid-Max-Cost` is in **USD** (`0.05` is 50,000 micro-USD); in the body the same cap is
`max_cost_micro`. See [routing](/docs/concepts/routing) for `order`, `only`, `ignore`, `sort` and
fallbacks.

## Find endpoints [#find-endpoints]

The catalog is public: `GET /v1/catalog/endpoints?q=email` searches it and
`GET /v1/catalog/endpoints/{provider}/{endpoint}` returns one endpoint's input JSON Schema, price and
quality. `POST /v1/quote/{provider}/{endpoint}` prices a call without making it.

