> ## Documentation index
> Fetch the complete documentation index at: https://docs.leadity.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart

> Create a key, make your first request and place your first order in a few minutes.

This walk-through uses the HTTP API with cURL, Node.js and Python. To work from an AI agent instead, follow [Set up the MCP server](https://docs.leadity.io/mcp/setup).

**1. Create an API key**

Open the [Leadity API screen](https://app.leadity.io/connectors/api) on the Leadity app's Connectors page and create an **API key**. Tick the scopes it needs: every key can read, and placing an order also needs **spend**. The secret is shown once, so copy it then and keep it somewhere safe.

```bash
export LEADITY_API_KEY="lk_api_..."
```

**2. Make your first request**

Search the niches you can order. A read like this takes no credits.

```bash cURL
curl "https://api.leadity.io/v1/niches?q=roof" \
  -H "Authorization: Bearer $LEADITY_API_KEY"
```

```javascript Node.js
const response = await fetch("https://api.leadity.io/v1/niches?q=roof", {
  headers: { Authorization: `Bearer ${process.env.LEADITY_API_KEY}` },
});
console.log(await response.json());
```

```python Python
import os

import requests

response = requests.get(
    "https://api.leadity.io/v1/niches",
    params={"q": "roof"},
    headers={"Authorization": f"Bearer {os.environ['LEADITY_API_KEY']}"},
)
print(response.json())
```

The answer groups each niche under its market. The `id` is what an order names.

```json
{
  "version": "3f9a1c2b7d4e",
  "groups": [
    {
      "group": "Home Services & Construction",
      "niches": [{ "id": "roofing_contractor", "name": "Roofing Contractor", "multiplier": 1, "findOwner": true }]
    }
  ]
}
```

**3. Price an order**

[`estimate_scrape`](https://docs.leadity.io/api-reference/scrapes/estimate-scrape) prices an order without placing it. Send the niches, the area and the filters. It takes no lead count: it answers the price of one lead, which prices any count.

```bash cURL
curl -X POST "https://api.leadity.io/v1/scrapes/estimate" \
  -H "Authorization: Bearer $LEADITY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "nicheIds": ["roofing_contractor"],
    "selection": { "states": [{ "country": "US", "state": "TX" }] },
    "filters": { "websitePresence": "any", "phoneTypeFilter": "mobile" }
  }'
```

A selection names its country and region by code. [`list_territories`](https://docs.leadity.io/api-reference/catalog/list-territories) lists the countries on sale and each one's regions, and [`search_areas`](https://docs.leadity.io/api-reference/catalog/search-areas) finds a city or a postal code inside one.

The answer carries `leadRateMilli`, the exact price of one lead in thousandths of a credit, and your account's floors: `minTargetLeads` and `minOrderCredits`. The price of any number of leads is `ceil(leads x leadRateMilli / 1000)` credits.

**4. Place the order**

[`create_scrape`](https://docs.leadity.io/api-reference/scrapes/create-scrape) takes credits, so it needs two things a read does not: an `Idempotency-Key` header that you keep for this one order, and a `maxCredits` ceiling worked out from the estimate's rate: 1,000 mobile leads at a `leadRateMilli` of 1000 cost 1,000 credits. If the price is above the ceiling nothing is charged.

```bash cURL
curl -X POST "https://api.leadity.io/v1/scrapes" \
  -H "Authorization: Bearer $LEADITY_API_KEY" \
  -H "Idempotency-Key: tx-roofers-2026-10-04" \
  -H "Content-Type: application/json" \
  -d '{
    "nicheIds": ["roofing_contractor"],
    "selection": { "states": [{ "country": "US", "state": "TX" }] },
    "filters": { "websitePresence": "any", "phoneTypeFilter": "mobile" },
    "targetLeads": 1000,
    "maxCredits": 1000
  }'
```

The answer comes back at once, `201`, with the scrape's `id`. The scrape runs from there. If the connection drops before you read it, send the same request with the same key: the retry answers `200` with the same scrape and `"replayed": true`, and charges nothing again.

**5. Wait for it, then download**

Poll [`get_scrape_status`](https://docs.leadity.io/api-reference/scrapes/get-scrape-status) every 30 to 60 seconds until `complete` is true, then download the leads.

```javascript Node.js
const headers = { Authorization: `Bearer ${process.env.LEADITY_API_KEY}` };
const id = "Vb7nW3xQ9k";

for (;;) {
  const status = await (await fetch(`https://api.leadity.io/v1/scrapes/${id}/status`, { headers })).json();
  if (status.complete) break;
  await new Promise((resolve) => setTimeout(resolve, 45_000));
}

const csv = await (await fetch(`https://api.leadity.io/v1/scrapes/${id}/leads.csv`, { headers })).text();
```

## Next steps

- [Filters](https://docs.leadity.io/filters): Mobile numbers only, no website, owner names, emails and more.
- [Errors](https://docs.leadity.io/errors): Every refusal the API can answer, and what to do about it.
