Docs

RestoSignals API reference

One REST API (plus a hosted MCP server) for restaurants, bars and cafés about to open, scored by opening_score. Base URL https://api.restosignals.com. Try every endpoint live in the interactive Swagger UI.

AuthMeteringErrors OpeningsScoringSignals ExportWebhooksAccount CoverageMCPAgents →
POST /v1/register Mint a trial API key (100 free credits). Free GET /v1/openings Scored, fused venue leads. 1 / lead GET /v1/openings/latest Venues with a signal in the last 7 days. 1 / lead GET /v1/signals Raw pre-fusion signal rows. 1 / row GET /v1/export Bulk CSV of fused venues. 1 / row POST /v1/webhooks Register a new-match alert webhook. Free GET /v1/webhooks List your webhooks. Free DELETE /v1/webhooks/{id} Delete a webhook. Free GET /v1/account Wallet balance, plan, keys. Free GET /v1/usage Usage by endpoint. Free GET /v1/config Public pricing / plans / packs. Free

Authentication

Every call takes an API key (prefix pk_). Create one free (50 lead credits, no card) at /signup, or mint a trial key programmatically:

curl -s -X POST https://api.restosignals.com/v1/register
# -> { "api_key": "pk_...", "credits": 50 }

Send the key on every request in a header — never in the query string (it would leak into logs and proxies). Both of these work:

-H "X-API-Key: pk_YOUR_KEY"
-H "Authorization: Bearer pk_YOUR_KEY"

Metering & credits

Every metered JSON response echoes credits_used and credits_remaining.

Errors

Errors return a JSON body { "detail": "…" } with a standard HTTP status:

