REST API reference | OpsBlu Docs

REST API reference

Live, enriched data on US local businesses. Version 1.0.0. Download the OpenAPI 3.1 spec.

Aggregates are free and never return names, IDs or coordinates. Record-level endpoints bill prepaid credits: 3 credits ($0.03) per standard record, 10 credits ($0.10) per hot record (new or changed in the last 30 days), charged once per unique record per calendar month. Paid responses include `credits_used` and `balance_remaining`. Over-rate requests answer 429 with `{"error":"slow_down","retry_after":N}`.

Conventions

  • Base URL https://opsblu.com. All paths are under /v1. JSON in, JSON out (exports download CSV).
  • Auth: Authorization: Bearer ob_live_…. Endpoints marked public need no credential.
  • Slugs are lowercase-hyphenated: oregon, portland, hvac-contractors. GET /v1/categories is the vocabulary.
  • Booleans in query strings accept true/false or 1/0.
  • Aggregate counts under 5 are the string "<5" (type Count). Treat it as "some, fewer than five".
  • Timestamps are RFC 3339 UTC.

Try it: free endpoints work in your terminal right now. For paid endpoints, create a key at /app/api-keys; your first key adds 750 free credits.

Aggregates

Free. Counts only, small counts rendered as "<5".

GET /v1/coverage public

Collection-wide counters and covered cities

Responses

CodeDescriptionBody
200 OK Coverage
curlbash
curl \
  "https://opsblu.com/v1/coverage"

GET /v1/stats public

Aggregate stats for a state, city or city × category

Parameters

NameInTypeDescription
state query string
city query string
category query string

Responses

CodeDescriptionBody
200 OK Stats
404 Not found Error
curlbash
curl \
  "https://opsblu.com/v1/stats?state=oregon&city=portland&category=dentists"

POST /v1/stats/polygon public

Aggregate stats inside a drawn boundary

The polygon is snapped to H3 cells server-side. Minimum area ~0.5 km². Hex counts under 5 come back as "<5".

Request body application/json, required

FieldTypeDescription
geojsonrequired object
categories string[]
persona "web" | "seo" | "ppc" | "opening"

Responses

CodeDescriptionBody
200 OK Stats
curlbash
curl -X POST \
  -H "Content-Type: application/json" -d '{"geojson":{},"categories":[],"persona":"web"}' \
  "https://opsblu.com/v1/stats/polygon"

GET /v1/categories public

Controlled category vocabulary with national counts

Responses

CodeDescriptionBody
200 OK object
curlbash
curl \
  "https://opsblu.com/v1/categories"

Businesses

Search is free (names + signals). Opening a record bills credits.

GET /v1/businesses

Search businesses (free: names + signals, no contacts)

Parameters

NameInTypeDescription
state query string
city query string
zip query string
category query string
q query string Name contains
no_website query boolean
cwv_fail query boolean
platform query "wordpress" | "wix" | "squarespace" | "shopify" | "other"
has_ads query boolean
has_analytics query boolean
server_side query boolean
new_days query integer
changed_days query integer
has_phone query boolean
has_email query boolean
hot query boolean
cursor query string
limit query integerdefault 25

Responses

CodeDescriptionBody
200 OK BusinessPage
429 Rate limited. Back off for retry_after seconds. Error
curlbash
curl -H "Authorization: Bearer ob_live_YOUR_KEY" \
  "https://opsblu.com/v1/businesses?state=oregon&city=portland&zip=97201"

GET /v1/businesses/{id}

Open a full record (billed once per month)

Parameters

NameInTypeDescription
idrequired path string

Responses

CodeDescriptionBody
200 OK object
401 Sign in or pass an API key Error
402 Insufficient credits or spend cap reached Error
404 Not found Error
curlbash
curl -H "Authorization: Bearer ob_live_YOUR_KEY" \
  "https://opsblu.com/v1/businesses/ob_por_den_0007"

Changes

What changed in a territory since a timestamp.

GET /v1/changes

Change events since a timestamp

Parameters

NameInTypeDescription
since query string (date-time) Default: 7 days ago
territory_id query string
types query string Comma list: new_business, site_launched, platform_changed, pixel_added, pixel_removed, closed
state query string
city query string
category query string
limit query integerdefault 200

