Your drops, from your own apps and AI

Everything the Drops app shows you is readable from outside it: every drop, who signed up, where everyone is in line, how each list turned up, what guests said. A REST API under /v1/ for your code, and an MCP server for Claude, Cursor, ChatGPT and any other AI tool.

Base URL

https://dagobah.hellagooddrops.com

Read-only

Six reads. An AI or an app can see your drops; it cannot change them.

Paid accounts

Included in the price. One key per account, made and revoked by the owner.

curl https://dagobah.hellagooddrops.com/v1/drops \
  -H "Authorization: Bearer hgd_live_YOUR_KEY"

Your key

The owner makes the key in the app: ☰ › Account, bottom of the page, Create key. It is shown once. Send it on every request:

Header
Authorization: Bearer hgd_live_q6Yslk…

Keys start with hgd_live_ and are 49 characters long. We keep a hash, never the key: if you lose it, revoke it in the app and make another. Revoking is instant.

Keep it server-side. The API sends no CORS headers on purpose: a key belongs in your backend, a script, or an AI tool's config, never in a web page.

Limits and errors

60 requests a minute per key, 120 per address. Every answer carries x-ratelimit-limit and x-ratelimit-remaining; a 429 carries retry-after in seconds. A drop's line moves every few seconds at most: polling it every 10 to 15 seconds is plenty.

Every error is JSON with a code you can switch on and a message you can show:

Error shape
{ "error": { "code": "drop_not_found", "message": "No drop with that id or code on this account." } }
401invalid_keyNo key, a malformed key, or a revoked one.
403no_scopeThe key cannot do this (every key can read).
404drop_not_foundNo drop with that id or code on this account.
404not_foundNo such route.
405method_not_allowed/v1/ takes GET only; /mcp takes POST only.
429rate_limitedOver the minute's budget. Wait retry-after seconds.
500server_errorOur side. Try again.

REST

All times are ISO 8601 in UTC; each drop carries its own time zone. :drop is a drop's id or its code, the letters at the end of its signup link (K7MRQ). Ids are the app's own and stay the same for the life of a drop or a guest. A drop's status is prelaunch (a test run), open, paused, nowait (No waiting), closed or finished.

GET/v1/account

The business the key belongs to.

FieldMeaning
name · slugstringThe business, as guests see it.
tagsstring[]The lists it hands out with its signup links, e.g. vip.
drops{total, live, prelaunch, finished}How many drops, by where they are.
keyobjectThe key you sent: its prefix and scopes.
200
{
  "name": "Northside Sneakers", "slug": "northside-sneakers",
  "tags": ["vip", "earlybird"],
  "drops": { "total": 6, "live": 1, "prelaunch": 1, "finished": 4 },
  "key": { "prefix": "hgd_live_q6Yslk", "scopes": ["read"] }
}
GET/v1/drops

Every drop on the account, newest first, with the four numbers on its home-screen card.

FieldMeaning
code · name · statusstringThe drop, and where it is.
flowstringladder: waves climb steps to one door. lanes: several tables, each its own door.
starts_at · ends_at · tztime, stringThe event's own times and zone.
addressobjectstreet, city, state, zip, parking, note.
signup_urlstringThe drop's signup link.
signed_up · turned_up · here · doneintSigned up; checked in; checked in and not yet called in; called in (Lanes) or through the door (Ladder).
closes_attime|nullWhen the drop's 72 hours end, once its clock has started.
200
{
  "count": 6,
  "drops": [
    { "id": "a4d98404-…", "code": "K7MRQ", "name": "Summer Collab Release",
      "status": "open", "flow": "lanes", "tz": "America/Los_Angeles",
      "starts_at": "2026-10-18T17:00:00Z", "ends_at": "2026-10-19T01:00:00Z",
      "address": { "street": "1450 Market St", "city": "San Francisco", … },
      "signup_url": "https://go.hellagooddrops.com/e/K7MRQ",
      "signed_up": 269, "turned_up": 245, "here": 58, "done": 187, … }
  ]
}
GET/v1/drops/:drop

One drop right now, as its board shows it. A Ladder drop answers steps: each step and the wave on it, the door step last. A Lanes drop answers lanes: how many are waiting for each one and its last call. Both carry the run card.

FieldMeaning
countsobjectsigned_up, turned_up, here, done, and ready_to_call: who could be called next.
steps[].waveLadder · object|nullThe wave on that step: its number, letter, people, when it was made and told. door marks the step people go in through.
lanes[].waiting · last_callLanesWaiting for this lane, and its last call: wave, letter, when, how many.
runobjectchecked_in, waiting, in_line, finished, no_show; in Ladder also waves_left, minutes_per_wave and ends_about (the median pace times the waves left, once two waves are done).
check_in · tickets_shownbooleanThe drop's own settings. Lanes adds lanes_are_different and one_turn_only.
200 · Lanes
{
  "drop": { "code": "K7MRQ", "name": "Summer Collab Release", "status": "open", "flow": "lanes",
            "check_in": true, "lanes_are_different": true, … },
  "counts": { "signed_up": 269, "turned_up": 245, "here": 58, "done": 187, "ready_to_call": 58 },
  "lanes": [
    { "key": "hats", "name": "Hats", "max": 20, "waiting": 26,
      "last_call": { "wave": 12, "letter": "M", "at": "2026-10-18T19:42:10Z", "people": 5 } },
    { "key": "tees", "name": "Tees", "max": 20, "waiting": 11, "last_call": { … } }
  ],
  "run": { "checked_in": 245, "waiting": 58, "called": 187, "no_show": 24, "lanes": 4, … },
  "now": "2026-10-18T19:45:00Z"
}
GET/v1/drops/:drop/people?status=here

