Skip to content

BuyRealClients API

v1

Search people, enrich your own records and reveal verified emails and direct dials from your code. Searching is free, reveals cost credits, and every call returns the same predictable JSON envelope.

Get an API key OpenAPI 3.1 specBase URLhttps://buyrealclients.com/api/v1

Quickstart

API access is included with the Pro and Team plans. Create a key on the API keys page, export it as BRC_API_KEY and make your first call.

Requestbash
curl https://buyrealclients.com/api/v1/account \  -H "Authorization: Bearer $BRC_API_KEY"
Response200 OK
{  "ok": true,  "data": {    "plan": {      "id": "pro",      "name": "Pro"    },    "credits": {      "balance": 1998    }  }}

Try it

Every example on this page runs as written once BRC_API_KEY is set. Create or revoke keys, and see each key's last use and request count, in Dashboard, API keys .

Authentication

Send your key in the Authorization header as a Bearer token. The X-API-Key header is accepted as an alternative. Keys look like brc_live_ followed by 32 characters and are shown once when created. We store only a hash.

Headerhttp
Authorization: Bearer brc_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx# orX-API-Key: brc_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

A missing, malformed or revoked key returns 401 INVALID_API_KEY. A valid key on an account whose plan has no API access (for example after a downgrade) returns 403 PLAN_REQUIRED.

CORS is enabled so you can test from a browser, but never ship a key in client-side code. Call the API from your backend and keep keys in environment variables or a secrets manager.

Rate limits

Requests are limited per API key over a sliding one-minute window. Reveals are additionally limited per minute and per day by your plan, and those limits apply to the app and the API combined.

PlanRequests / minReveals / minReveals / dayMax results per searchCredits / month
Pro60602,0005,0002,000
Team1201206,00010,0006,000

Every authenticated response carries these headers:

  • X-RateLimit-Limit requests allowed per minute for this key.
  • X-RateLimit-Remaining requests left in the current window.
  • X-RateLimit-Reset Unix time (seconds) by which your full budget is restored.
  • X-Request-Id unique id of the request. Include it when you contact support.

When you exceed a limit you get 429 with RATE_LIMITED (or DAILY_LIMIT) and a Retry-After header in seconds. Wait that long before retrying.

Rate limited429
HTTP/1.1 429 Too Many RequestsX-Request-Id: req_9f1c2d3e4a5b6c7d8e9f0a1bX-RateLimit-Limit: 60X-RateLimit-Remaining: 0X-RateLimit-Reset: 1791717660Retry-After: 12

Credits

Searching, fetching a person, suggestions, account and usage calls are free. Revealing a contact field costs 1 credit per field, once.

  • Revealing a field you already revealed, in the app or the API, is free and returns the same value.
  • If a field turns out to be empty, the credit is refunded automatically and you get 404 NO_DATA.
  • Out of credits returns 402 INSUFFICIENT_CREDITS and nothing is charged.
  • Credits are shared with the web app. Check the balance any time with GET /account.

Responses

Every response is JSON in one of two envelopes: { ok: true, data } or { ok: false, error: { code, message, details? } }. Branch on error.code, which is stable, and show error.message to humans. Field names are snake_case.

Contact values appear only under contact.email.value and contact.phone.value, and only for fields your account has revealed. Everything else, including contact.email.domain and the available flags, is safe to read freely.

Error402
{  "ok": false,  "error": {    "code": "INSUFFICIENT_CREDITS",    "message": "Not enough credits",    "details": {      "required": 1,      "balance": 0    }  }}

Endpoints

All paths are relative to https://buyrealclients.com/api/v1. Switching the language on any example switches all of them.

GET/api/v1/people/{id}Free

Get a person

Fetch one person by id or by the slug used in profile URLs. Contact values are included only for fields you have already revealed.

Path parameters