StatusMeaning
400Bad request — e.g. a webhook url that isn't http(s).
401Missing or invalid API key.
402Out of credits. Top up or upgrade.
404No such resource (e.g. deleting a webhook you don't own).

GET /v1/openings

The core call — fused, deduped venues ranked by opening_score DESC, then recency.

curl -s "https://api.restosignals.com/v1/openings?state=NY&min_opening_score=40&limit=25" \
  -H "X-API-Key: pk_YOUR_KEY"

Query parameters

ParamTypeDescription
statestringTwo-letter state, e.g. NY. Case-insensitive. Live: NY, TX, IL, OR, CO, WA, CA.
citystringFilter to one city (exact, case-insensitive).
signal_typestringOne of liquor, food_permit, business — venues carrying that signal.
min_opening_scoreintMinimum opening_score 0–100. Default 30.
statusstringpre_opening | opening | stale.
sincestringISO date; venues whose latest signal is on/after it.
limitintMax rows, 1–500. Default 50.
offsetintPagination offset. Default 0.

Response

{
  "count": 2,
  "credits_used": 2,
  "credits_remaining": 48,
  "truncated_by_balance": false,
  "contacts_included": true,           // true on a paid plan; false on the free tier
  "openings": [
    { "id": 4412, "business_name": "DINER 24 BROADWAY NYC LLC.", "dba": null,
      "address": "1674 Broadway", "city": "New York", "state": "NY", "county": null,
      "lat": null, "lng": null, "opening_score": 100, "status": "opening",
      "signal_types": ["business", "food_permit", "liquor"],
      "earliest_signal_date": "2026-06-02", "latest_signal_date": "2026-08-30",
      "contact": {                     // subscriber: revealed. free tier: {locked, available, unlock}
        "owner_name": "Diner 24 Broadway LLC", "phone": "9175781633",
        "email": null, "website": null,
        "owner_address": "1674 Broadway, New York NY 10019" } },
    { "id": 4390, "business_name": "MEDUSA ART STUDIOS & EVENTS", "city": "Astoria",
      "state": "NY", "opening_score": 90, "status": "opening",
      "signal_types": ["food_permit", "liquor"], "…": "…" }
  ]
}

On the free tier contacts_included is false and each contact is { "locked": true, "available": true, "unlock": "Subscribe…" } — so you can see a contact exists before paying. email is reserved for a later tier. Today the contact is the owner name on every venue, a mailing address in Texas and New York, and a phone in New York City, mined from the public filings (coverage widens as we add sources; highest fill on near-open venues).

Venue fields

FieldTypeDescription
idintStable venue id (use with venue_signals in MCP).
business_namestringBest display name across the fused signals.
dbastring | nullDoing-business-as, when present.
address, city, state, countystringNormalized location.
lat, lngnumber | nullCoordinates when the source provides them.
opening_scoreint0–100. Higher = closer to opening / more signals.
statusstringpre_opening, opening, or stale.
signal_typesstring[]Subset of ["liquor","food_permit","business"].
earliest_signal_date, latest_signal_datestring | nullISO dates spanning the evidence.
contactobjectPaid: {owner_name, phone, email, website, owner_address}. Free: {locked, available, unlock}.

GET /v1/openings/latest

Same response shape, filtered to venues whose latest signal landed in the last 7 days, sorted newest first. Params: state, limit, offset.

The opening_score model

0–100. We take the strongest evidence within each distinct signal type, then add a fusion bonus that grows with the number of independent types — so a multi-signal venue always outranks a single-signal one. That fusion is the product a raw feed can't reproduce.

Rough bands: 80–100 hot, multi-signal · 40–79 solid · < 30 single stale signal (below the default filter).

GET /v1/signals

The un-fused view — raw signal rows, for transparency and power users. Filters: source, signal_type, state, city, change_type, status, since, limit, offset. Each row includes source, signal_type, business_name, dba, address_raw, license_number, license_type, status, change_type, filing_date, issue_date, expiration_date, first_seen_date, source_url. 1 credit per returned row.

GET /v1/export

Bulk CSV of fused venues with the same filters as /v1/openings (plus limit up to 10,000). Columns: id, business_name, dba, address_norm, city, state, county, lat, lng, opening_score, status, signal_types (pipe-joined), earliest_signal_date, latest_signal_date. 1 credit per row.

curl -s "https://api.restosignals.com/v1/export?state=NY&min_opening_score=60" \
  -H "X-API-Key: pk_YOUR_KEY"

Returns a JSON body with a time-limited download_url (and expires_in seconds); the CSV also carries X-Credits-Used, X-Credits-Remaining and X-Row-Count headers.

Webhooks

Register a URL to be POSTed new matching venues as they surface — free. The daily worker dispatches matches.

# create
curl -s -X POST https://api.restosignals.com/v1/webhooks \
  -H "X-API-Key: pk_YOUR_KEY" -H "content-type: application/json" \
  -d '{"url":"https://you.example.com/hook",
       "criteria":{"state":"NY","city":"Brooklyn","signal_type":"liquor","min_opening_score":60}}'
# -> { "id": 7, "url": "…", "criteria": {…}, "active": true }

GET /v1/webhooks lists yours; DELETE /v1/webhooks/{id} removes one. Criteria keys: state, city, signal_type, min_opening_score (all optional).

Account & config

Coverage

Live states today: NY, TX, IL, OR, CO, WA, CA, added continuously. NY and IL carry fully fused, high-score leads; TX is currently issued-liquor only (lower scores). A state with no data returns an empty list — never a fabricated row. In MCP, call coverage for the current list and per-state counts.

Every venue carries the owner name; New York City adds a phone and Texas and New York add a mailing address, all mined from the public filings. Contacts are revealed on paid plans and locked (but flagged as available) on the free tier. Email is a later add.

MCP server (for AI agents)

The same data and wallet over the Model Context Protocol at https://api.restosignals.com/mcp:

{
  "mcpServers": {
    "restosignals": {
      "url": "https://api.restosignals.com/mcp",
      "headers": { "Authorization": "Bearer pk_YOUR_KEY" }
    }
  }
}

Tools: coverage (free — call first), new_openings, venue_signals, watch_area (free). Full setup, per-tool schemas and an installable skill are on the agents page →