API basics

Open .md

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 returns 401 invalid_partner_key. Keep the key on the server; never show it to the person.
  • Bodies: JSON, at most 4096 characters (413 too_large above that).
  • Errors: { "error": "<code>", "details": { … } }.
  • Retries: quotes and purchases take an Idempotency-Key header (1 to 128 printable characters). The same key and body return the same result; the same key with a different body returns 409 idempotency_key_reused.

Endpoints

Method and pathWhat it does
POST /v3/api/agent/registerRegister 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/meThe partner record, the connections people granted it, and counts.
POST /v3/api/agent/connect-linksAsk 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/quotesStart 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>/addressAmazon 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>/preferencesThe person's saved preferences for that store (place names, usual address and card, budget, notes).
POST /v3/api/agent/connections/<connection_id>/preferences/placesSave a place name, only as the answer to the agent's own destination_choice_needed quote.
POST /v3/api/agent/purchasesBuy 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>/operationsRun 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>/operationsPublic 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-jobsAdd 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/healthPublic: 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-statusRefresh (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>" } } } }
  • query holds 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" } inside constraints. hard marks a quote above it over_budget; target only reports it.
  • "preferences": "apply" or "ignore" sits next to connection_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" }
  • lines are the store's own charge rows and add up to total_cents.
  • selected_variants names the color, size or pack the store's page actually selected (Amazon may pick one on a product-family page); availability is 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 cleanup is done; 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

  • confirmation is 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 on approval_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, with detail.was_cents and detail.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_url next to Buy; Nook enters it into that one checkout and keeps nothing. confirmation alone 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.
  • uncertain means 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 gets 409 purchase_uncertain.
  • blocked / cancelled: nothing was bought; the same quote can be bought again with a new request and a new Idempotency-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.

Markdown version of this page