# Find a lead

Source: https://help.ruuster.com/api/leads-lookup

```http
GET https://api.ruuster.com/v1/leads/lookup
```

Find your leads by email, phone or CRM id. Returns every match, with links to their activity and emails.

- Authentication: `x-api-key` and `x-email` headers of an owner or admin
- Rate limit: *lookup* call, 20 per minute per key, within the 120 per minute
- Rows count against the daily lead-row quota (50,000 by default)

Only your brokerage's leads are searched.

## Query parameters

| Name | Type | Default | Description |
|---|---|---|---|
| `email` | string | | Case-insensitive. Secondary emails are checked when no lead has it as their main email |
| `phone` | string | | Any format; the last 10 digits are compared. Secondary numbers are checked when no lead has it as their main number |
| `crmExternalId` | string | | Exact match on the lead's id in your CRM |

Send exactly one of the three, otherwise `400 invalid_parameter`. Lookup by email or phone works even when lead contact details are off; the response then leaves out `email` and `phone`.

## Response

`data.leads` lists every match. Each has the short lead form (`leadId`, names, contact details when on, `crmExternalId`, `crmStatus`, `crmTags`, `agentId`, `createdAt`, `lastLoginAt`), plus `matchedOn` (`email`, `phone` or `crmExternalId`) and `links` to the lead's activity and emails. More than one record is normal: the same person can be a registered user and a CRM contact, or be with two agents. No match returns an empty list with `200`. For Ruuster's verdict on a lead's email address, use
[Get a lead's email status](https://help.ruuster.com/api/leads-email-status).

## Example request

cURL:

```bash
curl -s "https://api.ruuster.com/v1/leads/lookup?phone=(520)%20555-0142" \
  -H "x-api-key: $RUUSTER_API_KEY" \
  -H "x-email: $RUUSTER_EMAIL"
```

Node.js:

```javascript
const res = await fetch("https://api.ruuster.com/v1/leads/lookup?phone=(520)%20555-0142", {
  headers: {
    "x-api-key": process.env.RUUSTER_API_KEY,
    "x-email": process.env.RUUSTER_EMAIL,
  },
});
const body = await res.json();
if (!body.ok) throw new Error(`${body.error.code}: ${body.error.message} (${body.requestId})`);
console.log(body.data);
```

Python:

```python
import os
import requests

res = requests.get(
    "https://api.ruuster.com/v1/leads/lookup?phone=(520)%20555-0142",
    headers={"x-api-key": os.environ["RUUSTER_API_KEY"], "x-email": os.environ["RUUSTER_EMAIL"]},
    timeout=30,
)
body = res.json()
if not body["ok"]:
    raise RuntimeError(f'{body["error"]["code"]}: {body["error"]["message"]} ({body.get("requestId")})')
print(body["data"])
```

## Example response

```json
{
  "ok": true,
  "data": {
    "leads": [
      {
        "leadId": "user:c0ff3e21-8a4b-4c7d-9e15-2b6f8d3a1c04",
        "firstName": "Sam", "lastName": "Lee", "email": "sam.lee@example.com", "phone": "+15205550142",
        "crmExternalId": "48213", "crmStatus": "Showing Homes Nurture", "crmTags": ["buyer", "tucson"],
        "agentId": "7c1e9b42-3d85-4a6f-9e07-1b2c8d4f5a69",
        "createdAt": "2026-09-21T18:20:05Z", "lastLoginAt": "2026-09-30T02:11:40Z",
        "matchedOn": "phone",
        "links": { "activity": "/v1/leads/user:c0ff3e21-8a4b-4c7d-9e15-2b6f8d3a1c04/activity",
                   "emails": "/v1/leads/user:c0ff3e21-8a4b-4c7d-9e15-2b6f8d3a1c04/emails" }
      }
    ]
  },
  "meta": { "brokerageId": "4f6c2a9e-8d31-4b57-9a0e-2c7d5e1b8f43" }
}
```
