> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tybritelabs.com/llms.txt
> Use this file to discover all available pages before exploring further.

# List your purchase orders



## OpenAPI

````yaml /openapi.yaml get /v1/b2b/purchase-orders
openapi: 3.1.0
info:
  title: Galactic Core API
  version: 1.0.0
  description: >
    # Galactic Core — The Programmable Commerce Platform
      
    **By Tybrite Labs**
      
    Galactic Core is the programmable interface layer that transforms GalacticOS
    into a globally 

    accessible Backend-as-a-Service (BaaS) for commerce. Rather than rebuilding
    commerce logic 

    from scratch, Galactic Core re-exposes the operational depth of a
    production-grade retail 

    system through clean, versioned REST APIs and real-time webhooks.
      
    ## Why Galactic Core?
      
    **Commerce Infrastructure, Not Commerce Software**
      
    Galactic Core is not an application or a dashboard—it is **infrastructure**.
    The programmable 

    foundation upon which commerce applications are built. Developers inherit
    years of operational 

    hardening through simple API calls:
      
    - **Inventory management** with stock tracking and reorder logic

    - **Order processing** with payment reconciliation and fulfillment workflows

    - **Customer analytics** with RFM segmentation and purchase history

    - **Double-entry accounting** with automatic journal entries

    - **Multi-provider payments** (Stripe, PayPal, Paystack, M-Pesa)

    - **AI-powered recommendations** using semantic embeddings

    - **Dynamic pricing** with hierarchical discount rules
      
    ## Ship in Days, Not Months
      
    Stop rebuilding the same commerce infrastructure for every project. Galactic
    Core provides 

    production-ready primitives that eliminate months of development work:
      
    ✅ **No data silos** — All channels share the same operational reality  

    ✅ **No duplicated logic** — Business rules are centralized and consistent  

    ✅ **No fragile integrations** — Everything is part of one coherent system  

    ✅ **Complete auditability** — Every state change is tracked and traceable  
      
    ## Platform Capabilities
      
    **Core Commerce**

    - Products, Collections, Categories, Specifications

    - Orders with automatic inventory sync and accounting

    - Customers with RFM analytics and store metrics

    - Multi-provider payment processing with webhook automation
      
    **Advanced Features**

    - AI-powered semantic search and recommendations

    - Dynamic pricing engine with hierarchical rules

    - Cart & wishlist persistence with anonymous session support

    - Customer authentication with automatic record linking

    - Gift cards with full accounting integration

    - Promotions with usage tracking and discount attribution

    - Commerce-aware CMS with shoppable content
      
    **Global by Design**

    - Multi-currency support (135+ currencies via Stripe)

    - Regional payment methods (mobile money for Africa)

    - Multi-store architecture with complete data isolation

    - Edge-optimized delivery (10-50ms response times)
      
    ## Authentication
      
    All API requests require authentication using an API key in the
    `Authorization` header:
      
    ```

    Authorization: Bearer tybrite_sk_live_YOUR_API_KEY

    ```
      
    ### API Key Types
      
    **Secret Keys** (Server-Side Only)

    - Production: `tybrite_sk_live_*`

    - Sandbox: `tybrite_sk_test_*`

    - Full read/write access

    - ⚠️ Never expose in client-side code

    - **Required for:**
      - All write operations (POST, PUT, PATCH, DELETE)
      - Authentication endpoints (register, login, logout, etc.)
      - Payment verification (`POST /v1/payments/verify`)
      - AI recommendations (`POST /v1/recommendations`)
      - Order management
      - Customer management
      
    **Publishable Keys** (Client-Safe)

    - Production: `tybrite_pk_live_*`

    - Sandbox: `tybrite_pk_test_*`

    - Read-only access (GET requests only)

    - ✅ Safe for client-side use

    - **Allowed for:**
      - Product browsing
      - Search (both GET and POST semantic search)
      - Category/taxonomy browsing
      - CMS content retrieval
      - Pricing queries
      - Shipping calculations
      - Cart viewing (read-only)
      
    ### Key Type Enforcement
      
    Attempting to use a publishable key for write operations or restricted
    endpoints will return:

    ```json

    {
      "error": {
        "code": "forbidden",
        "message": "This operation requires a secret key. Publishable keys have read-only access.",
        "hint": "Use a secret key (tybrite_sk_*) for write operations"
      }
    }

    ```

    HTTP Status: 403 Forbidden
      
    ### Obtaining API Keys
      
    Generate API keys from your Tybrite dashboard under the Integrations page
    (Developer section).
      
    ## Environments


    The API uses a single endpoint (`https://api.tybritelabs.com`) with the
    environment determined by your API key prefix:

    - Use `tybrite_*_live_*` keys for production data

    - Use `tybrite_*_test_*` keys for sandbox/testing data


    Sandbox and production data are fully isolated — orders, customers, carts,
    and wishlists created with a test key are only visible to other test keys.
    Payment providers are automatically switched to test mode when using a
    sandbox key, regardless of your store's payment settings.


    Every authenticated response includes a `Tybrite-Environment` header
    confirming which environment resolved.


    ## Technical Features
      
    - **Ultra-Low Latency**: 10-50ms response times via edge caching

    - **Multi-tier caching** for low-latency reads.

    - **Idempotency Protection**: Prevent duplicate orders on retry

    - **Field Filtering**: Request only the fields you need (50-90% bandwidth
    reduction)

    - **Automatic Accounting**: Double-entry journal entries for all
    transactions

    - **Webhook Automation**: Real-time payment status updates and order
    processing


    ## Rate Limiting & Usage Quota


    Two independent controls protect the API. They return **different `429`
    codes** — handle them

    differently:


    | `429` code | What it means | `Retry-After` behavior | Counts toward your
    monthly quota? |

    | --- | --- | --- | --- |

    | `rate_limited` | An **abuse throttle** tripped (too many requests, too
    fast, from one client or key). Responses carry an `X-RateLimit-Scope: abuse`
    header. | Transient — slow down and retry shortly | **No** — throttled
    requests never consume your plan's monthly allowance |

    | `quota_exceeded` | You've reached your plan's **monthly request
    allowance**. | Resolves on the next monthly cycle, or sooner if you upgrade
    | n/a (this *is* the monthly meter) |


    ### Abuse rate limits (`rate_limited`)


    These are flat per-client throttles (not tied to your plan tier):


    **Publishable keys:**

    - 1,000 requests/hour per IP address

    - 10,000 requests/hour and 50,000 requests/day per API key


    **Secret keys:**

    - 10,000 requests/hour and 100,000 requests/day per API key


    ### Monthly usage quota (`quota_exceeded`)


    Your plan includes a monthly request allowance, reset on the 1st of each
    month (UTC):


    - **Starter:** 100,000 requests/month

    - **Growth:** 1,000,000 requests/month

    - **Premium:** 5,000,000 requests/month

    - **Enterprise:** unmetered


    (During a free trial the allowance is one-fifth of the plan.)
    Abuse-throttled requests are **not**

    counted against this allowance, so a traffic spike or scraping attempt can't
    quietly burn through

    your plan.


    ### Endpoint-Specific Limits


    **Payment Operations** (Additional limit on top of the above):

    - `POST /v1/payments/initialize`: 100 requests/hour per API key

    - Applies to both publishable and secret keys

    - Prevents payment spam and fraud attempts

    - Returns `429 rate_limited` if exceeded


    **Order Operations** (Enforced via idempotency):

    - `POST /v1/orders`: Requires `Idempotency-Key` header

    - `PATCH /v1/orders/:id`: Requires `Idempotency-Key` header

    - Duplicate keys return existing order/state (not counted against rate
    limits)

    - Prevents accidental duplicate orders and duplicate update processing


    **Authentication Operations**:

    - All auth endpoints: 10 requests/minute per IP address

    - Prevents brute force attacks

    - Applies to login, register, password reset, etc.


    Rate limit headers are included in responses:

    - `X-RateLimit-Limit`: Maximum requests allowed

    - `X-RateLimit-Remaining`: Requests remaining

    - `X-RateLimit-Reset`: Unix timestamp when the limit resets

    - `X-RateLimit-Scope: abuse`: present only on `rate_limited` responses
    (distinguishes an abuse
      throttle from the monthly quota)

    When an abuse limit is exceeded, the API returns HTTP 429 with error
    details:

    ```json

    {
      "error": {
        "code": "rate_limited",
        "message": "Too many requests for this API key. Please slow down and try again shortly.",
        "remaining": 0,
        "reset": 1739750400
      }
    }

    ```


    ## Special Headers


    ### Idempotency-Key (Required for Order Operations)


    **Endpoints:** `POST /v1/orders`, `PATCH /v1/orders/:id`


    Prevents duplicate order creation and duplicate update processing on network
    retries. If you retry a request with the same 

    idempotency key, the API returns the existing order/state instead of
    re-processing.


    ```

    POST /v1/orders

    Idempotency-Key: order-2026-02-16-abc123
      
    PATCH /v1/orders/922d235e-48c9-4933-abcd-88cb2a264f86

    Idempotency-Key: update-shipping-922d235e-1771524100

    ```


    **Requirements:**

    - Must be unique per operation (use different keys for create vs update)

    - Recommended formats:
      - Order creation: `order-{date}-{unique-id}`
      - Order updates: `update-{operation}-{order_id}-{timestamp}`
    - Stored for 24 hours

    - Returns existing order/state if key matches


    ### x-auth-token (Required for Customer Authentication)


    **Endpoints:**

    - `GET /v1/auth/me` - Get current authenticated customer

    - `POST /v1/auth/update-password` - Update customer password


    Contains the authentication token obtained from login/register endpoints.


    ```

    GET /v1/auth/me

    Authorization: Bearer tybrite_sk_live_YOUR_API_KEY

    x-auth-token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

    ```


    **Flow:**

    1. Customer logs in via `POST /v1/auth/login`

    2. Response includes `access_token`

    3. Use `access_token` as `x-auth-token` header value

    4. Token expires after session timeout (default 1 hour)


    ### X-Session-Id (Optional for Anonymous Carts)


    **Endpoints:** All cart endpoints (`/v1/cart/*`)


    Enables anonymous cart functionality before customer authentication.
    Generate a unique 

    session ID on the client and include it in cart requests.


    ```

    POST /v1/cart/items

    Authorization: Bearer tybrite_pk_live_YOUR_API_KEY

    X-Session-Id: session-abc123-xyz789

    ```


    **Behavior:**

    - If `X-Session-Id` provided: Cart associated with session (anonymous)

    - If `customer_id` provided: Cart associated with customer account

    - If both provided: `customer_id` takes precedence

    - If neither provided: Returns 400 error


    **Session Management:**

    - Generate UUID or random string on client

    - Store in localStorage/sessionStorage

    - Persist across page reloads

    - When customer logs in, migrate cart using `customer_id`


    ### Tybrite-Environment (Response Header)


    Every authenticated response includes a `Tybrite-Environment` header that
    confirms which environment your API key resolved to. Use this to verify that
    test keys are hitting sandbox data and live keys are hitting production
    data.


    ```

    Tybrite-Environment: sandbox

    ```


    Possible values: `production`, `sandbox`.


    ## Caching & Performance


    ### ETag Support


    All GET endpoints support ETag caching for efficient revalidation:


    ```

    # First request

    GET /v1/products/abc-123

    Response: 200 OK, ETag: "a1b2c3d4"


    # Subsequent request

    GET /v1/products/abc-123

    If-None-Match: "a1b2c3d4"

    Response: 304 Not Modified (no body)

    ```


    ### Cache Headers


    - `ETag`: Resource version identifier

    - `Cache-Control`: Caching directives

    - `X-Cache`: Cache status (HIT, MISS, HIT-304)


    ## Field Filtering


    Request only specific fields to reduce bandwidth:


    ```

    GET /v1/products?fields=id,name,price,stock

    ```


    Supports nested fields with dot notation:


    ```

    GET /v1/products?fields=id,name,attributes.color,attributes.size

    ```


    ## Error Handling


    All errors follow a consistent format:


    ```json

    {
      "error": {
        "code": "error_code",
        "message": "Human-readable error message",
        "details": "Additional context (optional)"
      }
    }

    ```


    ### Common Error Codes


    - `unauthorized` (401): Invalid or missing API key

    - `forbidden` (403): API key lacks required permissions

    - `not_found` (404): Resource not found

    - `invalid_request` (400): Malformed request or missing fields

    - `rate_limited` (429): Abuse throttle tripped — too many requests too fast
    (carries `X-RateLimit-Scope: abuse`; not counted against your monthly quota)

    - `quota_exceeded` (429): Monthly plan request allowance reached

    - `server_error` (500): Internal server error

    - `service_unavailable` (503): Service temporarily unavailable


    ## Idempotency


    Order creation supports idempotency to prevent duplicates on retry:


    ```

    POST /v1/orders

    Idempotency-Key: order-2026-02-03-abc123

    ```


    Retrying with the same key returns the existing order instead of creating a
    duplicate.


    ## Pagination


    List endpoints are **cursor-based**. Pass a `limit` (page size), and follow
    the

    `pagination.next_cursor` from each response to fetch the next page — there
    is no

    numeric `offset` or page number.


    ```

    GET /v1/products?limit=50

    GET
    /v1/products?limit=50&cursor=eyJwcm9kdWN0X2lkIjoiZDhjZWEyNzctOWJiNi00OTQyIn0=

    ```


    Each response carries a `pagination` object:


    ```json

    {
      "products": [...],
      "pagination": {
        "limit": 50,
        "has_more": true,
        "next_cursor": "eyJwcm9kdWN0X2lkIjoiZDhjZWEyNzctOWJiNi00OTQyIn0="
      }
    }

    ```


    When `has_more` is `false`, `next_cursor` is `null` and you've reached the
    last page.

    Cursors are opaque — pass them back verbatim; don't construct or parse them.
  contact:
    name: Galactic Core API Support - Tybrite Labs
    email: support@tybritelabs.com
    url: https://tybritelabs.com
  license:
    name: Proprietary
    url: https://tybritelabs.com/terms-of-service