Responses

CodeDescriptionBody
200 OK object
curlbash
curl -H "Authorization: Bearer ob_live_YOUR_KEY" \
  "https://opsblu.com/v1/changes?since=2026-10-21T00:00:00Z&territory_id=ter_3a…&types=new_business"

Exports

Two-step: create (estimate) then confirm (charge).

GET /v1/exports

List exports

Responses

CodeDescriptionBody
200 OK object
curlbash
curl -H "Authorization: Bearer ob_live_YOUR_KEY" \
  "https://opsblu.com/v1/exports"

POST /v1/exports

Create an export and get a credit estimate (nothing charged yet)

Request body application/json, required

FieldTypeDescription
filters Filters
ids string[]

Responses

CodeDescriptionBody
201 Created, status pending_confirm Export
curlbash
curl -X POST -H "Authorization: Bearer ob_live_YOUR_KEY" \
  -H "Content-Type: application/json" -d '{"filters":{},"ids":[]}' \
  "https://opsblu.com/v1/exports"

GET /v1/exports/{id}

Get an export

Parameters

NameInTypeDescription
idrequired path string

Responses

CodeDescriptionBody
200 OK Export
curlbash
curl -H "Authorization: Bearer ob_live_YOUR_KEY" \
  "https://opsblu.com/v1/exports/ob_por_den_0007"

POST /v1/exports/{id}/confirm

Confirm and charge; makes the CSV available

Parameters

NameInTypeDescription
idrequired path string

Responses

CodeDescriptionBody
200 Ready Export
402 Insufficient credits or spend cap reached Error
curlbash
curl -X POST -H "Authorization: Bearer ob_live_YOUR_KEY" \
  "https://opsblu.com/v1/exports/ob_por_den_0007/confirm"

GET /v1/exports/{id}/download

Download CSV

Parameters

NameInTypeDescription
idrequired path string

Responses

CodeDescriptionBody
200 CSV text/csv
curlbash
curl -H "Authorization: Bearer ob_live_YOUR_KEY" \
  "https://opsblu.com/v1/exports/ob_por_den_0007/download"

Tools

Report card, removal requests, sample pages.

POST /v1/report-card public

Score a business website

Request body application/json, required

FieldTypeDescription
url string
business string
city string

Responses

CodeDescriptionBody
201 Created object
curlbash
curl -X POST \
  -H "Content-Type: application/json" -d '{"url":"https://example.com","business":"","city":"portland"}' \
  "https://opsblu.com/v1/report-card"

GET /v1/report-card/{id} public

Get a report card

Parameters

NameInTypeDescription
idrequired path string

Responses

CodeDescriptionBody
200 OK ReportCard
curlbash
curl \
  "https://opsblu.com/v1/report-card/ob_por_den_0007"

POST /v1/removal-requests public

Ask us to remove a business

Request body application/json, required

FieldTypeDescription
business_namerequired string
domain string
address string
requester_emailrequired string (email)
relationship "owner" | "employee" | "other"

Responses

CodeDescriptionBody
201 Ticket RemovalRequest
curlbash
curl -X POST \
  -H "Content-Type: application/json" -d '{"business_name":"Alder Street Dental","domain":"example.com","address":"","requester_email":"owner@example.com"}' \
  "https://opsblu.com/v1/removal-requests"

GET /v1/samples/{token} public

Outreach sample page payload (noindex)

Parameters

NameInTypeDescription
tokenrequired path string

Responses

CodeDescriptionBody
200 OK
410 Expired
curlbash
curl \
  "https://opsblu.com/v1/samples/demo"

Account

Credits, billing, keys, territories.

GET /v1/me

Current account and balance

Responses

CodeDescriptionBody
200 OK Account
curlbash
curl -H "Authorization: Bearer ob_live_YOUR_KEY" \
  "https://opsblu.com/v1/me"

POST /v1/me/connect-bonus

Claim the +750 connect bonus (MCP/API/TagFrog)

Request body application/json

FieldTypeDescription
source "mcp" | "api" | "tagfrog"

Responses

