API basics
This page only repeats what Nook's published agent guide documents. Paths are relative to Nook's base URL. Field lists are abbreviated; the agent guide is the source of truth.
Basics
- Auth:
Authorization: Bearer nk_…, the agent's partner key. A missing or wrong key returns401 invalid_partner_key. Keep the key on the server; never show it to the person. - Bodies: JSON, at most 4096 characters (
413 too_largeabove that). - Errors:
{ "error": "<code>", "details": { … } }. - Retries: quotes and purchases take an
Idempotency-Keyheader (1 to 128 printable characters). The same key and body return the same result; the same key with a different body returns409 idempotency_key_reused.
Endpoints
| Method and path | What it does |
|---|---|
POST /v3/api/agent/register | Register a partner key the agent generated itself (nk_ plus 32 random bytes in base64url). Body: id, name, host, optional about. Returns 201 with the partner record. |
GET /v3/api/agent/me | The partner record, the connections people granted it, and counts. |
POST /v3/api/agent/connect-links | Ask for a link. { "merchants": "all" }, a list, or { "merchant": "amazon" }. Returns 201 with url, status: "waiting_for_person", expires_at. |
GET /v3/api/agent/connect-links/<id> | Link status: waiting_for_person, connecting, connected or failed. Once connected, connection.id is the connection_id. |
POST /v3/api/agent/quotes | Start a quote. Returns 202 with status: "preparing". |
GET /v3/api/agent/quotes/<id> | Read the quote. Poll every few seconds. |
POST /v3/api/agent/connections/<connection_id>/address | Amazon only: save a new delivery address the person asked for. Returns 202; read it at GET /v3/api/agent/address-operations/<id> (preparing, saved, needs_input with Amazon's suggested versions, or blocked). Not a purchase. |
GET /v3/api/agent/connections/<connection_id>/preferences | The person's saved preferences for that store (place names, usual address and card, budget, notes). |
POST /v3/api/agent/connections/<connection_id>/preferences/places | Save a place name, only as the answer to the agent's own destination_choice_needed quote. |
POST /v3/api/agent/purchases | Buy a ready quote. Body: quote_id and, if the person said yes in chat, confirmation (their words). Returns 202. |
GET /v3/api/agent/purchases/<id> | Read the purchase. |
GET /v3/api/agent/connections/<connection_id>/operations (and .md) | Named operations a connected store offers beyond quotes, such as searching flights or managing price alerts: each one's name, read or write, approval rule, input schema and output. |
POST /v3/api/agent/connections/<connection_id>/operations | Run one: { "operation", "input", "confirmation" }. A write that changes the person's account needs confirmation.text, the person's own words. Returns 202; read it at GET /v3/api/agent/operations/<id>. |
GET /v3/api/agent/sites, GET / POST /v3/api/agent/sites/<site>/operations | Public reads that need no account (for example movie showtimes), run in a fresh browser with nothing signed in. Any partner key can call them. |
POST /v3/api/agent/site-jobs | Add a website by its address: Nook connects the person's account there (or builds public reads only, with "mode": "public") and generates its operations. Open only to pilot partners for now (site_builder_access_required otherwise). |
GET /v3/api/connections/health | Public: Nook's status and the stores and sites a person can connect, with any operations each offers. |
POST / GET /v3/api/agent/purchases/<id>/order-status | Refresh (202, status: checking) and read the status of a confirmed order. The guide documents it for Uber Eats; Nook's Oct 2 changelog adds Instacart to the same order reader. GET only reads the last snapshot. |
Quote request
{ "connection_id": "<connection.id>",
"request": {
"items": [{ "query": "<the product's own words>", "size": "<pack or size>", "quantity": 1,
"options": [{ "name": "<what the user asked about>", "value": "<their words>" }] }],
"destination": { "kind": "saved", "label": "<text in a saved address>" },
"payment": { "kind": "saved", "network": "amex | visa | mastercard | discover", "last4": "<optional>" },
"constraints": { "tip": { "amount_cents": 400, "currency": "USD" } },
"merchant_data": { "ubereats": { "restaurant": "<its name>" } } } }
queryholds only the product's own words. Everything else goes in its own field. A requirement no field can express must be raised with the person, never dropped.- A budget is sent only when the person states one:
"budget": { "amount_cents": 1000, "currency": "USD", "kind": "hard" }insideconstraints.hardmarks a quote above itover_budget;targetonly reports it. "preferences": "apply"or"ignore"sits next toconnection_id.
Quote response
{ "id", "status": "preparing | ready | blocked | cancelled", "merchant", "connection_id",
"quote": { "items": [{ "title", "quantity", "unit_price_cents", "seller", "selected_variants", "availability" }], "lines": [{ "label", "cents" }],
"total_cents", "currency", "destination": { "matched", "label", "place" },
"payment": { "matched", "brand", "last4" }, "tip": { "cents", "requested", "matched" },
"delivery", "expires_at" },
"blocker": { "code", "message", "choices", "listings": [{ "product_id", "title", "price", "image", "url", "role" }] },
"warnings": [{ "code", "message" }],
"cleanup": "running | done | unconfirmed", "stages": [{ "stage", "ms" }], "preferences": { … },
"created_at", "finished_at" }
linesare the store's own charge rows and add up tototal_cents.selected_variantsnames the color, size or pack the store's page actually selected (Amazon may pick one on a product-family page);availabilityis that page's own text, not a stock promise.- When a blocker carries
listings, show the person each one's picture, link, title and price. Never ask the person for a product ID: the listings carry them. - Read the quote once more after
cleanupisdone; warnings about things Nook could not put back arrive late. - Common blocker codes:
quote_failed(Nook's own failure),quote_check_failed(checkout didn't match the request),product_choice_requires_user(the person must pick),product_mismatch(the chosen listing and the checkout disagree),over_budget.
Purchase response
{ "id", "quote_id", "connection_id", "merchant", "status", "quote", "approval_url", "approved_by", "confirmation",
"receipt": { "order_id", "merchant_confirmed": true, "observed_at" },
"failure", "detail", "warnings": [], "created_at", "updated_at" }
Statuses: awaiting_approval, approved, submitting, confirmed, blocked, cancelled, uncertain. Claim an order only from confirmed.
Purchase rules
confirmationis the person's reply to this quote's total, in their own words, 1 to 500 characters. Without it, the purchase waits until the person presses Buy onapproval_url.- Before its one click, Nook reads the checkout again and buys at the quote's total or less. It buys nothing if the total went up (
price_increased, withdetail.was_centsanddetail.now_cents) or the item, address or card changed. - A store that keeps no saved card (many Shopify stores) quotes the card as "Card you enter at purchase". The person types it on
approval_urlnext to Buy; Nook enters it into that one checkout and keeps nothing.confirmationalone can't buy these. failure: merchant_order_cancelled(Uber Eats): Uber cancelled an identified order after it was placed; Nook did not cancel it. Check refunds with Uber and don't reorder automatically.uncertainmeans Nook pressed the store's final button but couldn't read the result, so the order may exist. Never buy it again; a new purchase of the same quote gets409 purchase_uncertain.blocked/cancelled: nothing was bought; the same quote can be bought again with a new request and a newIdempotency-Key.quote_not_ready: the quote is blocked, still cleaning up, or carries warnings.409 in_use: the store account is busy with another run; retry shortly.404 not_found: the quote or purchase belongs to another partner or doesn't exist.
Quote refusals
Refused before any browser opens: 404 not_found (no connection you hold), 400 quotes_unavailable, 400 invalid_input (path, rule), 400 unsupported_request (paths: what this store's quotes can't honour yet, never dropped), 409 in_use.
Not documented here
- TBD: a public base URL for these docs. The agent guide names one; these docs leave it out until we decide what to publish.
- TBD: rate limits, pricing and SLAs. The sources don't state them.