NameTypeDescription
idrequiredstringPerson id or slug.
Requestbash
curl https://buyrealclients.com/api/v1/people/5f2a9c1e7b3d4a6e8c0f1b2d \  -H "Authorization: Bearer $BRC_API_KEY"
Response200 OK
{  "ok": true,  "data": {    "person": {      "id": "5f2a9c1e7b3d4a6e8c0f1b2d",      "slug": "jane-doe-acme-corp-1b2d",      "first_name": "Jane",      "last_name": "Doe",      "full_name": "Jane Doe",      "title": "VP of Sales",      "seniority": "vp",      "functions": [        "sales"      ],      "company": {        "name": "Acme Corp",        "slug": "acme-corp"      },      "location": {        "city": "Chicago",        "state": "Illinois",        "country": "United States"      },      "linkedin_url": "https://www.linkedin.com/in/janedoe-example",      "contact": {        "email": {          "available": true,          "status": "verified",          "domain": "acme.com"        },        "phone": {          "available": true        }      },      "tier": "premium",      "profile_url": "https://buyrealclients.com/people/jane-doe-acme-corp-1b2d"    }  }}
POST/api/v1/people/{id}/reveal1 credit per field

Reveal contact details

Reveals the email and/or phone of one person. Each newly revealed field costs 1 credit. Fields you revealed before, in the app or the API, are returned again for free. Fields with no data on file are never charged.

  • If some requested fields succeed and others fail, you get 200 with the failures listed under errors.
  • If nothing can be revealed, the first error is returned: 402 INSUFFICIENT_CREDITS, 404 NO_DATA, or 429 RATE_LIMITED / DAILY_LIMIT.
  • Reveals are also limited per minute and per day by plan (Pro: 60/min, 2,000/day; Team: 120/min, 6,000/day).

Path parameter and JSON body

NameTypeDescription
idrequiredstringPerson id or slug (path).
fieldsrequiredstring[]One or both of "email" and "phone".
Requestbash
curl -X POST https://buyrealclients.com/api/v1/people/5f2a9c1e7b3d4a6e8c0f1b2d/reveal \  -H "Authorization: Bearer $BRC_API_KEY" \  -H "Content-Type: application/json" \  -d '{"fields":["email","phone"]}'
Response200 OK
{  "ok": true,  "data": {    "person": {      "id": "5f2a9c1e7b3d4a6e8c0f1b2d",      "slug": "jane-doe-acme-corp-1b2d",      "first_name": "Jane",      "last_name": "Doe",      "full_name": "Jane Doe",      "title": "VP of Sales",      "seniority": "vp",      "functions": [        "sales"      ],      "company": {        "name": "Acme Corp",        "slug": "acme-corp"      },      "location": {        "city": "Chicago",        "state": "Illinois",        "country": "United States"      },      "linkedin_url": "https://www.linkedin.com/in/janedoe-example",      "contact": {        "email": {          "available": true,          "status": "verified",          "domain": "acme.com",          "value": "jane.doe@acme.com"        },        "phone": {          "available": true,          "value": "+1 312-555-0147"        }      },      "tier": "premium",      "profile_url": "https://buyrealclients.com/people/jane-doe-acme-corp-1b2d"    },    "credits": {      "spent": 2,      "balance": 1998    },    "results": {      "email": {        "source": "vault",        "credits_spent": 1      },      "phone": {        "source": "vault",        "credits_spent": 1      }    }  }}
POST/api/v1/people/reveal/batch1 credit per new field

Batch reveal

Reveals up to 25 people in one call. Ids are processed in order. Each id gets its own result: ok, error or skipped.

  • The batch stops at the first 402 (out of credits) or 429 (rate limit). Remaining ids come back as skipped with the reason, and are not charged.
  • A failed id (for example NOT_FOUND) does not stop the batch.

JSON body