CodeDescriptionBody
200 OK Account
409 Already granted
curlbash
curl -X POST -H "Authorization: Bearer ob_live_YOUR_KEY" \
  -H "Content-Type: application/json" -d '{"source":"mcp"}' \
  "https://opsblu.com/v1/me/connect-bonus"

POST /v1/billing/topup

Start a Stripe Checkout top-up

Request body application/json, required

FieldTypeDescription
amountrequired number

Responses

CodeDescriptionBody
200 OK object
curlbash
curl -X POST -H "Authorization: Bearer ob_live_YOUR_KEY" \
  -H "Content-Type: application/json" -d '{"amount":20}' \
  "https://opsblu.com/v1/billing/topup"

PUT /v1/billing/spend-cap

Set the monthly spend cap

Request body application/json, required

FieldTypeDescription
monthly_usd number

Responses

CodeDescriptionBody
200 OK Account
curlbash
curl -X PUT -H "Authorization: Bearer ob_live_YOUR_KEY" \
  -H "Content-Type: application/json" -d '{"monthly_usd":20}' \
  "https://opsblu.com/v1/billing/spend-cap"

GET /v1/billing/ledger

Credit ledger

Responses

CodeDescriptionBody
200 OK object
curlbash
curl -H "Authorization: Bearer ob_live_YOUR_KEY" \
  "https://opsblu.com/v1/billing/ledger"

GET /v1/keys

List keys

Responses

CodeDescriptionBody
200 OK
curlbash
curl -H "Authorization: Bearer ob_live_YOUR_KEY" \
  "https://opsblu.com/v1/keys"

POST /v1/keys

Create an API key (secret shown once)

Request body application/json

FieldTypeDescription
label string
spend_cap number

Responses

CodeDescriptionBody
201 Created APIKey
curlbash
curl -X POST -H "Authorization: Bearer ob_live_YOUR_KEY" \
  -H "Content-Type: application/json" -d '{"label":"claude-desktop","spend_cap":20}' \
  "https://opsblu.com/v1/keys"

DELETE /v1/keys/{id}

Revoke a key

Parameters

NameInTypeDescription
idrequired path string

Responses

CodeDescriptionBody
204 Revoked
curlbash
curl -X DELETE -H "Authorization: Bearer ob_live_YOUR_KEY" \
  "https://opsblu.com/v1/keys/ob_por_den_0007"

GET /v1/territories

List territories

Responses

CodeDescriptionBody
200 OK
curlbash
curl -H "Authorization: Bearer ob_live_YOUR_KEY" \
  "https://opsblu.com/v1/territories"

POST /v1/territories

Save a territory

Request body application/json, required

FieldTypeDescription
id string
name string
kind "city" | "zip" | "polygon"
state string
city string
zip string
geojson object
alerts object

Responses

CodeDescriptionBody
201 Created
curlbash
curl -X POST -H "Authorization: Bearer ob_live_YOUR_KEY" \
  -H "Content-Type: application/json" -d '{"id":"","name":"Portland metro","kind":"city","state":"oregon"}' \
  "https://opsblu.com/v1/territories"

GET /v1/territories/{id}

Get a territory

Parameters

NameInTypeDescription
idrequired path string

Responses

CodeDescriptionBody
200 OK
curlbash
curl -H "Authorization: Bearer ob_live_YOUR_KEY" \
  "https://opsblu.com/v1/territories/ob_por_den_0007"

PUT /v1/territories/{id}

Update a territory / alerts

Parameters

NameInTypeDescription
idrequired path string

Responses

CodeDescriptionBody
200 OK
curlbash
curl -X PUT -H "Authorization: Bearer ob_live_YOUR_KEY" \
  "https://opsblu.com/v1/territories/ob_por_den_0007"

DELETE /v1/territories/{id}

Delete a territory

Parameters

NameInTypeDescription
idrequired path string

Responses

CodeDescriptionBody
204 Deleted
curlbash
curl -X DELETE -H "Authorization: Bearer ob_live_YOUR_KEY" \
  "https://opsblu.com/v1/territories/ob_por_den_0007"

Schemas

Shapes referenced above. Count is either an integer or the string "<5": small-count suppression protects individual businesses in aggregate views.

Count

Counts under 5 are suppressed as "<5".

One of: integer or "<5".

Error

PropertyTypeDescription
error string
message string
retry_after integer

