Bookly · demo bookstore

Bookly Support API

A fully API-native order, shipping, returns and refunds system for building a customer support agent. No authentication, open CORS, 42 documented endpoints.

Conventions & rules

  • Success: { "data": ..., "meta": { "request_id" } }; errors use an RFC 9457-style envelope.
  • Money is integer cents. Orders accept UUID or BK-#####; customers accept UUID or email.
  • Lists paginate with limit (max 100) and offset.
  • Returns: 30-day window (90 days for damaged/wrong item), $4.99 label fee waived for damaged claims, ebooks non-returnable.
  • Cancellation allowed while processing or backordered.

Agent trace logging (required)

After every conversation the CX agent must POST a trace to /api/public/v1/agent-traces. Staff read these in the console under Decagon Convos. The same instructions are served in /api/public/tools.json, /llms.txt and the OpenAPI description.

## Logging your conversations back to Bookly (required after every call)

After you finish handling a customer, POST the whole conversation to `/api/public/v1/agent-traces`.
Bookly store staff review these traces to verify what you claimed you did, so log every turn and every tool call.

**When to log**
- Once, at the end of a conversation, with the complete `messages` array.
- If the conversation is still running, POST with `status: "in_progress"` and append later turns with `POST /api/public/v1/agent-traces/{id}/messages`.
- Never log the same conversation twice; reuse the returned `trace_number`.

**Required shape**
- `subject`: one short line describing the request (e.g. "Refund for damaged copy on BK-10005").
- `summary`: 1-3 sentences of what you did and why, including the reasoning behind any money movement.
- `customer_email` (and `order_id` / `ticket_id` when known) so the trace is queryable by customer and order.
- `intent` plus `intent_confidence` (0-1): what you believed the customer wanted and how sure you were.
- `resolution_confidence` (0-1): how confident you are that the outcome actually resolved the request. Log BOTH confidences on every trace.
- `outcome`: one of resolved | refund_issued | return_created | escalated | deflected | unresolved.
- `messages[]`: every turn, in order.

**Message formatting rules**
- `role`: customer | agent | tool | system | note. `speaker` is the display name shown in bold (defaults: "Customer", "Agent", "System").
- `occurred_at`: ISO-8601 UTC timestamp for each turn. Timestamps are rendered next to the bold speaker.
- Plain-language turns go in `content` as markdown; keep the customer's words verbatim.
- For every API call you made, add a `tool` message with `tool_name` (the tool/operation id), `tool_input` (the arguments) and `tool_output` (the trimmed response).
- EVERY agent (and tool) message MUST carry its own `intent_confidence` and `resolution_confidence` (0-1): the confidence that informed that specific reply. The console renders them as pie charts under each turn so staff can see the confidence trajectory across the conversation.
- Use `metadata` on a message for anything structured you want staff to see (policy id, rule that fired).
- Use a `note` role for internal reasoning that was never shown to the customer.

**Rendered format in the store console**
`**[2026-08-14T14:03:11Z] Customer:** where is my order?` — speaker bold, timestamp first, tool calls shown as collapsible JSON.

**Querying past conversations**
- `GET /api/public/v1/agent-traces?email=...` — everything you did for this customer before.
- `GET /api/public/v1/agent-traces?q=refund&outcome=refund_issued` — full-text search over subject, summary and transcript.
- `GET /api/public/v1/support/tickets?email=...&q=...` — past support tickets, including their event history.
- Always check prior traces and tickets before promising anything, so you do not contradict an earlier decision.

System

Health and discovery.

GET/api/public/v1/health

Liveness probe plus database connectivity check and API version.

Agent guidance: Call once at startup to confirm the API and dataset are reachable.

Try /api/public/v1/health
GET/api/public/v1/meta

Row counts, live sample identifiers (order numbers, emails, RMAs, tracking numbers), every enum value and the business-rule constants. This is the recommended bootstrap call for an agent.

Agent guidance: Fetch first so you can use real identifiers in later calls instead of guessing.

Try /api/public/v1/meta

Orders

Order lookup, cancellation and line items.

GET/api/public/v1/orders

Paginated order list with filters. Use `email` when a customer contacts support without an order number.

Agent guidance: Primary lookup when the customer gives an email address rather than an order number.

Try /api/public/v1/orders?limit=3&status=shipped
POST/api/public/v1/orders

Creates an order for an existing customer (or a brand-new one) and charges it. Books are matched by book_id, isbn or partial title; prices come from the catalog, so never send prices. Shipping: ground is free over $35.00 otherwise $4.99, expedited $12.99, overnight $24.99. Tax is 8.25% of the discounted subtotal. Stock is decremented, a charge transaction is written, and the response includes the full order plus a pricing breakdown.