NameTypeDescription
idsrequiredstring[]1 to 25 person ids or slugs. Duplicates are ignored.
fieldsrequiredstring[]One or both of "email" and "phone".
Requestbash
curl -X POST https://buyrealclients.com/api/v1/people/reveal/batch \  -H "Authorization: Bearer $BRC_API_KEY" \  -H "Content-Type: application/json" \  -d '{    "ids": [      "5f2a9c1e7b3d4a6e8c0f1b2d",      "000000000000000000000000",      "5f2a9c1e7b3d4a6e8c0f9999"    ],    "fields": [      "email"    ]  }'
Response200 OK
{  "ok": true,  "data": {    "results": [      {        "id": "5f2a9c1e7b3d4a6e8c0f1b2d",        "status": "ok",        "person": {          "id": "5f2a9c1e7b3d4a6e8c0f1b2d",          "slug": "jane-doe-acme-corp-1b2d",          "first_name": "Jane",          "last_name": "Doe",          "full_name": "Jane Doe",          "title": "VP of Sales",          "seniority": "vp",          "functions": [            "sales"          ],          "company": {            "name": "Acme Corp",            "slug": "acme-corp"          },          "location": {            "city": "Chicago",            "state": "Illinois",            "country": "United States"          },          "linkedin_url": "https://www.linkedin.com/in/janedoe-example",          "contact": {            "email": {              "available": true,              "status": "verified",              "domain": "acme.com",              "value": "jane.doe@acme.com"            },            "phone": {              "available": true,              "value": "+1 312-555-0147"            }          },          "tier": "premium",          "profile_url": "https://buyrealclients.com/people/jane-doe-acme-corp-1b2d"        },        "credits_spent": 1,        "results": {          "email": {            "source": "vault",            "credits_spent": 1          }        }      },      {        "id": "000000000000000000000000",        "status": "error",        "error": {          "code": "NOT_FOUND",          "message": "No person found with that id or slug"        }      },      {        "id": "5f2a9c1e7b3d4a6e8c0f9999",        "status": "skipped",        "reason": "INSUFFICIENT_CREDITS"      }    ],    "totals": {      "requested": 3,      "succeeded": 1,      "failed": 1,      "skipped": 1,      "credits_spent": 1,      "balance": 0    }  }}
POST/api/v1/enrichFree to match, credits only with reveal

Enrich a record

Match one of your own records to a person. A LinkedIn URL is an exact lookup. Otherwise the name is searched and scored against the company and the email domain.

  • Only matches with match_confidence of 0.75 or higher are returned. Anything weaker is 404 NO_MATCH, so a wrong person is never charged to you.
  • A name on its own is never enough. Add company or a work email (it is used for its domain, and for a first.last name if you send no name). The email address is not stored.
  • With reveal: true the match's available fields are revealed and charged like /reveal. Fields the person has no data for are skipped without a charge.

JSON body

NameTypeDescription
linkedin_urlstringExact LinkedIn profile URL. Highest confidence.
first_name / last_namestringName of the person. Or send full_name.
companystringCurrent company. Legal suffixes like Inc and LLC are ignored.
emailstringWork email; only its domain (and first.last name) is used.
revealbooleanReveal and charge the match's contact fields.Default false
reveal_fieldsstring[]With reveal: which fields to reveal.Default ["email","phone"]
Requestbash
curl -X POST https://buyrealclients.com/api/v1/enrich \  -H "Authorization: Bearer $BRC_API_KEY" \  -H "Content-Type: application/json" \  -d '{    "first_name": "Jane",    "last_name": "Doe",    "company": "Acme Corp",    "reveal": false  }'
Response200 OK
{  "ok": true,  "data": {    "match_confidence": 0.94,    "matched_on": [      "name",      "company",      "email_domain"    ],    "person": {      "id": "5f2a9c1e7b3d4a6e8c0f1b2d",      "slug": "jane-doe-acme-corp-1b2d",      "first_name": "Jane",      "last_name": "Doe",      "full_name": "Jane Doe",      "title": "VP of Sales",      "seniority": "vp",      "functions": [        "sales"      ],      "company": {        "name": "Acme Corp",        "slug": "acme-corp"      },      "location": {        "city": "Chicago",        "state": "Illinois",        "country": "United States"      },      "linkedin_url": "https://www.linkedin.com/in/janedoe-example",      "contact": {        "email": {          "available": true,          "status": "verified",          "domain": "acme.com"        },        "phone": {          "available": true        }      },      "tier": "premium",      "profile_url": "https://buyrealclients.com/people/jane-doe-acme-corp-1b2d"    },    "credits": {      "spent": 0,      "balance": 1998    }  }}
GET/api/v1/suggestFree

