Skip to content
BolderBolder API
Esc
navigateopen⌘Jpreview
On this page

Bolder API v2

⬇ Download this spec as YAML

Getting Started

The Bolder API provides programmatic access to your Bolder Shop data through a hypermedia-driven REST interface.

Fastest path — Personal Access Token

For scripts, CLI tools, and personal automation, skip the OAuth grant dance entirely:

  1. Go to https://auth.onbolder.com/dev/credentials and sign in. The first visit auto-creates a default developer application for your account — there’s nothing to register.
  2. Under Personal Access Tokens, create a new token: pick the scopes you need (see Token scopes below) and an expiry.
  3. Copy the token — it’s shown once.
export BOLDER_TOKEN=PASTE_YOUR_TOKEN_HERE

curl -H "Authorization: Bearer $BOLDER_TOKEN" https://api.onbolder.com/v2

All curl examples in this documentation use $BOLDER_TOKEN. Set it once in your shell and every example works immediately. See Personal Access Tokens below for details on expiry and revocation.

Building a real integration — register an OAuth application

If you’re building something you’ll distribute to other Bolder merchants (rather than automating your own account), register a dedicated application instead of using a PAT:

Go to https://auth.onbolder.com, sign in, and create a new application. You’ll receive a CLIENT_ID and CLIENT_SECRET. The fastest way to get a token from a terminal is the Client Credentials grant:

export BOLDER_TOKEN=$(curl -s \
  -X POST https://auth.onbolder.com/oauth/token \
  -d "grant_type=client_credentials&client_id=CLIENT_ID&client_secret=CLIENT_SECRET&scope=products.read,orders.read,orders.write" \
  | jq -r .access_token)

No jq? Use Python instead:

export BOLDER_TOKEN=$(curl -s \
  -X POST https://auth.onbolder.com/oauth/token \
  -d "grant_type=client_credentials&client_id=CLIENT_ID&client_secret=CLIENT_SECRET&scope=products.read,orders.read,orders.write" \
  | python3 -c "import sys,json; print(json.load(sys.stdin)['access_token'])")

Note: Unlike PATs, these tokens are temporary. Re-run the request above when your token expires, or use the refresh_token grant described in the Authentication section below.


Authentication

The Bolder API uses OAuth 2.0. The token must be sent in the Authorization header — query-parameter tokens are not accepted by v2.

Five grant types are supported:

Redirect the user to the authorization endpoint and exchange the returned code for tokens on your server.

GET https://auth.onbolder.com/oauth/authorize
  ?client_id=YOUR_CLIENT_ID
  &redirect_uri=https://yourapp.com/callback
  &response_type=code
  &scope=products.read,orders.read,orders.write

Then exchange the code:

POST https://auth.onbolder.com/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET
&redirect_uri=https://yourapp.com/callback
&code=RETURNED_CODE

2. Implicit Grant (for client-side JavaScript apps)

GET https://auth.onbolder.com/oauth/authorize
  ?client_id=YOUR_CLIENT_ID
  &redirect_uri=https://yourapp.com/callback
  &response_type=token
  &scope=products.read

The access token is returned in the URL fragment after the redirect.

3. Client Credentials (for server-to-server / automated scripts)

No user involved — the application authenticates as itself.

POST https://auth.onbolder.com/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials
&client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET
&scope=products.read,orders.read,orders.write

4. Resource Owner Password Credentials (trusted apps only)

POST https://auth.onbolder.com/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=password
&client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET
&username=USER_EMAIL
&password=USER_PASSWORD
&scope=products.read,orders.read,orders.write

5. JWT Bearer (refreshing expired tokens)

Exchange a refresh_token for a new access token:

POST https://auth.onbolder.com/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token
&client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET
&refresh_token=YOUR_REFRESH_TOKEN

Token response

All flows return a JSON token response:

{
  "access_token":  "eyJ...",
  "token_type":    "bearer",
  "expires_in":    7200,
  "refresh_token": "abc123...",
  "scope":         "products.read,orders.read,orders.write"
}

Access tokens are temporary. Implement refresh-token logic to obtain new tokens before they expire.

Token scopes

v2 uses granular scopes: request access to individual resource namespaces using {namespace}.read / {namespace}.write scopes. This lets an integration ask for only what it needs — e.g. an order-fulfillment tool can request orders.read,orders.write without also getting product or customer write access.

Namespace Read scope Write scope Covers
products products.read products.write Products, variants, collections
orders orders.read orders.write Orders, documents, tracking
customers customers.read customers.write Customer profiles
shops shops.read shops.write Shop configuration
hub hub.read hub.write Content (posts, pages)
store store.read store.write Themes and assets
sellers sellers.read — (read-only) Seller information
batches batches.read batches.write Batch job status

Request them the same way as any other scope, comma-separated:

&scope=products.read,orders.read,orders.write

Personal Access Tokens (PATs)

For scripts and CLI tools where the standard OAuth grants (which require redirect flows or a client secret exchange per session) are overkill, you can issue a Personal Access Token: a long-lived Bearer JWT tied to your user account and a specific application, created from the developer credentials page — see Fastest path — Personal Access Token above for the step-by-step. A few more details:

  • Give the token a name, choose an expiry (30 days, 90 days, 1 year, or no expiry), and select the scopes to grant — you can only grant scopes your own user role already has (see Token scopes above).
  • The raw token is shown once, immediately after creation. Copy it then — it cannot be retrieved again afterwards.

