API reference
A read-only HTTP API over your published catalogue. Every endpoint, scope and limit below is generated from the same registry Onetap Business OS answers from, so this page cannot drift from the product.
Getting a key
Settings → API Keys. Name the key, choose its scopes and an optional expiry. The key is shown once — it is stored only as a hash, so we cannot show it to you again and neither can anyone who reaches our database. Lost one is replaced, never recovered.
curl https://{your-domain}/api/v1/products \
-H "Authorization: Bearer pk_live_…"
# X-API-Key is accepted too, for tooling that only offers that header:
curl https://{your-domain}/api/v1/products -H "X-API-Key: pk_live_…"Authentication
Optional. Without a key, every endpoint answers for the business that owns the domain you called. Send a key — `Authorization: Bearer pk_…` or `X-API-Key: pk_…` — to ask for a specific business's catalogue from anywhere. A key does not raise your rate limit. Keys are read-only and identify a business, never a user, so they can never reach anything behind a person's permissions.
Scopes
There are three, and all three are reads. That is a property of the design rather than a stage we are at: a key identifies a business and carries no user identity, so it can never reach anything gated on a person's permissions. There is no write API.
catalog:readSearch your catalog and read its filter optionsproducts:readRead your published productscategories:readRead your published category treeEndpoints
Rate limits are per endpoint, not one shared budget. Exceeding one returns 429 with a Retry-After header.
GET/api/v1This description — endpoints, scopes, limits and caching.
GET/api/v1/productsPublished products, paginated, searchable and filterable.
qFree-text match on name, description, SKU or brand. `search` is accepted as an alias.categoryCategory id. Returns products filed directly under it.tagTag slug.brandBrand name, matched case-insensitively.featured`true` to return only featured products.sortOrdering. Defaults to `featured`.pagePage number, from 1. Defaults to 1.limitItems per page, maximum 100. Defaults to 25.GET/api/v1/products/:slugOne published product by its slug. 404 when the slug is not published for this tenant.
slug *The product's URL slug, in the path.GET/api/v1/products/:slug/recommendationsRelated products for one product, grouped as crossSell, upsell, related, coBuying and similar.
slug *The product's URL slug, in the path.GET/api/v1/categoriesThe published category tree, nested by default.
flat`true` returns a flat array instead of a nested tree.GET/api/v1/searchSearch across products, categories and tags at once.
q *The search text. Required — an empty query is a 400, not an empty result.type`products`, `categories`, `tags` or `all`. Defaults to `all`.pagePage number, from 1. Defaults to 1.limitItems per page, maximum 100. Defaults to 25.GET/api/v1/filtersFilter options — categories, brands, tags, price range, availability — with live counts for the current result set.
categoryNarrow the counts to one category id.qNarrow the counts to a search term.Responses
{
"success": true,
"data": { … },
"meta": { "version": "1", "timestamp": "2026-09-11T04:00:00.000Z" }
}
// and on failure — the status code carries the same news
{ "success": false, "error": "Product not found", "meta": { "version": "1" } }- All prices are in INR.
- Only published, catalogue-visible products are returned. Nothing behind a login is reachable with a key.
- Responses are CORS-open, so a browser can call them directly.
- Every response carries `success`, `data` and `meta`; an error carries `success: false` and `error`.
- Rate limits are per endpoint, not one budget — see each endpoint below. Exceeding one returns 429 with `Retry-After`.
Caching
- An anonymous response is publicly cacheable — the domain you called is part of the cache key, so a shared cache cannot hand your answer to another business.
- A key-resolved response is `private, no-store`. A header is NOT part of a shared cache key, so caching one would risk serving your data to the next caller of the same URL.
- Both forms send `Vary` on the authentication headers as well.
What this API does not do
- No writes. Every scope is a read. You cannot create or change an invoice, a party, a product or stock through a key.
- Catalogue only. The endpoints above are the whole surface. CRM, sales, purchase, finance and inventory are not reachable with a key.
- No outbound webhooks and no SDK. Poll the endpoints, and call them over plain HTTP from whatever you already use.