Authentication

All API requests require an API key sent via the X-API-Key header. Keys are provisioned after your access request is approved.

// Every request must include your API key
curl -X POST https://yourcrowdomain.com/api/v1/search \
  -H "Content-Type: application/json" \
  -H "X-API-Key: crw_live_YOUR_API_KEY" \
  -d '{"name": "Jane Smith", "city": "Austin", "state": "TX"}'

API keys follow the format crw_live_XXXXXXXX. Keep your key secret. If compromised, contact us immediately to revoke and reissue.

Authentication Flow

Here is how API key authentication works end-to-end:

+----------------+       +------------------+       +----------------+
|  Your Platform |       |    CROW API      |       |  ODIN Backend  |
+-------+--------+       +--------+---------+       +-------+--------+
        |                          |                         |
        |  1. POST /api/v1/search  |                         |
        |  X-API-Key: crw_live_... |                         |
        |------------------------->|                         |
        |                          |                         |
        |                          |  2. Validate key        |
        |                          |     Check rate limit    |
        |                          |     Check scopes        |
        |                          |                         |
        |  3. 200 OK (preview)     |                         |
        |<-------------------------|                         |
        |                          |                         |
        |  4. POST /api/v1/report  |                         |
        |  X-API-Key: crw_live_... |                         |
        |------------------------->|                         |
        |                          |  5. Fire intelligence   |
        |                          |     request             |
        |                          |------------------------>|
        |  6. 202 Accepted         |                         |
        |     { reference: "..." } |                         |
        |<-------------------------|                         |
        |                          |                         |
        |                          |  7. Report completed    |
        |                          |<------------------------|
        |                          |                         |
        |  8. Webhook POST         |                         |
        |  (if callback_url set)   |                         |
        |<-------------------------|                         |
        |                          |                         |

All requests are authenticated via the X-API-Key header. No session tokens, cookies, or OAuth flows required.

Rate Limits

Rate limits are enforced per API key. The following tiers apply:

TierDaily LimitBurst (per min)Cost
Starter100 requests20Free with API key
Growth1,000 requests60$199/mo
Enterprise10,000 requests200Custom
Rate limit headers are included in every response: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset.

When the limit is exceeded, you receive a 429 response:

{
  "error": "Rate limit exceeded",
  "daily_limit": 100,
  "remaining": 0,
  "reset": "2026-03-27T23:59:59Z",
  "message": "You have exceeded 100 requests/day. Resets at midnight UTC.",
  "upgrade_url": "https://crowsearch.com/enterprise.html"
}

Try It Live

Test the search endpoint directly from this page. Enter your API key and a subject name to see a live response.

Interactive API Tester

Code Examples

Quick integration snippets for popular languages:

cURL

curl -X POST https://crowsearch.com/api/v1/search \
  -H "Content-Type: application/json" \
  -H "X-API-Key: crw_live_YOUR_API_KEY" \
  -d '{"name": "Jane Smith", "city": "Austin", "state": "TX"}'

Python

import requests

response = requests.post(
    "https://crowsearch.com/api/v1/search",
    headers={
        "Content-Type": "application/json",
        "X-API-Key": "crw_live_YOUR_API_KEY",
    },
    json={
        "name": "Jane Smith",
        "city": "Austin",
        "state": "TX",
    },
)

data = response.json()
print(f"Records found: {data['preview']['records_found']}")
print(f"Categories: {', '.join(data['preview']['categories'])}")

Node.js

const response = await fetch("https://crowsearch.com/api/v1/search", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-API-Key": "crw_live_YOUR_API_KEY",
  },
  body: JSON.stringify({
    name: "Jane Smith",
    city: "Austin",
    state: "TX",
  }),
});

const data = await response.json();
console.log(`Records found: ${data.preview.records_found}`);
console.log(`Categories: ${data.preview.categories.join(", ")}`);

Ruby

require "net/http"
require "json"
require "uri"

uri = URI("https://crowsearch.com/api/v1/search")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Post.new(uri)
request["Content-Type"] = "application/json"
request["X-API-Key"] = "crw_live_YOUR_API_KEY"
request.body = {
  name: "Jane Smith",
  city: "Austin",
  state: "TX"
}.to_json

response = http.request(request)
data = JSON.parse(response.body)
puts "Records found: #{data['preview']['records_found']}"
puts "Categories: #{data['preview']['categories'].join(', ')}"

POST /api/v1/report

Order a full CROW background intelligence report. Reports are generated asynchronously via our ODIN intelligence backend. You'll receive a reference ID to poll for status, or provide a callback_url to receive a webhook when complete.

Request Body

FieldTypeRequiredDescription
namestringYesFull name of the subject
citystringNoCity to narrow results
statestringNoTwo-letter state code
tierstringNobrief, plus, or relationship. Default: brief
callback_urlstringNoWebhook URL for delivery notification

Example Request

curl -X POST https://yourcrowdomain.com/api/v1/report \
  -H "Content-Type: application/json" \
  -H "X-API-Key: crw_live_YOUR_API_KEY" \
  -d '{
    "name": "Jane Smith",
    "city": "Austin",
    "state": "TX",
    "tier": "plus",
    "callback_url": "https://yourplatform.com/webhooks/crow"
  }'

Example Response