Suggest filter values

Typeahead for the values that search filters expect. Returns up to 10 items.

Query parameters

NameTypeDescription
kindrequiredstringtitles, companies or locations.
qstringThe prefix typed so far.
Requestbash
curl -G https://buyrealclients.com/api/v1/suggest \  -H "Authorization: Bearer $BRC_API_KEY" \  --data-urlencode "kind=titles" \  --data-urlencode "q=vp sal"
Response200 OK
{  "ok": true,  "data": {    "kind": "titles",    "items": [      {        "value": "vp sales",        "label": "VP Sales",        "count": 18234      },      {        "value": "vice president of sales",        "label": "Vice President Of Sales",        "count": 9120      }    ]  }}
GET/api/v1/accountFree

Account and limits

Your plan, credit balance, rate and reveal limits, and counters for the key you are calling with.

Requestbash
curl https://buyrealclients.com/api/v1/account \  -H "Authorization: Bearer $BRC_API_KEY"
Response200 OK
{  "ok": true,  "data": {    "plan": {      "id": "pro",      "name": "Pro"    },    "credits": {      "balance": 1998,      "monthly_allowance": 2000,      "cost_per_reveal": 1    },    "limits": {      "requests_per_minute": 60,      "reveals_per_minute": 60,      "reveals_per_day": 2000,      "reveals_today": 2,      "max_search_results": 5000,      "max_page_size": 100,      "batch_reveal_max_ids": 25    },    "api_key": {      "id": "b1f0c5e2-0a7d-4e9a-9f43-2d8c5a1e7c10",      "name": "Production",      "prefix": "brc_live_Ab3",      "created_at": "2026-10-01T09:12:44.000Z",      "last_used_at": "2026-10-11T08:30:02.000Z",      "request_count": 1542    },    "user": {      "id": "809482b5-9ec3-4469-beeb-8ab1b3b4a3c2",      "email": "you@company.com"    }  }}
GET/api/v1/usageFree

Usage

Reveals and credits spent through the API per UTC day. Days without activity are included as zeros.

Query parameters

NameTypeDescription
daysinteger1 to 90 days, ending today.Default 30
Requestbash
curl -G https://buyrealclients.com/api/v1/usage \  -H "Authorization: Bearer $BRC_API_KEY" \  --data-urlencode "days=3"
Response200 OK
{  "ok": true,  "data": {    "period": {      "from": "2026-10-09",      "to": "2026-10-11",      "days": 3    },    "totals": {      "reveals": 14,      "credits_spent": 14    },    "daily": [      {        "date": "2026-10-09",        "reveals": 0,        "credits_spent": 0      },      {        "date": "2026-10-10",        "reveals": 9,        "credits_spent": 9      },      {        "date": "2026-10-11",        "reveals": 5,        "credits_spent": 5      }    ]  }}
GET/api/v1/openapi.jsonFree, no key

The OpenAPI 3.1 description of this API. Import it into Postman, Insomnia or a code generator. Download openapi.json.

Errors

Failed calls return the error envelope with the HTTP status below. Codes are stable; messages may be reworded.