Coverage

PropertyTypeDescription
businesses_total integer
added_today integer
cities_covered integer
new_this_week integer
updated_at string (date-time)
cities object[]

Depth

PropertyTypeDescription
phones Count
websites Count
emails Count
ads Count
cwv_fail Count
no_website Count
new_90d Count
enriched Count

CategoryCount

PropertyTypeDescription
slug string
name string
count Count

Stats

PropertyTypeDescription
scope string
state string
city string
category string
total Count
depth Depth
categories CategoryCount[]
platforms object<Count>
tracking object<Count>
new_by_month object[]
hexes object[]
suppressed boolean
coverage_complete boolean
updated_at string (date-time)

Signals

PropertyTypeDescription
hot boolean
new_in_days integer
changed object[]
no_website boolean
cwv_fail boolean
ads_no_tracking boolean

BusinessSummary

PropertyTypeDescription
id string
name string
category string
category_slug string
city string
state string
signals Signals
has_phone boolean
has_email boolean
has_website boolean
platform string
revealed boolean

CostEstimate

PropertyTypeDescription
records integer
hot_records integer
already_revealed integer
credits integer
usd number

BusinessPage

PropertyTypeDescription
items BusinessSummary[]
total integer
next_cursor string
estimate CostEstimate

CWV

PropertyTypeDescription
lcp number
cls number
inp number
pass boolean

SEO

PropertyTypeDescription
title boolean
meta boolean
h1 boolean
schema boolean
sitemap boolean
robots boolean

Marketing

PropertyTypeDescription
analytics string[]
ads_platforms string[]
pixels string[]
server_side_tracking boolean
consent_tool string

Business

Full paid record. No reviews, ratings or photos.

PropertyTypeDescription
id string
name string
category string
subcategories string[]
address string
city string
state string
zip string
lat number
lng number
phone string
emails string[]
website string
domain string
socials object<string>
first_seen_at string (date-time)
last_verified_at string (date-time)
status "active" | "closed" | "unknown"
web object object with has_website, platform, cwv, seo, ssl_issued_at
marketing Marketing
signals Signals

Filters

PropertyTypeDescription
state string
city string
zip string
category string
q string
no_website boolean
cwv_fail boolean
platform string
has_ads boolean
has_analytics boolean
server_side boolean
new_days integer
changed_days integer
has_phone boolean
has_email boolean
hot boolean
territory_id string

ChangeEvent

PropertyTypeDescription
id string
type string
at string (date-time)
business BusinessSummary

Export

PropertyTypeDescription
export_id string
status "pending_confirm" | "ready" | "expired"
filters Filters
ids string[]
estimate CostEstimate
estimated_credits integer
credits_used integer
rows integer
format string
download_url string
created_at string (date-time)
confirmed_at string (date-time)

ReportCard

PropertyTypeDescription
id string
url string
domain string
status string
cwv_mobile CWV
cwv_desktop CWV
seo SEO
platform string
tech_stack string[]
marketing Marketing
tracking_health object object with score, issues
comparison object object with category, zip, peer_count, peer_cwv_pass_rate, peer_ads_rate, peer_server_side_rate

RemovalRequest

PropertyTypeDescription
ticket_id string
business_name string
domain string
requester_email string
relationship string
status string
created_at string (date-time)
applies_by string (date-time)

Account

PropertyTypeDescription
id string
email string
domain string
business_email boolean
credits_balance integer 1 credit = $0.01
free_credits integer
free_credits_expire_at string (date-time)
spend_cap number USD per month, 0 = none
spent_this_month_usd number
connect_bonus_granted boolean
created_at string (date-time)

LedgerEntry

PropertyTypeDescription
id string
at string (date-time)
type "grant" | "topup" | "reveal" | "export" | "expiry" | "adjustment"
credits integer
balance_after integer
note string
ref_id string

APIKey

PropertyTypeDescription
id string
label string
prefix string
secret string Only returned on create
spend_cap number
created_at string (date-time)
last_used_at string (date-time)
revoked boolean

Territory

PropertyTypeDescription
id string
name string
kind "city" | "zip" | "polygon"
state string
city string
zip string
geojson object
alerts object object with email, slack_webhook, webhook, types, cadence