{"version":"1.1","description":"Agora routes designed for AI agents: semantic HTML, stable ids/classes, clear DOM contract. Prefer /agent/* routes and #agent-* / data-agent-* selectors over consumer UI pages.","basePath":"/agent","manifestUrl":"/api/agent-routes","executionModes":{"browser":{"examples":["Perplexity","OpenAI Operator","Claude Computer Use","Browser-Use"],"authRequired":false,"workflow":"/agent/search?q=... -> /agent/product/[slug] -> click #agent-add-to-cart -> /agent/cart -> /agent/checkout"},"programmatic":{"examples":["Custom LLM tools","MCP servers","Backend scripts"],"authRequired":true,"workflow":"GET /api/search -> read #agent-product-raw-json -> POST /api/agent/cart -> POST /api/agent/checkout"}},"routes":[{"path":"/agent","method":"GET","purpose":"Discovery: this page and manifest tell agents how to use agent routes.","contentType":"text/html","forAgents":"Start here. Read this page or fetch /api/agent-routes for the JSON manifest."},{"path":"/agent/search","method":"GET","purpose":"Product search. Pass ?q= for direct navigation, or submit the form; use Fetch more to paginate.","contentType":"text/html","forAgents":"Fastest: GET /agent/search?q={url_encoded_query}&page=1 (runs the search on load). Or use the search form (id=agent-search-form): set input id=agent-search-input name=q and submit. Results appear in id=agent-product-list as .agent-product-item cards carrying data-agent-product-id (Mongo _id), data-agent-product-slug, data-agent-product-name, data-agent-product-price. Link a.agent-product-link goes to /agent/product/{slug}. Use button id=agent-fetch-more to load the next page.","selectors":{"form":"#agent-search-form","searchInput":"#agent-search-input","searchSubmit":"#agent-search-submit","resultsSection":"#agent-search-results","productList":"#agent-product-list","productItem":".agent-product-item","productCard":".agent-product-card","productDetailLink":".agent-product-link","fetchMoreButton":"#agent-fetch-more"},"dataAttributes":{"productId":"data-agent-product-id","productSlug":"data-agent-product-slug","productName":"data-agent-product-name","productPrice":"data-agent-product-price","productBrand":"data-agent-product-brand","detailLinkHref":"data-agent-href"},"queryParams":"Page URL: ?q={query}&page={n}. For JSON search (no auth) use GET /api/search?q=...&page=1&count=20. Response: { data: { Products, hasMore } }."},{"path":"/agent/product/:slug","method":"GET","purpose":"Product detail. Full product data as machine-readable JSON, plus the add-to-cart form.","contentType":"text/html","forAgents":"Navigate to /agent/product/{slug}. Key content: definition list id=agent-product-meta ([data-agent-field] name, price, brand, store, availability = IN_STOCK | OUT_OF_STOCK). For complete data, read .textContent (NOT .innerHTML) of pre#agent-product-raw-json and JSON.parse it. Use product._id (not a plain id field) as the \"product\" value for cart and checkout. If variants is empty or omitted, omit variantId. To add to cart: pick a variant (select#agent-variant-select or [data-agent-variant-id] button), set input#agent-quantity-input, click button#agent-add-to-cart in form#agent-add-to-cart-form, then wait for [data-agent-cart-status=\"added\"].","selectors":{"article":"#agent-product-detail","meta":"#agent-product-meta","rawJson":"#agent-product-raw-json","description":"#agent-product-description","priceHistory":"#agent-product-price-history-list","addToCartForm":"#agent-add-to-cart-form","variantSelect":"#agent-variant-select","variantButton":"[data-agent-variant-id]","quantityInput":"#agent-quantity-input","addToCartButton":"#agent-add-to-cart","cartStatus":"[data-agent-cart-status]"},"dataAttributes":{"field":"data-agent-field","value":"data-agent-value","productId":"data-agent-product-id","productSlug":"data-agent-product-slug","variantId":"data-agent-variant-id","cartStatus":"data-agent-cart-status"},"cartStatusValues":["idle","adding","added","error"],"note":"Article has aria-details=agent-product-raw-json linking to the full JSON block."},{"path":"/agent/cart","method":"GET","purpose":"Cart review for browser agents.","contentType":"text/html","forAgents":"Cart rows live in #agent-cart-items; each row has data-agent-product-id, data-agent-variant-id, data-agent-quantity. Change qty via input#agent-cart-quantity-{index} + button#agent-cart-update-quantity-{index}; remove with button#agent-cart-remove-{index}. Cart is account-scoped. Click a#agent-proceed-to-checkout to go to /agent/checkout.","selectors":{"items":"#agent-cart-items","quantityInput":"#agent-cart-quantity-{index}","updateQuantity":"#agent-cart-update-quantity-{index}","remove":"#agent-cart-remove-{index}","proceedToCheckout":"#agent-proceed-to-checkout"},"dataAttributes":{"productId":"data-agent-product-id","variantId":"data-agent-variant-id","quantity":"data-agent-quantity"}},{"path":"/agent/checkout","method":"GET","purpose":"Shipping form for browser agents. Payment entry is confirmed by the user.","contentType":"text/html","forAgents":"Fill form#agent-checkout-form: #agent-first-name (firstName), #agent-last-name (lastName), #agent-email (email), #agent-address-line1 (addressFirst), #agent-city (city), #agent-state (state), #agent-zip (zipCode), select#agent-country (country, ISO 2-letter e.g. US). Click button#agent-submit-order. If your policy requires human confirmation for payment, stop after filling the form and prompt the user.","selectors":{"form":"#agent-checkout-form","firstName":"#agent-first-name","lastName":"#agent-last-name","email":"#agent-email","addressLine1":"#agent-address-line1","city":"#agent-city","state":"#agent-state","zip":"#agent-zip","country":"#agent-country","submitOrder":"#agent-submit-order"},"dataAttributes":{"checkoutStatus":"data-agent-checkout-status"}},{"path":"/api/search","method":"GET","purpose":"JSON product search. No authentication required.","contentType":"application/json","forAgents":"GET /api/search?q={query}&page={page}&count={count}. Response: { data: { Products: [{ _id, slug, name, price, ... }], hasMore } }.","responseShape":{"data":{"Products":"array of products (use _id and slug)","hasMore":"boolean"}}},{"path":"/api/agent/cart","method":"GET","purpose":"Read the API-key user cart (Bearer auth). Proxies to GET /api/v1/cart.","contentType":"application/json","forAgents":"GET with Authorization: Bearer <token>. Response: { status: \"success\", items, cart }. Use this for cart baseline before POST adds.","headers":{"Authorization":"Bearer <token>"},"responseShape":{"status":"success","items":"array of cart lines","cart":"full cart object"}},{"path":"/api/agent/cart","method":"POST","purpose":"Headless cart setup (Bearer auth). Proxies to POST /api/v1/cart.","contentType":"application/json","forAgents":"POST { items: [{ product, quantity, variantId? }] } with Authorization: Bearer <token>. product is product._id (or id) from search / agent-product-raw-json. Omit/null variantId defaults to product _id. Unknown products → 404; malformed ids → 400.","headers":{"Content-Type":"application/json","Authorization":"Bearer <token>"},"requestBody":{"items":"Array of { product: string, quantity: number, variantId?: string }. product is the product._id (same value as id). Omit variantId when the product has no variants (server defaults to _id)."},"responseShape":{"status":"success","items":"echo of items set in the cart"}},{"path":"/api/agent/payment-intent","method":"POST","purpose":"Create a Stripe PaymentIntent for the API-key user cart (Bearer auth). Proxies to POST /api/v1/payment-intent.","contentType":"application/json","forAgents":"POST with Authorization: Bearer <token>. Optional body: shippingState, shippingOptions, email, firstName, lastName, paymentMethod. Response: { status, clientSecret, paymentIntentId, stripeCustomerId, publishableKey }. Confirm with Stripe.js using publishableKey + clientSecret, then pass pm_… / pi_… to /api/agent/checkout. quantity on cart POST must be integer >= 1 (0 → 400). Empty items [] clears the cart.","headers":{"Content-Type":"application/json","Authorization":"Bearer <token>"},"responseShape":{"status":"success","clientSecret":"string","paymentIntentId":"string","stripeCustomerId":"string","publishableKey":"string — Stripe pk_… for confirming the PaymentIntent"}},{"path":"/api/agent/checkout","method":"POST","purpose":"Agent checkout. Sets the cart first (if items provided), then places the order in one call.","contentType":"application/json","forAgents":"Optional items set the cart (POST /api/v1/cart). Create PaymentIntent via POST /api/agent/payment-intent, confirm with Stripe, then place order with paymentMethodId + paymentIntent, offsetPerc (credits %; 0 = full card charge), formData (wins for address/email), shippingAddress (optional mirror).","headers":{"Content-Type":"application/json","Authorization":"Bearer <token>"},"requestBody":{"items":"Optional. Array of { product: string, quantity: number, variantId?: string }. product is the product._id. If present, cart is set first.","paymentMethodId":"string — Stripe pm_… after confirming the PaymentIntent from /api/agent/payment-intent","paymentIntent":"string — Stripe pi_… id after the PaymentIntent has succeeded","offsetPerc":"number? — percent of merchandise total to cover with Agora credits (0–100). Use 0 for full payment-method charge.","shippingAddress":"object { firstName, lastName, addressFirst, city, state, zipCode, country } — optional; formData wins for headless checkout","formData":"object { firstName, lastName, email, addressFirst, city, state, zipCode, country } — required for guest/headless; wins over shippingAddress"},"responseShape":{"status":"success","order":"order object (orderId / _id, status)"}},{"path":"/api/agent/orders/:orderId","method":"GET","purpose":"Order tracking. Proxies to GET /api/v1/order-tracking/:orderId.","contentType":"application/json","forAgents":"GET with Authorization: Bearer <token>. Proxies to GET /api/v1/order-tracking/{orderId} (orderCode or _id). Response: { orderId, status, trackingUrl, estimatedDelivery } or 404. Cross-user orders return 404.","headers":{"Authorization":"Bearer <token>"},"responseShape":{"orderId":"string","status":"string","trackingUrl":"string?","estimatedDelivery":"string?"}}],"usage":["1. Fetch GET /api/agent-routes to get this manifest.","2. To search: navigate to /agent/search?q={url_encoded_query}&page=1 (or fill #agent-search-input name=q and submit #agent-search-form); parse #agent-product-list .agent-product-item cards (data-agent-product-id / -slug / -name / -price); follow a.agent-product-link or data-agent-href to product detail. JSON alternative: GET /api/search?q=...&page=1&count=20 (no auth).","3. To get product detail: go to /agent/product/{slug}; read #agent-product-meta for key fields, or JSON.parse the .textContent (not .innerHTML) of pre#agent-product-raw-json. Cart and checkout items.product must be product._id (same value as id).","4. Browser agents (no API key): select a variant (#agent-variant-select or [data-agent-variant-id]), set #agent-quantity-input, click #agent-add-to-cart, wait for [data-agent-cart-status=\"added\"], open /agent/cart (use #agent-cart-quantity-{i} / #agent-cart-remove-{i} as needed), click #agent-proceed-to-checkout, fill #agent-checkout-form, click #agent-submit-order (\"Place order\"; hand off payment confirmation to the user if policy requires).","5. Programmatic agents: create a key at https://www.searchagora.com/developer-tools/api-keys (Premium — /pricing) and send Authorization: Bearer YOUR_API_KEY (Developer API base https://zues.searchagora.com/api/v1; see /agents.md).","6. Headless checkout: POST /api/agent/cart (optional), POST /api/agent/payment-intent → confirm with Stripe, then POST /api/agent/checkout with paymentMethodId + paymentIntent, offsetPerc (credits %; 0 default), formData (wins for address), shippingAddress optional.","7. To track order: GET /api/agent/orders/{orderId} with Bearer token; proxies to GET /api/v1/order-tracking/{orderId}."]}