---
name: aurastack-reseller
description: Use when integrating, testing or operating the AuraStack Reseller API - listing products, quoting, placing orders paid from an AuraStack balance, handling order statuses and errors, the sandbox and end-to-end tests. Triggers on "AuraStack", "aurastack.link", "sk_sandbox_", "sk_live_", "sk_aura_", "resell AuraStack products".
---

# AuraStack Reseller API

Base URL https://aurastack.link/api/v1. Key in AURASTACK_API_KEY, sent as
Authorization: Bearer $AURASTACK_API_KEY. Contract: https://aurastack.link/api/v1/openapi.json
(read it for exact fields). Full guide: https://aurastack.link/docs/api.md

## Hard rules

1. Work with the sandbox key (sk_sandbox_...) until the user says, in this conversation, to go
   live. Sandbox orders are never charged. Never place a live order to "check it works".
2. Keys are server-side only. Never put a key in browser code, a mobile app, a URL or a log.
3. One Idempotency-Key per customer purchase (for example the shop's own order id).
   Retry with the same key and the identical body: the customer is never charged twice.
4. Never log or print delivery.items. Store them only where the shop keeps the order.

## The purchase flow

1. GET /products (follow next_cursor until null) or GET /products/{id}.
2. POST /quotes { product_id, quantity } right before ordering. Show the price to the buyer.
3. POST /orders with Idempotency-Key and
   { product_id, quantity, expected_unit_price: <quote.unit_price>, billing: { country } }.
   billing is the reseller's own (they are AuraStack's customer). Companies add
   is_company: true (JSON boolean), company_name, vat_number (EU numbers with their country prefix).
4. Read the order: delivered -> hand delivery.items to the buyer. processing -> poll
   GET /orders/{id} every 10 to 30 s.

## Statuses

| status | charged | do |
|---|---|---|
| pending_payment | no | retry the same request with the same Idempotency-Key |
| payment_captured, processing | yes | poll the order |
| delivered | yes | final: deliver delivery.items |
| failed + failure_code INSUFFICIENT_BALANCE | no | final: top up, new Idempotency-Key |
| failed + other failure_code | yes | under review: tell the buyer, do not refund yet |
| refunded | refunded | final: money is back on the balance |

## Errors (branch on HTTP status and error.type)

- 400 invalid_request_error: fix the request. 401: bad key, stop.
- 402 payment_error: balance too low, nothing charged.
- 409 price_changed: error.unit_price is the new price; re-quote and confirm with the buyer.
- 409 invalid_request_error: out of stock or unavailable; offer another product.
- 422 idempotency_error: key reused for a different product or quantity.
- 429 rate_limit_error: wait, then retry with the same Idempotency-Key.
- 500, 503: retry with the same Idempotency-Key and backoff (a few times at most).
- 502 with an order body: read status and failure_code; the buyer may have been charged.

## Sandbox and end-to-end tests

The sandbox behaves like live: catalog prices (cached for about a minute) and real stock, same validation, VAT and
idempotency, and a sandbox balance that starts at 1000.00 and goes down with each order.
The developer creates the sandbox key in the AuraStack dashboard (Sandbox panel).
- Start every test run with POST /sandbox/reset (balance back to 1000.00, sandbox orders cleared).
- Force a case with header AuraStack-Sandbox-Outcome on POST /orders:
  delivered | processing | on_hold | refunded | insufficient_balance | price_changed | out_of_stock.
- Write one end-to-end test per value before going live. Keep the key in CI secrets.
- Sandbox writes are limited to 120 per minute per account, sandbox orders to 2000 per 24 hours.

## Going live

Swap sk_sandbox_ for a live key (sk_live_), remove the AuraStack-Sandbox-Outcome header, top up the
balance. Ask the user before the first live order.