Agent guidance: Use when a caller wants to buy or re-order a title. Load GET /api/public/v1/inventory first to confirm the exact ISBN and stock, then place the order. If a title is short on stock you get 409 conflict — read back the shortfall and retry with allow_backorder: true only after the customer agrees.

See request body in the OpenAPI spec
GET/api/public/v1/orders/{id}

Full order with customer, line items, shipments, returns, refunds and transactions embedded.

Agent guidance: The single richest call for answering 'where is my order?'.

Try /api/public/v1/orders/BK-10042
GET/api/public/v1/orders/{id}/items

Line items with the joined book record (format matters for return eligibility).

Agent guidance: Use the returned order_item_id values when creating a partial return.

Try /api/public/v1/orders/BK-10042/items
POST/api/public/v1/orders/{id}/cancel

Cancels an order and voids the authorization. Only allowed while the status is processing or backordered.

Agent guidance: Use for 'cancel my order'. If it returns 409, offer a return instead.

See request body in the OpenAPI spec

Shipping

Shipments, tracking events and reshipments.

GET/api/public/v1/orders/{id}/shipments

All shipments for the order, each with its full tracking event history.

Agent guidance: Answer delivery-timing questions and detect stalled tracking.

Try /api/public/v1/orders/BK-10042/shipments
POST/api/public/v1/orders/{id}/reship

Generates a new shipment and tracking number. Allowed when the order is lost_in_transit or shipped.

Agent guidance: Use for lost-in-transit packages after confirming tracking is stalled.

See request body in the OpenAPI spec
GET/api/public/v1/shipments/{tracking}

Fetch a shipment by tracking number or UUID, with its events and parent order.

Agent guidance: Direct tracking lookup when the customer pastes a tracking number.

Try /api/public/v1/shipments/1Z999AA10123456784

Returns

Eligibility, RMA creation and lifecycle.

POST/api/public/v1/orders/{id}/returns/eligibility

Deterministic eligibility check. Standard window is 30 days from delivery; damaged or wrong-item claims get 90 days and waive the $4.99 label fee. Ebooks are non-returnable.

Agent guidance: Always call this before creating a return so you can explain the outcome to the customer.

See request body in the OpenAPI spec
GET/api/public/v1/returns

Paginated returns with their items and parent order.

Agent guidance: Check whether a return already exists before creating a duplicate.

Try /api/public/v1/returns?limit=3
POST/api/public/v1/returns

Creates an RMA with a prepaid label and computes the expected refund. Rejects with 409 when the order is not eligible unless `override_eligibility` is true.

Agent guidance: Call after eligibility passes. `items` is optional — omit it to return every line on the order, or match lines by order_item_id, isbn or title. Set initiate_refund to open the refund in the same call.

See request body in the OpenAPI spec
POST/api/public/v1/returns/{rma}/receive

Moves the return to `received`, optionally issuing the refund immediately.

Agent guidance: Warehouse-side action; set auto_refund to close the loop in one call.

See request body in the OpenAPI spec
POST/api/public/v1/returns/{rma}/cancel

Cancels an open RMA. Fails with 409 once the return is refunded.

Agent guidance: Use when the customer decides to keep the item.

See request body in the OpenAPI spec

Refunds

Refunds, store credit and the money ledger.

GET/api/public/v1/refunds

Paginated refunds with their parent order.

Agent guidance: Confirm whether money already went back before promising a new refund.

Try /api/public/v1/refunds?limit=3
POST/api/public/v1/refunds

Issues a full or partial refund, records the matching ledger transaction, credits store credit when requested and flips the order to `refunded` once fully covered. Over-refunding is rejected.

Agent guidance: Use for goodwill refunds and post-return settlements.

See request body in the OpenAPI spec
GET/api/public/v1/refunds/{id}

Fetch a refund by refund number (RF-12345) or UUID.

Agent guidance: Give the customer the exact refund amount and timing.

Try /api/public/v1/refunds/RF-12345
PATCH/api/public/v1/refunds/{id}

Moves a refund to any status. Settling (`succeeded`) writes the ledger transaction, applies store credit and flips the order to refunded once fully covered; cancelling or failing a settled refund writes a reversal. Every change appends to the refund timeline (`events`).

Agent guidance: Use to release a `pending_return` refund early for a loyal customer, or to cancel a refund the customer no longer wants.

See request body in the OpenAPI spec

Customers

Customer identity and order history.