servers:
  - url: https://api.tybritelabs.com
    description: Production API
security:
  - BearerAuth: []
tags:
  - name: System
    description: API information and health checks
  - name: Authentication
    description: >
      Customer authentication and session management.
        
      **⚠️ SECRET KEY REQUIRED**: All authentication endpoints require a secret
      key (tybrite_sk_*).

      Publishable keys will return 403 Forbidden.
        
      These endpoints manage customer accounts, login sessions, password resets,
      and OTP verification.

      Use these to build customer-facing authentication flows in your
      storefront.
        
      **Special Headers:**

      - `x-auth-token`: Required for `GET /v1/auth/me` and `POST
      /v1/auth/update-password`

      - Contains the authentication token from login/register response

      - Token expires after session timeout (default 1 hour)
        
      **Rate Limiting:**

      - All authentication endpoints: 10 requests/minute per IP address

      - Prevents brute force attacks on customer accounts
  - name: Products
    description: Product catalog management
  - name: Orders
    description: >
      Order lifecycle management with automatic inventory sync and accounting.
        
      **Special Headers:**

      - `Idempotency-Key`: **REQUIRED** for `POST /v1/orders` and `PATCH
      /v1/orders/:id`
        - Prevents duplicate order creation and duplicate update processing on network retries
        - Recommended formats:
          - Order creation: `order-{date}-{unique-id}`
          - Order updates: `update-{operation}-{order_id}-{timestamp}`
        - Stored for 24 hours
        - Retrying with same key returns existing order/state (not counted against rate limit)
      - `X-Timestamp`: **REQUIRED** for `POST /v1/orders` and `PATCH
      /v1/orders/:id`
        - Unix timestamp in seconds (current time)
        - Must be within 5 minutes of server time
        - Used to prevent replay attacks
      - `X-Signature`: **REQUIRED** for `POST /v1/orders` and `PATCH
      /v1/orders/:id`
        - HMAC-SHA256 signature of payload (timestamp + "." + request_body), base64-encoded
        - Sign using your HMAC secret from the Integrations page (Developer section)
        - Requests with invalid/missing signatures return 401 Unauthorized
        
      **Automatic Processing:**

      - Inventory automatically decremented when payment_status changes to
      'paid'

      - Double-entry accounting journal entries created automatically

      - Payment status tracked and updated via webhooks

      - Gift card redemptions and promotion usage tracked with idempotency
      protection
  - name: Customers
    description: Customer profile management
  - name: Cart & Wishlist
    description: |
      Shopping cart and wishlist operations with anonymous session support.
        
      **Special Headers:**
      - `X-Session-Id`: Optional header for anonymous cart functionality
      - Generate a unique session ID on the client (UUID or random string)
      - Store in localStorage/sessionStorage for persistence
      - When customer logs in, migrate cart by providing `customer_id` instead
        
      **Cart Association:**
      - If `X-Session-Id` provided: Cart associated with session (anonymous)
      - If `customer_id` provided: Cart associated with customer account
      - If both provided: `customer_id` takes precedence
      - If neither provided: Returns 400 error
        
      **Use Cases:**
      - Anonymous browsing: Use `X-Session-Id` before customer authentication
      - Logged-in customers: Use `customer_id` parameter
      - Cart migration: Switch from session to customer_id after login
  - name: Search
    description: >
      Semantic search with AI embeddings and simple text search.
        
      **Key Type Support:**

      - `GET /v1/search` (simple text search): Both secret and publishable keys
      allowed

      - `POST /v1/search` (semantic search): Both secret and publishable keys
      allowed
        
      Note: Despite using POST method, semantic search is a read-only operation
      and works

      with publishable keys. The POST method is used to support complex request
      bodies.
  - name: Recommendations
    description: >
      AI-powered product recommendations using semantic embeddings and
      collaborative filtering.
        
      **⚠️ SECRET KEY REQUIRED**: Recommendation generation requires a secret
      key (tybrite_sk_*).

      Publishable keys will return 403 Forbidden.
        
      This restriction protects the computational resources and AI model access
      used for

      generating personalized recommendations.
  - name: Discovery
    description: >
      Windowed storefront discovery lists derived from live shopper signals —
      most-viewed,

      most-added-to-cart, and best-converting products over a time window (1h /
      1d / 7d / 30d).

      Use them to power "Popular now" shelves, "Trending in carts" sections, and
      PDP "hot" badges.


      Publishable-key accessible (safe in a browser/app) and available on every
      plan. Distinct from

      Recommendations: these are simple, non-personalized signal rankings, not
      the ML engine.
  - name: Events
    description: >
      Storefront interaction events (product views, add-to-cart,
      add-to-wishlist). These power the

      `next` recommendation type — the products a shopper is most likely to view
      or add next based

      on their current session. Publishable keys are accepted so events can be
      sent from the browser.
  - name: Tax
    description: >
      Tax estimation for checkout. Preview the tax for a shipping destination
      and cart before placing

      an order, so the storefront can show and charge the final tax-inclusive
      total. Publishable keys

      are accepted so the estimate can be fetched from the browser during
      checkout.
  - name: Analytics
    description: >
      First-party storefront analytics capture. Fire a lightweight page-view /
      session-start event

      from the storefront on each route change; device, browser, and approximate
      location are derived

      automatically from the request. These events power the merchant's Store
      Analytics dashboard

      (traffic, audience, conversion funnel, and revenue-by-source). Publishable
      keys are accepted so

      events can be sent directly from the browser.
  - name: Taxonomy
    description: Categories and subcategories
  - name: CMS
    description: Content management (posts, lookbooks)
  - name: Payments
    description: >
      Multi-provider payment processing (Stripe, PayPal, Paystack, M-Pesa).
        
      **Special Headers:**

      - `Idempotency-Key`: **REQUIRED** for `POST /v1/payments/initialize`
        - Unique key to prevent duplicate payment initialization (e.g., payment-{timestamp}-{random})
        - If you retry with the same key, the original payment initialization is returned
        - Prevents duplicate charges on network retries
      - `X-Timestamp`: **REQUIRED** for `POST /v1/payments/initialize`
        - Unix timestamp in seconds (current time)
        - Must be within 5 minutes of server time
        - Used to prevent replay attacks
      - `X-Signature`: **REQUIRED** for `POST /v1/payments/initialize`
        - HMAC-SHA256 signature of payload (timestamp + "." + request_body), base64-encoded
        - Sign using your HMAC secret from the Integrations page (Developer section)
        - Requests with invalid/missing signatures return 401 Unauthorized
        
      **Key Type Requirements:**

      - `GET /v1/payments/methods`: Both secret and publishable keys allowed

      - `POST /v1/payments/initialize`: Secret key required

      - `POST /v1/payments/verify`: **SECRET KEY REQUIRED** (read operation but
      sensitive)
        
      Payment verification requires a secret key because it accesses sensitive
      payment status

      information that should not be exposed to client-side code.
        
      **Rate Limiting:**

      - Payment initialization has an additional rate limit of 100 requests/hour
      per API key

      - This is on top of the standard abuse limits (publishable: 1,000/hour per
      IP + 10,000/hour & 50,000/day per key; secret: 10,000/hour & 100,000/day
      per key)

      - Exceeding any of these returns `429 rate_limited` (carries
      `X-RateLimit-Scope: abuse`; not counted against your monthly quota)

      - Prevents payment spam and fraud attempts
  - name: Shipping
    description: Shipping zones and delivery cost calculation
  - name: Pricing
    description: Dynamic pricing engine
  - name: Promotions
    description: Marketing promotions and discounts
  - name: Gift Cards
    description: Gift card management
  - name: Messaging
    description: Real-time customer support messaging
  - name: GC Connect
    description: >
      Hosted authorization flow for connecting third-party tools to a merchant's
      store.


      **Connect your GC Store** lets developers build integrations where
      merchants

      authorize access with a single click — no API key copying required. The
      result

      is a permanent key pair scoped to the merchant's store and the permissions
      they

      granted.


      **Flow overview:**

      1. Redirect the merchant to the consent page with your `client_id`,
      `redirect_uri`,
         `scope`, and `state`.
      2. The merchant logs in (if not already) and approves the connection.

      3. Galactic Core redirects back to your `redirect_uri` with a short-lived
      `code`.

      4. Your **server** calls `POST /v1/connect/token` to exchange the code for
      `sk` + `pk`.

      5. Store the `sk` securely server-side. Use it for all subsequent API
      calls on behalf
         of the merchant.

      **Keys are permanent** — they remain active until the merchant disconnects
      your

      application from their Settings panel, or you call `POST
      /v1/connect/revoke`.


      **To integrate**, your application must be approved by Galactic Core.
      Apply via the

      [Developer Portal](https://gc.tybritelabs.com/developers).
  - name: Reviews
    description: >
      Product reviews and ratings submitted by customers, moderated by
      merchants.


      **Key type behavior:**

      - Publishable keys (`tybrite_pk_*`) — list and get approved reviews,
      submit reviews
        (requires an additional customer session token), and mark reviews helpful.
      - Secret keys (`tybrite_sk_*`) — all of the above, plus view
      pending/rejected reviews,
        approve or reject submissions, and delete any review.

      **Review lifecycle:**

      1. A logged-in customer submits a review (`POST /v1/reviews`). It starts
      as `pending`.

      2. The merchant reviews pending submissions in their dashboard and calls
         `PATCH /v1/reviews/{id}` to approve or reject.
      3. Once approved, the review appears in public listing results.


      **Verified purchases:** Supply the `order_id` when submitting. If the
      order belongs to

      the authenticated customer, the review is automatically marked
      `verified_purchase: true`.


      **Duplicate prevention:** A customer may only have one non-rejected review
      per product.

      A second submission returns `409 Conflict`.


      **Special headers:**

      - `x-auth-token`: Customer session JWT — required for `POST /v1/reviews`
      (submit)
        and for `DELETE /v1/reviews/{id}` when using a publishable key to delete own review.
        Obtained from `POST /v1/auth/login` or `POST /v1/auth/verify-otp`.
  - name: Returns
    description: >
      Return requests a shopper lodges against their own online orders.


      **Key type behavior:**

      - The reason-code list (`GET /v1/returns/reasons`) needs only an API key —
      no
        customer session — so you can build the reason picker before sign-in.
      - Listing, getting, and creating returns require an API key **and** a
      customer
        session: either `x-auth-token` (a GC-native session token) or
        `x-external-auth` (a bring-your-own-auth assertion).

      A customer can only create, list, and track their OWN returns. Approving,

      processing refunds or store credit, restocking, and rejecting items are

      store-management tasks handled in the merchant admin, not through this
      API.


      **Special headers:**

      - `x-auth-token` **or** `x-external-auth`: identifies the signed-in
      customer on
        `GET /v1/returns`, `GET /v1/returns/{id}`, and `POST /v1/returns`.
  - name: Disputes
    description: >
      Disputes a shopper raises on their own marketplace orders when something
      goes

      wrong — the item never arrived, arrived damaged, or was not as described.


      Disputes are a marketplace capability: the operator sits between the
      shopper and

      the merchant, reviews an open dispute, and applies a resolution (a refund,
      store

      credit, or another remedy). This API is the shopper's side of that flow —
      open a

      dispute, list and track your own, add a message, and cancel one you
      opened.

      Reviewing and resolving disputes are operator and merchant tasks handled
      in the

      admin dashboards, not through this API.


      **Key type behavior:**

      - The reason-code list (`GET /v1/disputes/reasons`) needs only an API key
      — no
        customer session — so you can build the reason picker before sign-in.
      - Listing, getting, opening, messaging, and cancelling disputes require an
      API key
        **and** a customer session: either `x-auth-token` (a GC-native session token) or
        `x-external-auth` (a bring-your-own-auth assertion).

      A shopper can only open, list, track, message, and cancel their OWN
      disputes.


      **Special headers:**

      - `x-auth-token` **or** `x-external-auth`: identifies the signed-in
      customer on the
        per-shopper dispute endpoints.
  - name: Marketplace
    description: >
      Endpoints for building a multi-merchant marketplace storefront.


      These endpoints let a marketplace storefront read the marketplace's
      identity and

      branding (and a single merchant's store information within it), resolve
      commission,

      check out a cart spanning multiple merchants in a single payment, and read
      a

      shopper's unified profile across every merchant they have shopped with.


      To narrow aggregated marketplace catalog results to a single merchant's
      "shop page",

      pass `?store_id=<merchant>` to the products, categories, subcategories,
      and search

      endpoints (operator key only).


      **Key types:**

      - Marketplace information, unified checkout, and the unified customer
      profile use
        the marketplace operator key. Commission resolution accepts the marketplace operator
        key or a merchant secret key.

      Merchant payment onboarding and operator payout runs are merchant/operator
      back-office

      tasks handled in the admin interface, not through this API.
  - name: Ingestion
    description: >
      Sync an external product catalog INTO Galactic Core.


      **⚠️ SECRET KEY + SIGNATURE REQUIRED**: `POST /v1/ingest/products`
      requires a secret

      key (`tybrite_sk_*`) **and** a request signature. Publishable keys return
      403; a missing

      or invalid signature returns 401. This is the one write endpoint where
      both are mandatory.


      Use ingestion when a merchant's own system (an ERP, a PIM, another
      storefront, a

      spreadsheet export) is the source of truth for products and you want to
      push or sync

      that catalog into Galactic Core — rather than entering products by hand.


      **What it does:**

      - Accepts a batch of products as **JSON, XML, or CSV** (set the
      `Content-Type`, or
        `?format=`). One request can carry many products.
      - **Upserts by SKU**: a product whose SKU already exists is updated; a new
      SKU is created.
        Use `?strategy=create_only` to skip existing SKUs instead of updating them.
      - **Groups variants**: rows that share a `product_group` become variants
      of a single
        product (e.g. a shirt in S/M/L). Rows without a group are single-variant products.
      - **Reports per row**: the response carries a `summary` (created / updated
      / skipped /
        failed counts) and an `errors` array naming the row, SKU, field, and reason for every
        rejected row — so a partly-valid batch still imports the good rows and tells you exactly
        what to fix.

      **Signing:** sign each request the same way as orders/payments —
      `X-Timestamp` (unix

      seconds) + `X-Signature` (HMAC-SHA256 of `timestamp + "." + raw_body`,
      base64), within a

      5-minute window. An `Idempotency-Key` is required so a retried batch is
      processed once.


      **Test before you integrate (no key needed):**

      - `GET /v1/ingest/sample?format=json|xml|csv` returns a valid sample feed
      to copy.

      - `POST /v1/ingest/test` validates a feed and returns the same
      `summary`/`errors` you'd
        get from a real import — **without writing anything**. Both are rate-limited to 60/hour
        per IP.

      **Scheduled sync:** merchants can also register a feed URL in their
      dashboard for Galactic

      Core to pull and sync on a schedule; a `feed.sync.completed` webhook fires
      after each run.
  - name: Webhooks
    description: >
      Outbound webhook management for merchant integrators.


      **⚠️ SECRET KEY REQUIRED**: All webhook endpoints require a secret key
      (`tybrite_sk_*`).

      Publishable keys will return 403 Forbidden.


      Webhooks allow your systems to receive real-time notifications when events
      occur in your

      store — eliminating the need to poll the API.


      **Delivery contract:**

      - **At-least-once** delivery — endpoints must be idempotent. Use
      `event.id` for dedup.

      - **HMAC-signed** — every request carries `X-Tybrite-Signature:
      t=<timestamp>,v1=<hmac_sha256>`.
        Verify with the `signing_secret` returned at endpoint creation.
      - **Payload size** — capped at 256 KB per delivery.

      - **Ordering** — best-effort, not guaranteed. Use event timestamps for
      sequencing.


      **Signature verification:**

      ```typescript

      const [tPart, v1Part] = req.headers['x-tybrite-signature'].split(',');

      const timestamp = tPart.replace('t=', '');

      const receivedSig = v1Part.replace('v1=', '');

      const payload = `${timestamp}.${rawBody}`;

      const expected = hmacSha256Hex(signingSecret, payload);

      if (receivedSig !== expected) throw new Error('Invalid signature');

      // Replay check: reject if |now - timestamp| > 300 seconds

      ```


      **Rate Limiting:** 500 requests/hour per secret key.
  - name: Sandbox
    description: >
      Developer tooling for the sandbox (test) environment — make your test runs
      fast and repeatable.


      **⚠️ SECRET TEST KEY REQUIRED**: every Sandbox endpoint requires a
      `tybrite_sk_test_*` key and

      only ever touches your sandbox data; publishable keys and live keys are
      rejected (403). Your

      live data and store configuration are never affected.


      - **Reset** (`POST /v1/sandbox/reset`, or `DELETE /v1/sandbox/data`) —
      wipe all your sandbox
        test data instantly instead of waiting for the automatic 30-day cleanup.
      - **Fast-forward time** (`POST /v1/sandbox/time`) — advance your sandbox
      by N days so abandoned
        carts, stock-reservation windows and analytics roll forward without waiting. (Subscription
        trials/renewals and promotion/gift-card expiry are not time-shifted — see the endpoint.)
      - **Replay a webhook** (`POST /v1/sandbox/webhooks/replay`) — re-send a
      recorded sandbox webhook
        event to your endpoints without recreating the underlying record.
  - name: B2B
    description: >
      GC B2B — the buyer-side wholesale flow: request a quote (RFQ), receive and
      accept

      a quote, track the resulting purchase order, and pay invoices on terms.


      Every endpoint acts on the buyer's own records and requires the buyer's
      session

      (`x-auth-token` or `x-external-auth`) alongside the API key. Supplier-side
      actions —

      pricing quotes, confirming purchase orders, fulfilling, and credit
      decisions — are

      handled in the supplier's admin, never through this API. Available only on

      deployments with B2B enabled.
externalDocs:
  description: Galactic Core Documentation
  url: https://docs.tybritelabs.com/galactic-core
paths:
  /v1/b2b/purchase-orders:
    get:
      tags:
        - B2B
      summary: List your purchase orders
      operationId: listPurchaseOrders
      parameters:
        - name: x-auth-token
          in: header
          required: false
          schema:
            type: string
          description: Buyer session token (GC-native). Provide this or x-external-auth.
        - name: x-external-auth
          in: header
          required: false
          schema:
            type: string
          description: >-
            Bring-your-own-auth assertion identifying the buyer. Provide this or
            x-auth-token.
      responses:
        '200':
          description: Purchase orders retrieved
          content:
            application/json:
              example:
                data:
                  - id: 7761b763-224b-43f2-a3f0-01139159b430
                    quote_id: e18980a5-a8d2-454b-9774-f302fcb2a9ea
                    po_number: PO-20260711-47cc6c
                    status: confirmed
                    currency: USD
                    subtotal: 200
                    tax_amount: 0
                    total: 200
                    payment_terms: net30
                    created_at: '2026-07-11T13:32:07.271194+00:00'
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/B2bPurchaseOrder'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '403':
          $ref: '#/components/responses/ForbiddenError'
      security:
        - BearerAuth: []
components:
  schemas:
    B2bPurchaseOrder:
      type: object
      example:
        id: 7761b763-224b-43f2-a3f0-01139159b430
        quote_id: e18980a5-a8d2-454b-9774-f302fcb2a9ea
        po_number: PO-20260711-47cc6c
        status: confirmed
        currency: USD
        subtotal: 200
        tax_amount: 0
        total: 200
        payment_terms: net30
        created_at: '2026-07-11T13:32:07.271194+00:00'
      properties:
        id:
          type: string
          format: uuid
        quote_id:
          type:
            - string
            - 'null'
          format: uuid
        po_number:
          type: string
        status:
          type: string
          enum:
            - issued
            - confirmed
            - partially_fulfilled
            - fulfilled
            - cancelled
        line_items:
          type: array
          items:
            type: object
        currency:
          type: string
          example: USD
        subtotal:
          type: number
        tax_amount:
          type: number
        total:
          type: number
        payment_terms:
          type: string
          enum:
            - prepaid
            - net15
            - net30
            - net60
        created_at:
          type: string
          format: date-time
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              example: invalid_request
            message:
              type: string
              example: Missing required field
            details:
              type: string
              example: The 'email' field is required
            hint:
              type: string
              description: Additional guidance on how to resolve the error.
            available_stock:
              type: integer
              description: Current stock level (present on insufficient_stock errors).
            current_cart_quantity:
              type: integer
              description: Quantity already in cart (present on insufficient_stock errors).
            limit:
              type: integer
              description: >-
                Rate limit ceiling (present on rate_limited / quota_exceeded
                errors).
            remaining:
              type: integer
              description: >-
                Requests remaining in the current window (present on
                rate_limited / quota_exceeded errors).
            reset:
              type: integer
              description: >-
                Unix timestamp when the rate limit / quota window resets
                (present on rate_limited / quota_exceeded errors).
  responses:
    UnauthorizedError:
      description: Authentication failed - invalid or missing API key
      headers:
        Tybrite-Environment:
          $ref: '#/components/headers/TybriteEnvironment'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: unauthorized
              message: Missing or invalid Authorization header
    ForbiddenError:
      description: Insufficient permissions - operation requires secret key
      headers:
        Tybrite-Environment:
          $ref: '#/components/headers/TybriteEnvironment'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: forbidden
              message: >-
                This operation requires a secret key. Publishable keys have
                read-only access.
  headers:
    TybriteEnvironment:
      description: >
        Confirms which environment your API key resolved to. Use this to verify
        that test keys

        are hitting sandbox data and live keys are hitting production data.


        - `production` — requests are scoped to live data; real orders,
        customers, and payments

        - `sandbox` — requests are scoped to isolated test data; no real money
        is moved


        Present on every authenticated response, including error responses.
      schema:
        type: string
        enum:
          - production
          - sandbox
      example: sandbox
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: API Key
      description: >
        **API Key Authentication**
            
        Use your API key in the Authorization header:

        ```

        Authorization: Bearer tybrite_sk_live_YOUR_KEY

        ```
            
        **Key Types:**
            
        **Secret Keys (Server-Side Only):**

        - Format: `tybrite_sk_live_*` (production) or `tybrite_sk_test_*`
        (sandbox)

        - Full read/write access to all endpoints

        - ⚠️ NEVER expose in client-side code or public repositories

        - Required for: write operations, authentication, payment verification,
        AI recommendations
            
        **Publishable Keys (Client-Safe):**

        - Format: `tybrite_pk_live_*` (production) or `tybrite_pk_test_*`
        (sandbox)

        - Read-only access (GET requests only, plus POST semantic search)

        - ✅ Safe for client-side JavaScript, mobile apps, and public code

        - Allowed for: browsing products, search, CMS content, pricing queries
            
        **Endpoint-Specific Requirements:**

        - **Authentication endpoints** (`/v1/auth/*`): Secret key required

        - **Payment verification** (`POST /v1/payments/verify`): Secret key
        required

        - **AI Recommendations** (`POST /v1/recommendations`): Secret key
        required

        - **Semantic Search** (`POST /v1/search`): Both key types allowed
        (read-only operation)

        - **All write operations**: Secret key required

        - **All read operations**: Both key types allowed
            
        Using a publishable key for restricted operations returns 403 Forbidden.

````