Start HereDeveloper quickstart

Developer quickstart

Authenticate and make your first Orchard API call in about five minutes. For the full integration walkthrough, see Developers.

The mental model

Two repos, three planes:

  • Your repo — the public storefront (any framework; Next.js gets the best SDK ergonomics). Your domain, your Vercel project, your Stripe account.
  • Orchard — the admin UI (admin.theorchard.dev/t/{slug}), the platform API (api.theorchard.dev/api/v1/*), the database, RBAC, and infrastructure. You never commit here.

Your storefront talks to Orchard two ways: the typed @orchard/sdk package or raw REST against /api/v1/*. Both hit the same endpoints. Data is isolated to your tenant_id by row-level security — the tenant is derived server-side from your API key, never from a parameter you send.

What you need

A tenant slug and a test-mode API key (sk_test_… / pk_test_…), both issued by the Orchard operator when your tenant is provisioned.

1. List products (public — no key needed)

Public reads identify the tenant with the x-tenant-slug header:

curl https://api-test.theorchard.dev/api/v1/products \
  -H "x-tenant-slug: your-slug"
{
  "products": [
    {
      "id": "...",
      "name": "...",
      "slug": "...",
      "price": { "amount": 4200, "currency": "usd" },
      "first_image_url": "..."
    }
  ],
  "cursor": null
}

Paginate with ?cursor=, filter with ?search=, or batch-fetch with ?ids=a,b,c (max 100 UUIDs).

2. The same call, Bearer-authenticated

Any read that supports Bearer derives the tenant from the key (the x-tenant-slug header is ignored, which defeats leaked-key replay):

curl https://api-test.theorchard.dev/api/v1/products \
  -H "Authorization: Bearer sk_test_your_key"

A required-Bearer route returns a generic 401 for any bad key (the reason is never disclosed) and 403 if the key lacks the scope.

3. Capture a lead

curl -X POST https://api-test.theorchard.dev/api/v1/leads \
  -H "x-tenant-slug: your-slug" \
  -H "Content-Type: application/json" \
  -d '{ "email": "shopper@example.com", "source": "newsletter" }'

Always returns { "ok": true } — it never reveals whether the email was already captured (privacy by design).

4. Check stock for a set of products

curl -X POST https://api-test.theorchard.dev/api/v1/inventory/status \
  -H "Authorization: Bearer sk_test_your_key" \
  -H "Content-Type: application/json" \
  -d '{ "ids": ["<product-uuid-1>", "<product-uuid-2>"] }'

Returns a coarse status_key (in_stock / low_stock / out_of_stock) per product — never raw counts.

That’s the loop: read the catalog, capture leads, check availability, then create checkout sessions (POST /checkout/sessions, Bearer checkout:write — returns a hosted Stripe Checkout URL to redirect the shopper to). Everything else is the same shape.

Generate types from the spec (works today)

npx openapi-typescript https://docs.theorchard.dev/openapi.generated.json \
  -o src/orchard-types.ts

You get a fully-typed network boundary without waiting for the SDK.

Next