Loop
How it worksThe loopWhy LoopPricingDocs
guide Python · REST API

Use Loop in Python.

Loop exposes a clean REST API at api.stayinloop.dev/v1. Call it with requests or httpx, drop the OpenAPI spec into LangChain or the OpenAI SDK, or point an MCP-capable agent at stayinloop.dev/mcp. No key required in the free tier.

option 1 requests (quickest)
loop_demo.py
import requests

BASE = "https://api.stayinloop.dev/v1"

# search
results = requests.get(
    f"{BASE}/search",
    params={"q": "quiet vegan restaurant", "location": "Kreuzberg, Berlin"},
).json()["results"]

top = results[0]
print(top["name"], top["availability"]["status"])

# get full details + result_token
details = requests.get(f"{BASE}/details/{top['result_id']}").json()

# verify a claim live
obs = requests.get(
    f"{BASE}/verify/{top['result_id']}",
    params={"claim": "open tonight"},
).json()

# report outcome (mutates confidence)
resp = requests.post(
    f"{BASE}/report",
    json={"result_token": details["result_token"], "outcome": "correct"},
).json()
print(resp["new_confidence"])
option 2 OpenAI SDK — function calling

Fetch the OpenAPI spec and convert it to OpenAI tool definitions. The model can then call search, get_details, verify, and report natively.

loop_openai.py
import json
import requests
from openai import OpenAI

client = OpenAI()
BASE = "https://api.stayinloop.dev/v1"

# load Loop's tool definitions from the OpenAPI spec
spec = requests.get(f"{BASE}/openapi.json").json()

# convert to OpenAI tool format (simplified — adapt to your schema transformer)
tools = [
    {
        "type": "function",
        "function": {
            "name": path.strip("/").replace("/", "_"),
            "description": info.get("get", info.get("post", {})).get("summary", ""),
            "parameters": {"type": "object", "properties": {}},
        },
    }
    for path, info in spec["paths"].items()
]

response = client.chat.completions.create(
    model="gpt-4o",
    tools=tools,
    messages=[{"role": "user", "content": "Find a vegan restaurant open now in Kreuzberg"}],
)
option 3 httpx async — concurrent calls

Use httpx.AsyncClient to fan out get_details and verify in parallel — useful in FastAPI routes or async agent pipelines.

loop_async.py
import asyncio
import httpx

BASE = "https://api.stayinloop.dev/v1"

async def find_and_verify(query: str, location: str) -> dict:
    async with httpx.AsyncClient() as client:
        results = (await client.get(
            f"{BASE}/search",
            params={"q": query, "location": location},
        )).json()["results"]

        if not results:
            return {"error": "no results"}

        top = results[0]
        details, obs = await asyncio.gather(
            client.get(f"{BASE}/details/{top['result_id']}"),
            client.get(f"{BASE}/verify/{top['result_id']}", params={"claim": "open now"}),
        )
        return {**details.json(), "observation": obs.json()}

result = asyncio.run(find_and_verify("vegan table for 4", "Kreuzberg, Berlin"))
print(result["name"], result["observation"]["observed_at"])
Free tier: 30 reads/min, no key required. To get 60 reads/min and appear named on the signals board, pass Authorization: Bearer sk_live_… as a header or append ?key=sk_live_… to any URL.
← Full API referenceWatch your calls on the signals board →