The list: everyone who signed up, the ones still to come in first. Names and times only: a guest's phone number, email and pass never leave the app. status is all (default), here, not_here, in_wave or done; tag keeps one list; q finds part of a name; limit is 1 to 500, default 100.

FieldMeaning
countsobjectall, here, not_here, in_wave, done, and how many on each list.
people[].tagstring|nullThe list their signup link carried.
people[].checked_in_at · called_at · done_attime|nullWhen they checked in, were called, came through.
people[].via_signbooleanSigned up at the check-in sign rather than from a link.
people[].wave · stepLadderThe wave they are in, and the step it is on.
people[].lane · turnsLanesThe lane they picked, and each turn: lane, status, verified at the table.
200
{
  "drop": { "code": "K7MRQ", "name": "Summer Collab Release", "flow": "lanes" },
  "status": "here",
  "counts": { "all": 269, "here": 58, "not_here": 24, "in_wave": 187, "done": 0, "tags": { "vip": 28 } },
  "people": [
    { "id": "b1e22775-…", "name": "Teresa A.", "tag": "vip", "via_sign": false,
      "signed_up_at": "2026-10-15T22:29:09Z", "checked_in_at": "2026-10-18T17:12:40Z",
      "called_at": null, "done_at": null, "door_scans": 0,
      "lane": "Hats", "turns": [ { "lane": "Tees", "status": "done", "verified": true } ] }
  ]
}
GET/v1/drops/:drop/metrics

The night in numbers, the app's Metrics screen. All timestamps, nothing estimated.

FieldMeaning
totalsobjectregistered, turned_up, came_inside, never_showed, at_sign.
by_list[]list, signed_up, turned_up, servedPer signup list. null is everyone with no list. The number to act on: send more of the links that turn up.
lists_with_no_signups[]list, closed_atLinks that brought nobody.
by_hour[]at, nCheck-ins per hour.
by_lane[]LanesEach lane: called, calls, last_at, waiting.
waves[]no, step, people, minutesEvery wave, with minutes from told to done.
200 · Ladder
{
  "drop": { "code": "Q3TZB", "name": "Closing Sale", "status": "finished", "flow": "ladder" },
  "totals": { "registered": 304, "turned_up": 264, "came_inside": 220, "never_showed": 40, "at_sign": 0 },
  "by_list": [
    { "list": null, "signed_up": 262, "turned_up": 227, "served": 213, "at_sign": 0 },
    { "list": "vip", "signed_up": 11, "turned_up": 9, "served": 8, "at_sign": 0 }
  ],
  "by_hour": [ { "at": "2026-10-04T17:00:00Z", "n": 179 }, … ],
  "waves": [ { "no": 1, "step": "Inside", "people": 25, "minutes": 18, … } ]
}
GET/v1/drops/:drop/reviews?limit=50

The drop's star ratings: the count, the average, the spread, and the newest first with what the guest wrote. limit is 1 to 500, default 50.

200
{
  "drop": { "code": "K7MRQ", "name": "Summer Collab Release" },
  "count": 41, "average": 4.7, "spread": { "1": 0, "2": 1, "3": 2, "4": 5, "5": 33 }, "commented": 12,
  "reviews": [
    { "stars": 5, "comment": "Got coffee and came back when my phone said go.", "at": "2026-10-18T20:04:18Z", "guest": "Sophia P." }
  ]
}
POST/mcp

MCP: your drops inside an AI tool

The same six reads as tools an AI can call, over the Model Context Protocol (Streamable HTTP, stateless). Point any MCP client at https://dagobah.hellagooddrops.com/mcp with your key in the same Authorization header, then ask it things like "how's the line at the drop right now?", "which list turned up best on Saturday?" or "any reviews mention parking?"

ToolReturns
get_accountThe business, its lists, how many drops.
list_dropsEvery drop, its status and its four numbers.
get_drop dropOne drop right now: steps or lanes, the waves, the run card.
get_drop_people drop, status, tag, q, limitThe list: names, lists, where each person is.
get_drop_metrics dropBy list, by hour, by lane, every wave.
get_drop_reviews drop, limitStar ratings and comments.

Each tool answers with text and structuredContent (the same JSON as the REST read). A drop that is not on the account answers isError. Same limits as REST. One JSON-RPC message per POST; the server keeps no session.

Connect it

claude mcp add --transport http drops https://dagobah.hellagooddrops.com/mcp \
  --header "Authorization: Bearer hgd_live_YOUR_KEY"
  1. Make a key in the app (☰ › Account › Create key).
  2. Add the server to your tool with the snippet above. Any client that can send a header works; ChatGPT's connectors and other OAuth-only clients cannot yet.
  3. Ask. The tool list is small on purpose: an AI reads your drops, it does not run them.

Public text

Guest names and review comments are typed by the public. The server tells the model so in every tool that carries them, and you should too in anything you build on top: treat them as data, never as instructions. A guest who signs up as "ignore previous instructions" is a guest named that.

Changes

2026-10-16First release: six reads under /v1/, MCP at /mcp, self-serve keys in the app.

Questions, or something you need that is not here: hello@hellagooddrops.com.