Use it exactly like any other access token:

curl -H "Authorization: Bearer $PERSONAL_ACCESS_TOKEN" https://api.onbolder.com/v2

PATs do not expire on a fixed short TTL like regular access tokens, so there is no refresh-token flow — the token is valid until its chosen expiry (if any) or until revoked. Revoke a PAT at any time from the same credentials page; revocation takes effect immediately.


Hypermedia (HAL)

All responses follow the HAL (Hypertext Application Language) format. Every response contains:

  • _links — navigation links to related resources and available actions.
  • _embedded — inline sub-resources (e.g. variants inside a product).
  • _class — array of type strings (e.g. ["results", "products"]).
  • Properties — the resource’s own data fields at the top level.

CURIEs

Link relation types use service-namespaced CURIEs so clients can resolve documentation for any relation:

{
  "_links": {
    "curies": [
      { "name": "products", "href": "https://api.onbolder.com/docs/v2#products:{rel}", "templated": true },
      { "name": "orders",   "href": "https://api.onbolder.com/docs/v2#orders:{rel}",   "templated": true }
    ],
    "self":             { "href": "https://api.onbolder.com/v2/products/123" },
    "products:update":  { "href": "https://api.onbolder.com/v2/products/123", "method": "put" },
    "products:variants":{ "href": "https://api.onbolder.com/v2/products/123/variants" }
  }
}

Clients should follow links rather than constructing URLs. If a link is absent from a response, the action is either unavailable or not permitted for the current token. The presence of a link is itself an affordance.

URI Templates

Some links are URI templates (marked "templated": true). Expand them with the parameters shown in the template before making a request:

products:list → https://api.onbolder.com/v2/products{?q,status,page,per_page,...}

Expanded:       https://api.onbolder.com/v2/products?status=visible&page=2

Pagination

List endpoints return a standard pagination envelope:

{
  "_class":      ["results", "products"],
  "total_items": 142,
  "per_page":    20,
  "page":        1,
  "_links": {
    "self": { "href": "https://api.onbolder.com/v2/products?page=1" },
    "next": { "href": "https://api.onbolder.com/v2/products?page=2" },
    "prev": { "href": "https://api.onbolder.com/v2/products?page=0" }
  },
  "_embedded": {
    "items": [...]
  }
}

Default page size is 20, maximum is 200 (use per_page to override).


Errors

HTTP Status Meaning
400 Bad request — malformed JSON or missing required field
401 Unauthorized — missing or invalid access token
403 Forbidden — valid token but insufficient permissions
404 Not found
422 Unprocessable — validation failed; see _embedded.errors
429 Too many requests — rate limit exceeded
500 Server error

Validation errors (422) embed a structured error list:

{
  "_embedded": {
    "errors": [
      { "field": "name", "messages": ["can't be blank"] }
    ]
  }
}

HTTP caching

The API emits standard ETag and Last-Modified headers. Clients may send If-None-Match / If-Modified-Since on subsequent requests; unchanged resources return 304 Not Modified with no body.

Version 2.0
Base URLhttps://api.onbolder.com/v2

Root

API entry point — embeds sellers, shops, and navigation links to every resource

Sellers

Seller entities — the business layer between an account and its shops. An account can have multiple sellers, each owning one or more shops and their product catalog.

Catalog

Customers

Shop customers. Includes customer authentication and password-reset flows.

Orders

Shop orders. Supports batch status updates and per-order document management.

Products

Catalog products, automatically scoped to the authenticated account’s sellers. Account-scoped tokens need no extra parameters; tokens without an account/seller scope must supply shop_subdomains.

Shops

Shops owned by the authenticated account. A shop is the customer-facing storefront that belongs to a seller. Settings, admins, shipping tables, payment methods, exchange rates, and other shop-level configuration are anchored to a specific shop.

Webhooks

Event webhooks. Subscribe to events such as orders.created, products.updated, etc. Inactive subscriptions can be reactivated and their delivery history inspected.

Store

Collections

Curated product collections (manually or rule-based). Products can belong to multiple collections.

Product Types

Product type definitions used to group and filter catalog products.

Variants

Product variants (size, colour, etc.). Nested under /products/{product_id}/variants. Each variant holds its own SKU, price, stock level, and images.

Themes

Hosted-storefront themes, templates, and assets. Applies only to shops with a hosted storefront (store: namespace); absent for headless shops.

Content

CMS-style content for a shop’s storefront — blog posts, static pages, and contact/lead-capture forms.

Price Lists

Named price lists for B2B / wholesale pricing. Products can have per-variant price overrides within a price list.

Promotions

Promotional discount codes and automatic discounts applied at checkout.

Volume Discounts

Quantity-based discount rules (tiered pricing by units purchased).

Subscriptions

Recurring product subscriptions. SubscriptionFee defines the recurring payment terms attached to a product/variant; SubscriptionPurchase is a customer’s active subscription created from a recurring order.

Was this page helpful?