Developer documentation · REST / npm / MCP

Business records for your code and AI agents.

Discover available data for free, choose an interface, then make a small, intentional pull. Start here before creating a key or spending credits.

Looking for bidders for a construction project? Real estate developers & PMs →

Two interfaces. Separate keys and balances.

MULTIPLE INDUSTRIES

Roster Engine

REST API and npm SDK for business records across contractors, healthcare, retail, transport and more.

Base URL
/api/re/v1
Authentication & billing
X-API-Key: re_live_…
Credits per returned record.
Start with REST or npm ↓

CONTRACTOR SEARCH

Contractor MCP + REST

Search by state, trade, and city or ZIP. Use MCP tools in a compatible AI client, or call REST directly.

Endpoints
/api/mcp · /api/v1
Authentication & billing
Bearer cr_live_…
Separate prepaid dollar balance.
Connect with MCP ↓

A key for one family will not authenticate the other. The contractor OpenAPI reference does not describe Roster Engine.

1. Discover the data. No key, no charge.

This Roster Engine request returns a coverage snapshot and the current rate card. It does not retrieve paid records.

Terminal · free discovery
curl --fail-with-body https://contractorroster.com/api/re/v1/rosters

Read rosters for coverage, rates for credit costs and packs, and stats_updated_at for the snapshot age. Counts are not a live availability guarantee.

Prefer JavaScript? Free npm example
Node.js 18+ · ES module (.mjs)
// npm install roster-engine
// Node.js 18+, in an ES module (.mjs)
import RosterEngine from "roster-engine";

const engine = new RosterEngine();
const catalog = await engine.rosters(); // Free. No key needed.
console.log(catalog.rosters, catalog.rates, catalog.stats_updated_at);
Package on npm ↗

Shell examples use POSIX syntax. On Windows, use WSL/Git Bash or translate them to PowerShell.

2. Create and store your Roster Engine key.

When you are ready to pull records, replace the example email with your own and run this once. New keys start with zero credits. Discovery is free; retrieving records requires a funded balance.

Terminal · creates a key, does not pull records
curl --fail-with-body https://contractorroster.com/api/re/v1/keys \
  -H 'Content-Type: application/json' \
  --data '{"email":"[email protected]"}'

The response contains api_key and free_credits: 0. Save the key immediately in a secret manager or server environment as ROSTER_ENGINE_API_KEY. It is returned once; never put it in browser code, a URL, a public repository or an agent prompt.

Already have a key? Skip this step. A 409 means that email already has a key; recover your saved key or contact us.

3. Fund your key, then pull one record.

Request a checkout URL with POST /api/re/v1/topup, your X-API-Key header and {"pack_usd":10}. Complete payment at the returned checkout_url, then confirm credits with GET /api/re/v1/balance. A zero-balance key receives 402 on record requests.

This example requests at most one California contractor with both phone and email and a stored licensed classification. It spends up to 5 credits at the current rate. An empty result is possible.

Terminal · metered GET, not a free preview
# Metered: up to 1 record, up to 5 credits at the current rate.
# Set ROSTER_ENGINE_API_KEY privately in your server environment first.
curl --fail-with-body \
  'https://contractorroster.com/api/re/v1/rosters/contractors/leads?state=CA&has_both=true&min_verification=licensed&limit=1' \
  -H "X-API-Key: $ROSTER_ENGINE_API_KEY"

Read records, pull_id, credits_charged.total and balance_remaining from the response. A returned cursor lets you request another page; that page is another metered call.

Know the cost before you continue

Current rates: 1 credit for record-only, 3 for one contact type, 5 for both. Contact-bearing records are the default. Packs start at $10 for 500 credits; check discovery for current rates.

Roster Engine has no dry-run mode. A leads GET spends credits. Adding dry_run=true does not make it free. Repeating a pull can charge again.

Roster Engine reference

Base: https://contractorroster.com/api/re/v1

GET /rosters
No key. Free catalog, coverage snapshot and current credit rates.
POST /keys
No key. Creates a key; JSON body: {"email":"[email protected]"}. Returned once with free_credits: 0. Fund the key before retrieving records.
GET /balance
X-API-Key. Free balance check: credits and spend_lifetime.
GET /rosters/{roster}/leads
X-API-Key. Metered records. Always set an explicit limit (1–500). Default: 50.
POST /topup
X-API-Key. JSON body: {"pack_usd":10}. Returns a checkout_url; a person completes payment.

Filters on a metered pull

state / city / zip / zip_prefix
Geography; use a two-letter state code.
has_both / has_email / has_phone
Set true to require the selected contact fields. has_both=true requires both.
min_verification
directory, public_record_seed, registered, or licensed. A stored source classification, not a fresh license check.
min_rating
Minimum stored rating, when available.
has_contact
Contact-bearing rows are the default. Use any to also allow record-only rows.
limit / cursor
1–500 records per call. Continue with the returned cursor and the same filters; each page is metered.

Roster IDs: contractors, dentists, chiropractors, restaurants, retail, carriers, towing, movers, home_health, care_facilities. Check discovery for geographic coverage.

Connect an AI agent with MCP.

For the contractor interface, add a Streamable HTTP MCP server at https://contractorroster.com/api/mcp. This is the cr_live_ key family, not Roster Engine.

  1. Start with free list_states and list_trades discovery. Use count_contractors for a free estimate.
  2. For paid searches, request a contractor key and configure Authorization: Bearer with that key in your client’s secret settings.
  3. Preview with search_contractors and dry_run: true. Get the owner’s approval before making a paid search or topping up.

Using an agent that calls REST directly? Give it the plain-text integration guide. It contains the same starter examples and the spending boundaries.

Opt-outs and your own exclusion lists

Business opt-outs recorded by ContractorRoster are applied automatically to paid API contact results. Records excluded by that check are not charged. A failed policy check stops delivery.

Your own exclusion list is different: it can help you avoid buying contacts you already hold. Customer-supplied lists are not yet supported by Roster Engine REST/npm or contractor REST/MCP. Do not invent exclusion parameters or assume they will be honored.

For a website list order, use the list builder's exclusion-file option before checkout. Filtering API results in your own application happens after purchase and does not reduce the charge.

Keep customer lists out of URLs, agent conversations and support messages. An exclusion list does not establish permission to contact the remaining businesses.

Use the website list builder →

Before you put this in production

  • Roster Engine leads GET requests spend credits. There is no dry_run mode on that endpoint. Do not add dry_run and assume a request is free.
  • Use an explicit small limit and check the balance. At current rates, reserve up to 5 credits per requested record. Do not automatically retry an uncertain metered request: repeat pulls can charge again.
  • In npm roster-engine 0.1.0, pullAll checks maxCredits after charging a page. It is not a strict pre-charge spending ceiling; use individually bounded pulls for budget control.
  • Contractor MCP count_contractors is a free estimate; search_contractors supports dry_run:true. A paid search requires separate approval. Availability may change between preview and purchase.
  • Preserve source, source_id, verification and verified_at where returned. Contact enrichment has its own contact_source. Do not claim every record is licensed or checked in real time.

Handle errors explicitly

  • 401 — Check the key family and authentication header.
  • 402 — Insufficient balance. Ask the owner before topping up.
  • 429 — Back off. Roster Engine discovery is currently 30/min/IP; pulls are 60/min/IP; key creation is 5/hour/IP.
  • 503 or a non-JSON gateway response — Unavailable, not “no matches.” Reconcile uncertain metered requests before retrying.

Need help? [email protected]. Include the HTTP status and a pull ID if available. Do not send your key or customer records.