{
  "reference": "CRW-A1B2C3D4",
  "status": "processing",
  "tier": "plus",
  "estimated_delivery": "2026-03-31T12:00:00.000Z",
  "status_url": "/api/v1/report/CRW-A1B2C3D4",
  "callback_url": "https://yourplatform.com/webhooks/crow"
}

GET /api/v1/report/:reference

Check the status of a previously ordered report. When the report is delivered, the response will include a secure download URL and password.

Example Request

curl https://yourcrowdomain.com/api/v1/report/CRW-A1B2C3D4 \
  -H "X-API-Key: crw_live_YOUR_API_KEY"

Example Response (Processing)

{
  "reference": "CRW-A1B2C3D4",
  "tier": "plus",
  "status": "analyzing",
  "steps": {
    "received": "2026-03-26T10:00:00.000Z",
    "collecting": "2026-03-26T10:05:00.000Z",
    "analyzing": "2026-03-26T14:00:00.000Z",
    "reviewing": null,
    "delivered": null
  },
  "expected_delivery": "2026-03-31T12:00:00.000Z"
}

Example Response (Delivered)

{
  "reference": "CRW-A1B2C3D4",
  "tier": "plus",
  "status": "delivered",
  "steps": { ... },
  "expected_delivery": "2026-03-31T12:00:00.000Z",
  "report_url": "/api/report/abc123...",
  "report_password": "Kx7mNp"
}

GET /api/v1/usage

Check your API usage statistics for the current billing period.

Example Response

{
  "key": "crw_live_a1b2...x9z0",
  "company": "Acme Lending",
  "total_requests": 847,
  "total_searches": 812,
  "total_reports": 35,
  "today_requests": 14,
  "daily_limit": 100,
  "remaining_today": 86
}

Webhooks

CROW supports two webhook delivery methods:

1. Per-Order Callbacks

Provide a callback_url when ordering a report. CROW will POST to that URL when the report is ready:

{
  "event": "report.completed",
  "reference": "CRW-A1B2C3D4",
  "status": "delivered",
  "report_url": "/api/report/abc123...",
  "delivered_at": "2026-03-28T09:15:00.000Z"
}

2. Registered Partner Endpoints

Partners can register a persistent webhook endpoint via the API. All reports associated with your partner code will trigger webhooks automatically.

POST /api/webhooks/register

{
  "callback_url": "https://yourplatform.com/webhooks/crow",
  "partner_code": "ACME-LAW"
}

// Response
{
  "id": 42,
  "callback_url": "https://yourplatform.com/webhooks/crow",
  "secret": "a1b2c3...signing_secret",
  "message": "Use the secret to verify webhook signatures."
}

Webhook Verification

Every webhook includes an X-Crow-Signature header containing an HMAC-SHA256 signature of the request body, signed with your endpoint secret:

// Verify in Node.js
const crypto = require("crypto");
const signature = req.headers["x-crow-signature"];
const expected = "sha256=" + crypto
  .createHmac("sha256", YOUR_WEBHOOK_SECRET)
  .update(JSON.stringify(req.body))
  .digest("hex");

if (signature !== expected) {
  return res.status(401).send("Invalid signature");
}

Retry Policy

Retry schedule: CROW retries failed webhooks up to 3 times with exponential backoff: 5 seconds, 25 seconds, 125 seconds. Your endpoint must return a 2xx status within 10 seconds.

Delivery Log

Check delivery status for any reference via the API:

GET /api/webhooks/deliveries?reference=CRW-A1B2C3D4
Authorization: Bearer YOUR_JWT_TOKEN

API Pricing

Simple per-use pricing. No monthly minimums. You're billed based on actual usage.

Search

$25

Per search query. Returns preview data and record categories found.

Full Report

$500

Per report, any tier. Complete background intelligence delivered within 2-7 business days.

Volume discounts available for partners processing 50+ reports/month. Contact us to discuss enterprise pricing.

Error Code Reference

All errors follow a consistent JSON structure:

{
  "error": "Human-readable error message",
  "code": "MACHINE_READABLE_CODE",
  "status": 400,
  "requestId": "req_abc123..."
}
StatusCodeDescriptionResolution
400INVALID_PARAMSMissing or invalid request parametersCheck required fields: name is always required
400INVALID_TIERInvalid report tier specifiedUse: brief, plus, or relationship
400INVALID_STATEInvalid US state codeProvide a two-letter state abbreviation (e.g., TX, CA, NY)
401MISSING_API_KEYNo API key providedAdd X-API-Key header to your request
401INVALID_API_KEYAPI key not recognized or revokedVerify your key or request a new one
403SCOPE_DENIEDAPI key lacks permission for this endpointContact us to upgrade key scopes
404NOT_FOUNDReport reference not foundVerify the reference ID is correct
409DUPLICATE_ORDERA report for this subject was recently orderedUse the existing reference or wait before reordering
429RATE_LIMITDaily rate limit exceededWait for reset at midnight UTC or upgrade tier
500INTERNAL_ERRORInternal server errorRetry after a brief delay. If persistent, contact support.
503SERVICE_UNAVAILABLEBackend intelligence service temporarily unavailableRetry with exponential backoff

Request API Access

API access is available to vetted platforms and partners. Tell us about your use case and we'll get back to you within 1 business day.

Get your API key

Your request has been submitted. We'll review your application and reach out within 1 business day with your API credentials.