Loop
docs v0 · open wave

Wire Loop into your agent.

One endpoint where agents search, verify, and act on real businesses. Current coverage: restaurants in Kreuzberg, Berlin — expanding by vertical as agent demand shows where to go next. No key required during the open wave; keyed agents get named attribution and higher limits.

01 connect · MCP

Paste https://stayinloop.dev/mcp into Claude (Settings → Connectors) — or add it to any MCP client config:

mcp.json
{
  "mcpServers": {
    "loop": { "url": "https://stayinloop.dev/mcp" }
  }
}

With an API key: https://stayinloop.dev/mcp?key=sk_live_…

02 connect · REST
curl
curl https://api.stayinloop.dev/v1/search \
  -G \
  --data-urlencode 'q=quiet vegan table for 4 tonight' \
  --data-urlencode 'location=Kreuzberg, Berlin'

Optional Authorization: Bearer sk_live_… header. Boolean filters as query params: vegan, vegetarian, outdoor, open_now, plus price_band.

03 connect · ChatGPT

ChatGPT’s developer mode (Pro/Plus/Business, Settings → Apps → Advanced settings → Developer mode) accepts full MCP connectors: create a connector with https://stayinloop.dev/mcp and no authentication — or append ?key=sk_live_…. Building a custom GPT instead? The REST API ships an OpenAPI spec for Actions: /v1/openapi.json.

04 the four tools
search(query, location?, filters?)

Natural-language search over the live catalog. Filters: vegan, vegetarian, outdoor, open_now, price_band (€ | €€ | €€€) — also derived automatically from the query text.

Ranked results (max 8) with result_id, confidence, observed_at, and inferred availability.
· Out-of-coverage locations return an explicit coverage message, never junk.
get_details(result_id)

The full structured record for a chosen result — address, coordinates, hours, contact, tags.

Complete record plus a result_token (valid 30 minutes) used for reporting outcomes.
verify(result_id, claim?)

Freshness check before acting: the latest observation for the record and exactly when it was seen.

latest_observation, observed_at, record_confidence, current inferred availability.
report(result_token, outcome)

Close the loop: outcome is one of correct | wrong | booked | closed | other.

Acknowledgement with the record's new confidence and freshness stamp — reports mutate the data immediately.
· Reporting agents earn fresher data and higher limits.
05 result shape
search → 200
{
  "results": [
    {
      "result_id": "7f7250b4-…",
      "name": "Al Catzone - Pizza Napovegana",
      "cuisine": ["pizza"],
      "tags": ["outdoor seating", "pizza", "vegan only"],
      "price_band": { "value": "€", "inferred": true },
      "vegan": true,
      "outdoor_seating": true,
      "address": "Brandesstraße 7, Kreuzberg, Berlin",
      "availability": {
        "status": "likely_open_now",
        "inferred": true,
        "basis": "opening hours last observed 2026-06-09",
        "confidence": 0.75
      },
      "confidence": 0.95,
      "observed_at": "2026-06-10T07:12:09Z",
      "relevance": 12.4
    }
  ],
  "note": "availability is inferred — call verify(result_id) before acting on it."
}

Every record carries observed_at and confidence. Anything inferred says so — availability.inferred is always true until a merchant is connected. Verify before you act; report after.

06 errors
unknown_result_id
The result_id doesn't exist (or isn't a valid id).
invalid_result_token
The token is malformed or wasn't issued by Loop.
expired_result_token
Tokens live 30 minutes — call get_details again.
invalid_outcome
outcome must be: correct, wrong, booked, closed, other.
rate_limited
Per-IP limits: 30 read calls/min, 10 reports/min (HTTP 429 + Retry-After on REST).

Errors are structured JSON on both surfaces — tool calls never surface raw 500s for bad inputs.

Watch your calls land on the live signals board. Questions or a key request: hello@stayinloop.dev.