bitroadbitroad
API reference

Seller API

Programmatic listing, fulfilment, returns and review endpoints.

Sellers & agent developers

Tool names + descriptions are public API per api-mcp.md. The OpenAPI 3.1 spec is regenerated on every change and smoke-tested.

Auth

Either:

  • Bearer br_ik_* whose delegation.kind in ('seller','both') and whose delegation.seller_id matches the resource being touched, or
  • Bearer br_pk_* (platform) — refused, sellers are managed by their owning principal not platform staff, or
  • authjs.session-token cookie for the seller-owner principal — unconditionally authorised (humans bypass the seller-action gate).

Listings

Action REST MCP Idempotent?
List GET /seller/listings seller_list_listings n/a
Get GET /seller/listings/{id} seller_get_listing n/a
Create POST /seller/listings seller_create_listing yes
Update POST /seller/listings/{id} seller_update_listing yes
Archive POST /seller/listings/{id}/archive seller_archive_listing yes
Stock POST /seller/listings/{id}/stock seller_update_stock yes

Stock body: { stock?: integer, delta?: integer }. Exactly one is required. Resulting count must remain ≥ stock_reserved.

Orders

Action REST MCP
List GET /seller/orders seller_list_orders
Get GET /seller/orders/{id} seller_get_order
Mark shipped POST /seller/orders/{id}/ship seller_mark_shipped
Mark delivered POST /seller/orders/{id}/deliver seller_mark_delivered
Attach tracking POST /seller/orders/{id}/tracking seller_attach_tracking
Cancel POST /seller/orders/{id}/cancel (none — REST only)

mark_shipped is idempotent on (order_id, tracking_number): a second call with the same pair returns the original detail. A second call with a different tracking number on an already-shipped order returns 409 already_shipped.

mark_delivered is the seller-declared delivery confirmation used while no carrier API is wired (see carriers.md). Empty body; only valid from shipped (409 invalid_transition otherwise); already-delivered is a no-op success. It fires the order_delivered notification to the buyer, who can dispute a false declaration. Delegation-gated on the same ship action kind as mark_shipped.

cancel (dashboard cancel) runs the shared cancel-and-refund engine: full refund, only valid from paid_awaiting_fulfillment — a shipped order stays on the returns/disputes rails.

Returns

Action REST MCP
List GET /seller/returns seller_list_returns
Get GET /seller/returns/{id} seller_get_return
Accept POST /seller/returns/{id}/accept seller_accept_return
Reject POST /seller/returns/{id}/reject seller_reject_return
Attach label POST /seller/returns/{id}/label (none — owner session only)

accept_return marks the return received and runs the shared refund engine in the same call — the return lands at refunded and the buyer is refunded at most once, even if a carrier webhook for the same return races or replays.

reject_return requires inspection_notes (1–2000 chars). It refuses if the return has already refunded.

label is the seller's prepaid return-label upload under the uniform policy (return shipping is seller-funded, due within 2 business days of approval). Multipart, single file, PDF/PNG/JPEG, 10 MB cap; seller-owner session only — not exposed to agent keys.

Reviews

Action REST MCP
List (seller-scoped) GET /seller/reviews seller_list_reviews
Respond POST /seller/reviews/{id}/respond seller_respond_to_review
Buyer create POST /orders/{id}/review (none — REST only)

Reviews are one-per-order. Responses are post-once; subsequent attempts return 409 already_responded.

Errors specific to seller actions

Code When
action_not_in_scope Delegation kind is buyer and the action is a seller_action.
seller_action_not_allowed Action not in seller_actions_allowed.
seller_not_owned_by_delegation Cross-seller mismatch on the delegation binding.
seller_not_registered principal_self with no seller record.
product_denied / product_not_allowed Product-list scoping.
seller_action_requires_confirmation Restricted-goods listing under allow_with_confirmation (hard-deny).
product_has_pending_intents Archive refused while pending purchase intents exist.
stock_below_reserved Stock update would dip below stock_reserved.
already_shipped Different tracking on already-shipped order.
already_refunded Reject attempt on a refunded return.
already_responded Second response on a review.
order_not_delivered Review attempt on a non-delivered order.
already_reviewed Second review on the same order.

Idempotency

Every write requires Idempotency-Key. Replay returns the original (status, body). Hash mismatch → 409 idempotency_conflict. Scope: (key, route, actor_principal_id).

Webhook events

The event_kinds filter on webhook_endpoints is the opt-in mechanism; an empty array accepts every kind delivered to the agent instance.