← Files Peristyle Grocery CartARCHIVED FILE
reference/raw-http.md
4.74 KB · Oct 2, 2026 · 00:11 UTC
# Raw HTTP fallback
**Read this only when the `peristyle-grocery-cart` MCP server is unavailable.**
The MCP server is the recommended, secure default — it handles Kroger OAuth and
keeps secrets off the agent. Use raw HTTP only when those tools genuinely aren't
present.
Base URL: `https://api.peristyle.io` (the canonical host — see "Pin the host" in
SKILL.md before pointing anywhere else).
---
## Recipe routes (no auth)
```
POST /v1/recipes/search {"query": "pasta carbonara", "limit": 10}
GET /v1/recipes (browse newest; ?q= for full-text)
GET /v1/recipes/{id} (detail)
GET /v1/recipes/{id}/ingredients
```
No `Authorization` header required.
---
## Kroger (OAuth required)
### Connecting
1. `POST /v1/kroger/auth/start` → `{"link_token": "…", "login_url": "…"}`
2. User opens `login_url` and signs in.
3. Poll `POST /v1/kroger/auth/poll {"link_token": "…"}` until
`{"status": "connected", "api_key": "pk_…"}` (once). Use
`Authorization: Bearer pk_…` on Kroger action calls.
If you already hold a `pk_…` key (e.g. one issued by the connector OAuth flow
at `/.well-known/oauth-authorization-server`), send it as
`Authorization: Bearer` on the `/auth/start` call: the Kroger account then
attaches to that same user, and the poll returns `{"status": "connected"}`
**without** an `api_key` — keep using the key you have.
### Match → add
```
POST /v1/kroger/match
Authorization: Bearer pk_…
{"recipe_id": "<id>"}
```
Freeform shopping list (no recipe) — one call for the whole "and also grab…" list:
```
POST /v1/kroger/match/items
Authorization: Bearer pk_…
{"items": ["fage 2% greek yogurt 32 oz", "bananas", "18 eggs"]}
```
Single product by UPC or the trailing digits of a kroger.com product URL:
```
GET /v1/kroger/products/0068954408302
Authorization: Bearer pk_…
```
```
POST /v1/kroger/cart/add
Authorization: Bearer pk_…
{
"items": [{"upc": "…", "quantity": 1}],
"modality": "PICKUP",
"recipe_id": "…"
}
```
Give the user `checkout_url` from the response when present.
---
## Walmart (no OAuth)
Walmart routes require `WALMART_ENABLED=true` on the server. No user sign-in or
`pk_…` key is ever needed for any Walmart route.
### Match → add
```
POST /v1/walmart/match
{"recipe_id": "<id>"}
```
```
POST /v1/walmart/cart/add
{
"items": [{"product_id": "945193065", "quantity": 1}],
"store_id": "5435",
"recipe_id": "…"
}
```
Response:
```json
{
"status": "added",
"store": "walmart",
"added_count": 5,
"checkout_url": "https://www.walmart.com/sc/cart/addToCart?items=…",
"note": "Open the checkout link in your browser while signed in to Walmart…"
}
```
The user **must open `checkout_url` in a browser** while signed in to Walmart.
The API does not write to their cart server-side.
### Catalog search
```
GET /v1/walmart/products?query=baby+spinach&limit=10
GET /v1/walmart/products?item_id=945193065
GET /v1/walmart/locations?zip=78701
```
---
## Full API reference
| Method | Path | Auth |
|--------|------|------|
| `GET` | `/v1/health` | none |
| `GET` | `/v1/recipes` | **none (public)** |
| `POST` | `/v1/recipes/search` | **none (public)** |
| `GET` | `/v1/recipes/{id}` | **none (public)** |
| `POST` | `/v1/kroger/auth/start` | none |
| `POST` | `/v1/kroger/auth/poll` | none |
| `GET` | `/v1/kroger/auth/status` | `pk_…` |
| `GET` | `/v1/kroger/locations?zip=` | none (app credentials) |
| `GET` | `/v1/kroger/products?query=&brand=` | `pk_…` |
| `GET` | `/v1/kroger/products/{upc}` | `pk_…` |
| `POST` | `/v1/kroger/match` | `pk_…` |
| `POST` | `/v1/kroger/match/items` | `pk_…` |
| `POST` | `/v1/kroger/cart/add` | `pk_…` |
| `GET` | `/v1/walmart/locations?zip=` | none |
| `GET` | `/v1/walmart/products?query=` | none |
| `POST` | `/v1/walmart/match` | none |
| `POST` | `/v1/walmart/cart/add` | none |
| `POST` | `/v1/pantry/opt-in` | `pk_…` |
| `GET` | `/v1/pantry` | `pk_…` |
| `PUT` | `/v1/pantry/items` | `pk_…` |
| `POST` | `/v1/pantry/feedback` | `pk_…` |
| `POST` | `/v1/pantry/confirmations/{id}/resolve` | `pk_…` |
MCP users: Kroger connect is handled by `connect_kroger` /
`finish_kroger_connection`. Walmart needs no connect step.
### Pantry (opt-in)
All pantry routes need a `pk_…` key, and every route except `opt-in` requires
the user to have opted in first (403 otherwise). `GET /v1/pantry` returns
items with a decayed `status` (`have` / `probably_out` / `out`), love/hate
`feedback`, and `pending_confirmations`. `PUT /v1/pantry/items` takes
`{"items": [{"name": "whole milk", "state": "have"|"out"|"remove", "staple": true?}]}`.
Cart adds by an opted-in user return a `pantry_confirmation_id`; after the user
checks out, resolve it with
`POST /v1/pantry/confirmations/{id}/resolve {"purchased": true, "removed_refs": []}`
to stock the pantry.
SHA-256: 4146700d7f5bc1060b70f2f35598bebdcb16772f0903e4c0217b9ca366d541df