-
Notifications
You must be signed in to change notification settings - Fork 0
Endpoints
The gateway is self-describing: MCP's tools/list returns every tool it offers,
with descriptions and input schemas. At the time of writing that is 62 tools, of
which ddREST covers the 26 that make up ordinary browse-cart-order use.
bun run list-toolsThat prints what the gateway currently advertises and flags anything ddREST calls that it does not — the check to run when adding a route or after DoorDash ships a change.
| Method | Path | Tool |
|---|---|---|
| GET | /v1/restaurants |
doordash_find_restaurants |
| GET | /v1/nearby-stores |
internal_find_nearby_stores |
| GET | /v1/stores/{store_id} |
internal_get_store_info |
| GET | /v1/stores/{store_id}/menu |
doordash_get_restaurant_menu |
| GET | /v1/stores/{store_id}/items |
internal_find_items_in_store |
| GET | /v1/stores/{store_id}/items/{item_id} |
internal_get_item_details |
| GET | /v1/stores/{store_id}/menus/{menu_id}/items/{item_id} |
doordash_get_food_item |
| GET | /v1/stores/{store_id}/promotions |
internal_list_eligible_cart_promotions |
| POST | /v1/product-lists |
doordash_create_product_list |
| GET | /v1/carts |
doordash_list_active_carts |
| POST | /v1/carts/items |
doordash_add_to_cart |
| POST | /v1/carts/{cart_uuid}/items |
doordash_add_to_cart |
| GET | /v1/carts/{cart_uuid} |
doordash_get_cart |
| DELETE | /v1/carts/{cart_uuid} |
doordash_clear_cart |
| DELETE | /v1/carts/{cart_uuid}/items/{cart_item_id} |
doordash_remove_cart_item |
| POST | /v1/carts/{cart_uuid}/promotions |
internal_apply_cart_promotion |
| DELETE | /v1/carts/{cart_uuid}/promotions/{promo_code} |
internal_remove_cart_promotion |
| POST | /v1/carts/{cart_uuid}/preview |
internal_preview_order |
| POST | /v1/carts/{cart_uuid}/order |
internal_submit_order |
| GET | /v1/carts/{cart_uuid}/checkout-url |
doordash_get_checkout_url |
| GET | /v1/orders |
internal_get_order_history |
| GET | /v1/orders/{order_uuid}/receipt |
internal_get_order_receipt |
| GET | /v1/orders/{order_uuid}/status |
internal_get_order_status |
| POST | /v1/orders/{order_uuid}/reorder |
internal_reorder |
| GET | /v1/addresses |
doordash_list_delivery_addresses |
| PUT | /v1/addresses/current |
doordash_set_delivery_address |
| GET | /v1/payment-methods |
doordash_get_payment_info |
POST /v1/carts/{cart_uuid}/order places a real order and charges the account.
tip_amount_cents is required rather than defaulted, so a tip is always
deliberate.
Anywhere coordinates are accepted — GET /v1/restaurants and
GET /v1/nearby-stores — you can pass an address_id from
GET /v1/addresses instead, and ddREST reads the coordinates off the saved
address for you:
curl -s "http://localhost:8787/v1/restaurants?query=pizza&address_id=addr-home" \
-H "authorization: Bearer dds2.…"That costs one extra upstream lookup, so passing latitude/longitude
directly stays the cheaper path. Nothing is cached — an address you just added
would otherwise be invisible until a TTL elapsed.
Pass address_id=default for whichever address DoorDash marks as the account
default, so the common case needs no lookup at all:
curl -s "http://localhost:8787/v1/restaurants?query=pizza&address_id=default" \
-H "authorization: Bearer dds2.…"The id is the address_id field, not address_link_id.
Sending address_id and coordinates is refused rather than picking a winner,
since the two can disagree and you would have no way to tell which was used. An
unknown id returns address_not_found listing the addresses that do exist —
ids are opaque numbers, so each comes with its printable address:
{
"error": "address_not_found",
"message": "No saved address has the id \"9999\".",
"addresses": "/v1/addresses",
"known_addresses": [
{ "id": "1611178960", "address": "Thompson Hotels, 21 E Bellevue Pl, Chicago, IL 60611, USA" }
]
}A saved address carrying no coordinates returns address_missing_coordinates
rather than quietly falling back to the configured default.
Every optional argument the gateway advertises is exposed, bar the guest-session
ones (session_id, session_nonce, is_guest) which switch identity away from
your authenticated account or ask for an AES-encrypted response. /docs has the
full list; the ones worth knowing about:
| Route | Parameter | Why it matters |
|---|---|---|
/v1/restaurants |
radius |
Miles. Upstream defaults to 3, which is tight outside a dense city — widen it if results look sparse. |
/v1/restaurants |
desired_restaurant_name, item_name
|
Narrow to a named restaurant or a specific dish. |
/v1/stores/{id}/menu |
include_extras |
Every item's options inline. Much larger response. |
/v1/stores/{id}/items |
disable_ads |
Suppress sponsored placements. Worth setting if you take only the first result, since a sponsored placement is not ranked. |
/v1/stores/{id}/items |
max_results, snap_eligible_only
|
Results per item; SNAP/EBT filter. |
/v1/carts/{uuid}, add-to-cart |
include_pricing |
Subtotal, taxes and fees inline. An estimate — the preview endpoint is what an order is priced against. |
/v1/carts/{uuid}/preview and /order
|
address_id |
Deliver this order to a saved address without changing the account default. Sent upstream as delivery_address_id. |
/v1/nearby-stores |
use_store_ranker |
Experimental upstream ranking instead of soonest-ETA. |
Boolean query parameters accept true/false, 1/0, yes/no, and reject
anything else rather than guessing — ?disable_ads=maybe is a 400, not a
silent true.
The auth and pairing routes are not tool-backed:
| Method | Path | Purpose |
|---|---|---|
| POST | /v1/auth/login/start |
Begin the paste-back login |
| POST | /v1/auth/login/complete |
Finish it and get a session |
| GET | /v1/auth/session |
Inspect the current session |
| POST | /v1/auth/logout |
Revoke it |
| POST | /v1/auth/pair/request |
Device: ask for a pairing code |
| POST | /v1/auth/pair/token |
Device: poll for the session |
| GET/POST | /v1/auth/pair |
Human: the approval pages (HTML) |
| POST | /v1/auth/pair/verify |
Human: look up a code (JSON) |
| POST | /v1/auth/pair/complete |
Human: approve it (JSON) |
| POST | /v1/auth/pair/deny |
Human: refuse it (JSON) |
Every MCP tool accepts an intent string, and per dd-cli's own help text
DoorDash "may review this data for research and product-improvement purposes".
This API generates it server-side, per operation, and forwards no end-user text.
Callers cannot set or influence it. Every string sent is in one auditable place:
src/mcp/tools.ts.
It is optional on all 26 tools, which the gateway's own schemas confirm — they describe it as "logged for product analytics and monitoring only — has no effect on the results returned". ddREST sends it anyway, because a generated one-line description of the operation is a smaller disclosure than an empty field is a benefit, and it keeps behaviour close to dd-cli's. Nothing would break if it were dropped.
{ "error": "session_expired", "message": "…", "login_start": "/v1/auth/login/start" }error is a stable machine-readable code. Notable ones: session_missing,
session_invalid, session_expired, csrf_origin_rejected,
login_ticket_expired, state_mismatch, token_exchange_failed,
doordash_unauthorized, doordash_forbidden, upstream_error.
A 403 doordash_forbidden with private_beta_gating: true means the account
authenticated fine but is not an approved consumer-MCP tester.
Tool responses are passed through unvalidated, but they are documented. The
gateway advertises an outputSchema per tool alongside its inputs, so /docs
shows the real response shape for the 20 of 26 tools that describe one. The
other six declare a bare {additionalProperties: true} and fall back to the
generic pass-through result:
doordash_get_restaurant_menu internal_get_item_details
doordash_list_active_carts doordash_get_checkout_url
doordash_list_delivery_addresses doordash_get_payment_info
Documented is not enforced. Nothing validates a response against its schema — DoorDash can add a field at any time and it must still pass through untouched.
The schemas are committed rather than fetched at boot, so the API document is
identical for everyone, needs no account, and renders /docs without a network
call. Refresh them after a DoorDash change:
bun run list-tools --dump && bun run gen-schemasThat rewrites src/schemas/results.generated.ts,
hoisting each tool's $defs into shared components so their $refs resolve
inside the OpenAPI document.