Skip to main content
Galactic Core holds a handful of ideas constant across every endpoint — who a request is authenticated as, which environment it lands in, how errors and pages are shaped, and what the platform does on your behalf when an order is created. They are set out here once, and every service page assumes them.

Storefront-facing by design

The API exists to power a storefront — a shopper browsing a catalog, searching, managing their cart, checking out, paying, and tracking their own orders and returns. Merchant/admin operations (editing the catalog, moderating reviews, issuing refunds, changing store settings) happen in the Galactic Core admin, not through this API. The one exception is catalog ingestion, where a merchant syncs their own product feed in — see Catalog Ingestion. Key requirements follow from that boundary: catalog reads are open to a publishable key a browser can hold, while writes that a storefront’s server performs on a shopper’s behalf — creating an order, taking payment — require a secret key.

Keys and sessions

Three identities combine depending on the call: A storefront uses the publishable key for browsing, a customer session once the shopper signs in, and routes sensitive writes (order creation, payment, ingestion) through a server holding the secret key. Customer sessions come in two flavours — a GC-issued token, or a bring-your-own-auth assertion if you run your own identity provider. See Authentication and Customers & Auth. Sensitive writes (orders, order updates, payments, ingestion) are additionally HMAC-signed so the server can verify the request body wasn’t tampered with — the SDK computes and attaches the signature for you.

Environments: production and sandbox

Every key carries an environment. A *_test_* key writes and reads sandbox data; a *_live_* key writes and reads production data. They share the same endpoints and the same store, but the data never mixes — you can build and exercise the full flow (orders, customers, carts, payments in provider test mode) against sandbox without touching real records. Each authenticated response also echoes the resolved environment in a Tybrite-Environment header.

Isolation

Your data is scoped to your store and never co-mingled with another store’s. Every key resolves to a single store_id, and the database enforces that boundary at the row level — each query is constrained to your store’s rows by row-level security tied to the authenticated key, with no way for one store to read or write another’s data even on a shared table. This holds for every endpoint, not just the ones that take a store parameter. For partners running a marketplace deployment, the boundary goes a step further: each operator’s marketplace runs on its own dedicated backend — a separate database and API stack, not a shared one — so an entire marketplace (and all its merchants) is isolated at the infrastructure level from every other deployment. Within a deployment, individual stores are isolated from each other by the row-level security described above.

Conventions that hold everywhere

  • Errors — every error is { "error": { "code": "…", "message": "…", "details"?: … } } with a standard HTTP status. Codes are stable strings you can branch on.
  • Pagination — list endpoints are cursor-based: a response carries a next_cursor; pass it back to fetch the next page. (The SDK exposes helpers for this.)
  • Sparse fieldsets — pass fields= to fetch only the columns you need (lean catalog grids), or full: true / a detail call to get the complete object (SEO, media, specifications).
  • Idempotency — order creation takes an Idempotency-Key; a retried call with the same key and body returns the original result instead of creating a duplicate.

Products and variants — which ID to send where

A product is the catalog entry a shopper browses (the “Cotton Hoodie”). A variant is a specific buyable SKU of it (the “Cotton Hoodie / Navy / M”). Every product has at least one variant, and one is marked the default. Two ID types follow from this — product_id and variant_id — and which one an endpoint takes follows from what it acts on:
  • Money and inventory are variant-grained. A shopper buys a specific SKU, so anything that touches a cart, the stock count, or what gets charged uses variant_id.
  • Catalog and discovery are product-grained. Browsing, recommendations, and reviews are about the product, so they use product_id.
Carry the variant_id you put in the cart all the way through to the order — don’t drop down to product_id at checkout, or you may order the default variant instead of the one the shopper chose.
Gotcha — product_specifications are keyed by variant. A product’s published specifications are per-variant: each spec row references a variant_id (despite some internal column naming). If a product has multiple variants, each can carry its own specifications. When you read specs off a product detail, they belong to the specific variant, not the product as a whole.

Performance & rate limits

Reads are served through a multi-tier edge cache, so catalog, pricing, and store-info calls return in tens of milliseconds globally and stay fast under load. The SDK retries transient failures automatically. There are two independent limits, and a 429 tells you which one you hit by its error.code: Rate-limit tiers (the abuse throttle): publishable keys are limited per-IP and per-key (hourly + daily); secret keys per-key (hourly + daily); signed-in shoppers also get a per-session cap. These are flat across plans — they protect a store from any single client monopolizing it. Abuse-throttled traffic is never billed to the merchant, so a flood can’t deplete their monthly quota. The monthly quota itself scales with the plan.

What an order does for you

Creating a paid order is a single call, but Galactic Core performs the operational work behind it automatically and atomically:
  • reduces stock for each line item (quantity- or barcode-tracked),
  • redeems any gift cards applied,
  • updates the customer’s purchase metrics,
  • posts the double-entry accounting (revenue, tax, cost of goods), and
  • records attribution for analytics.
If a non-fatal step partially fails (e.g. a gift-card redemption), the order is still recorded and the response includes a post_processing_warnings array, so a partial failure is visible in the response rather than inferred later from the ledger.

Currency

Every priced response already tells you its currency — you don’t fetch it separately. Product and pricing responses carry the currency inline: display_currency and currency_symbol on each product (list and detail), plus base_currency and exchange_rate from the pricing endpoints. Both are selectable via sparse fieldsets (fields=...,display_currency,currency_symbol). So a storefront renders prices with the right symbol straight from the catalog read — no extra call. Store info’s currencies list is configuration metadata (which currencies the store has enabled), not the per-response source of truth. See Currency.

Where to go next

Quickstart

Your first authenticated call.

Authentication

Keys, sessions, and HMAC in depth.

TypeScript SDK

The typed client and every service.

API Reference

Every endpoint and schema.