GET/api/public/v1/customers

Search customers by email, fuzzy name/email query or loyalty tier.

Agent guidance: Identity resolution before touching order data.

Try /api/public/v1/customers?limit=3

Catalog

Book catalog search.

GET/api/public/v1/inventory

Returns the entire book catalog in one call — every title with author, format, category, price and current stock — plus per-author rollups and totals in `meta`. No search or pagination.

Agent guidance: Call this once at the start of a conversation to load the whole catalog into context; then answer stock, author and price questions without further lookups.

Try /api/public/v1/inventory
GET/api/public/v1/books

Search books by title, author or ISBN with category, format and stock filters.

Agent guidance: Recommend replacements or confirm stock before promising a reship.

Try /api/public/v1/books?q=the&limit=3

Knowledge

Policies and FAQs for grounded answers.

GET/api/public/v1/policies

Shipping, returns, refunds, privacy and account policies in full text.

Agent guidance: Ground policy answers in this text instead of improvising.

Try /api/public/v1/policies
GET/api/public/v1/policies/{slug}

Fetch a single policy document by slug, e.g. `returns`.

Agent guidance: Quote the exact clause back to the customer.

Try /api/public/v1/policies/returns
GET/api/public/v1/faqs

Curated question/answer pairs for common support topics.

Agent guidance: First stop for general questions that need no account data.

Try /api/public/v1/faqs?q=shipping

Support

Tickets and simulated support actions.

GET/api/public/v1/support/tickets

Paginated, filterable ticket history with customer, order and full event history embedded — the record of every previous support interaction.

Agent guidance: Search this before acting: check for an existing open ticket and read what was already promised to the customer.

Try /api/public/v1/support/tickets?limit=3
POST/api/public/v1/support/tickets

Opens a ticket, linking the customer by email and optionally an order.

Agent guidance: Escalation path when you cannot resolve the request with the other endpoints.

See request body in the OpenAPI spec
PATCH/api/public/v1/support/tickets/{id}

Change status, priority or record a resolution. Accepts TCK number or UUID.

Agent guidance: Close the ticket once the customer confirms the issue is resolved.

See request body in the OpenAPI spec
POST/api/public/v1/support/actions/password-reset

Simulates sending a reset email. Always returns success so account existence is never leaked.

Agent guidance: Standard answer for 'I can't log in'.

See request body in the OpenAPI spec
POST/api/public/v1/support/actions/address-change

Updates the shipping address while the order is still pending or processing.

Agent guidance: Use before the order ships; afterwards offer a return or intercept instead.

See request body in the OpenAPI spec
GET/api/public/v1/support/tickets/{id}

Full ticket with customer, order and the complete event history (messages, notes, resolutions).

Agent guidance: Read the ticket history before replying so you do not repeat or contradict a previous agent.

Try /api/public/v1/support/tickets/TCK-12345

Agent traces

Log every CX-agent conversation back to Bookly and search past conversations. Required after each call.

POST/api/public/v1/agent-traces

Records one CX-agent conversation (every turn plus every tool call) so Bookly staff can audit what the agent did. Call this at the end of every conversation. Formatting contract: each message carries `role`, an optional bold `speaker`, an ISO-8601 `occurred_at` timestamp, markdown `content`, and — for tool turns — `tool_name`, `tool_input` and `tool_output`. Anything structured goes in `metadata`.

Agent guidance: Mandatory after every customer interaction. Include a plain-language `summary` explaining the reasoning behind any refund, return or escalation.

See request body in the OpenAPI spec
GET/api/public/v1/agent-traces

Paginated, searchable history of every logged CX-agent conversation, with all messages and tool calls embedded.

Agent guidance: Check this before answering: if you already promised something to this customer, honour it instead of re-deciding.

Try /api/public/v1/agent-traces?limit=5
GET/api/public/v1/agent-traces/{id}

Full trace with customer, order, ticket and the ordered message list including tool inputs/outputs.

Agent guidance: Pull the exact wording of a previous promise before continuing a follow-up conversation.

Try /api/public/v1/agent-traces/TRC-100001
POST/api/public/v1/agent-traces/{id}/messages

Adds more messages to an existing trace, in order, and recomputes counts, duration and the transcript.

Agent guidance: Use for long-running conversations you logged with status in_progress.

See request body in the OpenAPI spec
PATCH/api/public/v1/agent-traces/{id}

Revise the summary, outcome, sentiment, tags or status of an already-logged conversation.

Agent guidance: Close out an in_progress trace or correct the recorded outcome.

See request body in the OpenAPI spec