Store API — options & variants
Manage your Southbill Store catalogue, option groups, variants, orders and evidence with your secret API key.
Store API — options & variants
Your Southbill Store catalogue is reachable with the same secret API key you use for the rest of the REST API. Base URL:
https://api.southbill.com/v1/store
So GET https://api.southbill.com/v1/store returns the store itself, GET https://api.southbill.com/v1/store/products lists products.
Authenticate with Authorization: Bearer sk_live_… (server-side only — secret keys are rejected from a browser origin). Write calls accept an Idempotency-Key header.
Required scopes: store:read, products:read, products:write, orders:read, orders:write, files:write. Existing keys were upgraded automatically.
Why variants
A product is the catalogue item ("Runner 01"). A variant is the concrete thing a buyer picks — Size M, Colour Black. Variants are built from option groups (Size) and option values (S, M, L). Each variant references exactly one value per option group and may carry its own price, SKU and stock.
Product "Runner 01"
├─ Option group "Size" → values S, M, L
├─ Option group "Colour" → values Black, White
└─ Variants: S/Black (SKU RUN-S-BLK), M/Black, …
Endpoints
| Method | Path | Description |
|---|---|---|
GET |
/store |
The merchant's store (slug, display name, status, logo/cover URLs). |
GET |
/products |
List products. |
GET |
/products/{id} |
Product incl. option_groups and variants. |
POST |
/products |
Create a product. |
PATCH |
/products/{id} |
Update a product. |
DELETE |
/products/{id} |
Archive a product. |
POST |
/products/{id}/prices |
Create a price (min 250 minor units). |
GET POST |
/products/{id}/options |
List / create option groups. |
PATCH DELETE |
/options/{id} |
Rename / delete an option group. |
POST |
/options/{id}/values |
Add a value to a group. |
DELETE |
/values/{id} |
Delete an option value. |
GET POST |
/products/{id}/variants |
List / create variants. |
PATCH DELETE |
/variants/{id} |
Update / delete a variant. |
GET |
/orders, /orders/{id} |
Store orders (source store only). |
PATCH |
/orders/{id} |
Fulfillment updates — shipped/completed need evidence. |
POST |
/orders/{id}/evidence |
Attach delivery evidence. |
POST |
/checkouts |
Create a Checkout session for a store product/variant. |
POST |
/files |
Upload product images, documents or evidence (max 5 MB). |
Create an option group
curl https://api.southbill.com/v1/store/products/PRODUCT_ID/options \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{ "name": "Size", "values": ["S", "M", "L"] }'
{
"object": "option_group",
"id": "8df0e320-…",
"product": "019c72f4-…",
"name": "Size",
"values": [
{ "object": "option_value", "id": "9f7e71ab-…", "value": "S", "sort_order": 0 },
{ "object": "option_value", "id": "82170ba4-…", "value": "M", "sort_order": 1 }
]
}
Create a variant
curl https://api.southbill.com/v1/store/products/PRODUCT_ID/variants \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: variant-run01-s-blk" \
-d '{
"options": [{ "group": "8df0e320-…", "value": "9f7e71ab-…" }],
"price": "6040da6b-…",
"sku": "RUN-S-BLK",
"track_inventory": true,
"stock_qty": 12
}'
Presentation fields
Variants accept the same presentation fields as the dashboard editor, on both POST /products/{id}/variants and PATCH /variants/{id}:
| Field | Type | Notes |
|---|---|---|
title |
string ≤80 | Variant headline (falls back to the option combination). |
description |
string ≤2000 | Variant-specific description. |
image_path |
string ≤300 or null |
Storage path from POST /v1/store/files. |
features |
string[] | Max 12 entries, each ≤120 chars, duplicates dropped. |
delivery_days |
integer 0–3650 or null |
Delivery time shown in the storefront. |
revisions |
integer 0–3650 or null |
Included revisions (service products). |
highlight |
boolean | Marks the variant as recommended. |
sort_order |
integer | Display order. |
All of them are returned on every variant object.
Rules enforced by the API:
optionsmust contain exactly one value per option group of the product.- A value must belong to the group it is sent with (
invalid_options, 400). - The same combination cannot exist twice (
variant_exists, 409). pricemust be an active price on the same product; omit it to inherit the product's default price.stock_qtyis required whentrack_inventoryistrue.- The option combination is immutable — delete and recreate the variant to change it.
Deleting
Deletion is guarded so your storefront never ends up with dangling variants:
DELETE /values/{id}→409 value_in_usewhile a variant uses that value.DELETE /options/{id}→409 variants_existwhile the product still has variants.DELETE /variants/{id}works at any time, except for the implicit default variant of a product.
Checkout for a store product
Create a hosted Checkout session for a catalogue product or variant. Price, currency and stock are resolved server-side from your catalogue — you only name the product.
curl https://api.southbill.com/v1/store/checkouts \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: checkout-run01-0001" \
-d '{
"product_id": "019c72f4-…",
"variant_id": "b6f2b0e0-…",
"quantity": 1,
"success_url": "https://yourshop.com/thanks",
"cancel_url": "https://yourshop.com/cart"
}'
{
"ok": true,
"session_id": "cs_...",
"checkout_url": "https://payments.southbill.com/c/cs_...?cs=...",
"amount": 4900,
"currency": "eur",
"expires_at": "2026-01-01T12:30:00.000Z"
}
Details:
- Scope:
checkout:write. Secret keys only (never from a browser). - The store must be live and approved, the product
activeandstore_visible. - Stock is reserved for the session and released automatically when it expires (30 min) or is cancelled.
- Variant price wins, otherwise the product's default price is used. Recurring prices are rejected (
unsupported_price). success_url/cancel_urlare optional and must behttps; they default to your storefront.- The session is a normal Checkout session with
source = store, so it producesstore.*order events, not plainpayment.*only. - Errors:
product_unavailable(404),variant_unavailable(404),price_unavailable(409),out_of_stock(409),amount_too_small(400).
Sandbox
The identical routes exist in the sandbox through an installed app (App API, environment test). Sandbox writes never touch a payment provider — the catalogue, variants and orders live in isolated sandbox tables and are wiped on a sandbox reset.