HTTPCodeMeaning
400VALIDATION_ERRORA parameter or body field is invalid. details.issues lists each problem by path.
400INVALID_JSONThe request body is not valid JSON.
400INSUFFICIENT_INPUTEnrich could not derive a first and last name from the input.
401INVALID_API_KEYThe key is missing, malformed, unknown or revoked.
402INSUFFICIENT_CREDITSNot enough credits for the reveal. Nothing was charged. Buy credits or wait for your monthly grant.
403PLAN_REQUIREDThe key is valid but the account's plan has no API access (Pro and Team only).
404NOT_FOUNDNo person with that id or slug.
404NO_DATAThe person has no email or phone of that kind on file. You were not charged.
404NO_MATCHEnrich found no match at or above the confidence threshold.
429RATE_LIMITEDToo many requests or reveals per minute. Wait Retry-After seconds.
429DAILY_LIMITDaily reveal cap for your plan reached. Resets at 00:00 UTC.
500INTERNAL_ERRORUnexpected error. Retry; if it persists contact support with the X-Request-Id.
503VAULT_UNAVAILABLEContact data is temporarily unavailable. You were not charged. Retry shortly.

SDK snippets

There is no official SDK yet. These small clients handle auth, the response envelope and waiting out a 429 using Retry-After. Copy them into your project.

Node.js (18+)
brc.mjsjavascript
// brc.mjs: minimal client that waits and retries when rate limitedconst BASE = "https://buyrealclients.com/api/v1";export async function brc(path, { method = "GET", query = {}, body } = {}) {  const url = new URL(BASE + path);  for (const [key, value] of Object.entries(query)) {    for (const item of [].concat(value)) url.searchParams.append(key, String(item));  }  for (let attempt = 0; attempt < 4; attempt++) {    const res = await fetch(url, {      method,      headers: {        Authorization: `Bearer ${process.env.BRC_API_KEY}`,        "Content-Type": "application/json",      },      body: body ? JSON.stringify(body) : undefined,    });    if (res.status === 429) {      const wait = Number(res.headers.get("Retry-After") ?? 1);      await new Promise((r) => setTimeout(r, wait * 1000));      continue;    }    const json = await res.json();    if (!json.ok) {      throw Object.assign(new Error(json.error.message), { code: json.error.code, status: res.status });    }    return json.data;  }  throw new Error("Still rate limited after 4 attempts");}// const { results } = await brc("/people/search", { query: { q: "cto", has_email: true } });// const { person } = await brc(`/people/${results[0].id}/reveal`, { method: "POST", body: { fields: ["email"] } });
Python 3 (requests)
brc.pypython
# brc.py: minimal client that waits and retries when rate limitedimport osimport timeimport requestsBASE = "https://buyrealclients.com/api/v1"class BrcError(Exception):    def __init__(self, code, message, status):        super().__init__(f"{code}: {message}")        self.code, self.status = code, statusdef brc(path, method="GET", params=None, json=None):    for _ in range(4):        res = requests.request(            method,            BASE + path,            params=params,            json=json,            headers={"Authorization": f"Bearer {os.environ['BRC_API_KEY']}"},            timeout=30,        )        if res.status_code == 429:            time.sleep(int(res.headers.get("Retry-After", 1)))            continue        body = res.json()        if not body["ok"]:            raise BrcError(body["error"]["code"], body["error"]["message"], res.status_code)        return body["data"]    raise RuntimeError("Still rate limited after 4 attempts")# people = brc("/people/search", params={"q": "cto", "has_email": "true"})["results"]# person = brc(f"/people/{people[0]['id']}/reveal", "POST", json={"fields": ["email"]})["person"]

Changelog

  1. v1

    Initial release

    People search and lookup, single and batch reveal, enrich, suggestions, account and usage, with Bearer auth, per-key rate limits, CORS and an OpenAPI 3.1 description.

Versioning. The version is in the path (/api/v1). Within v1 we only make backwards-compatible changes: new endpoints, new optional parameters and new response fields. Write your parser to ignore fields it does not know. Breaking changes ship as /api/v2, with v1 kept running for at least 12 months after v2 launches.