Developer API
Curobi has an HTTP API for pulling your subscription data into whatever else you run — a warehouse, an ERP, a CRM, a BI dashboard, a nightly reconciliation script — for changing a subscription from your own server, and signed outbound webhooks so those systems are told when something happens instead of polling for it.
https://app.curobi.com/api/admin/v1The Developer API and outbound webhooks are a Pro feature, and they share one entitlement — the API is what you ask, webhooks are what you’re told, and a merchant with one and not the other has half an integration. See Pricing & Plans.
Minting keys, the bearer header, the scope list, and what happens on uninstall.
Authentication & scopesEvery v1 endpoint, the subscription writes, pagination, rate limits, and versioning.
Admin API referenceThe browser-safe surface: publishable keys, origin allowlists, and the Mix & Match catalogue.
Storefront APIA headless customer portal, behind a session exchanged for a Shopify customer token.
Customer APIFork-and-restyle purchase and portal components that encode the integration contract.
Reference React componentsAsynchronous CSV and JSONL exports: datasets, filters, signed downloads, retention.
Export jobsThe error envelope and every code the API can return.
ErrorsEndpoint setup, signature verification, retries, and the event catalogue.
WebhooksThe cart-line property contract for build-a-box, Mix & Match, and gifts.
Headless & custom storefrontsQuickstart
Confirm you’re on Pro
The API is checked against your plan on every request, not just when the key is minted. A key
from a shop on any plan below Pro is refused with plan_upgrade_required even if the key itself is
perfectly valid. Partner development stores are refused too, until the store is on a paid Shopify
plan and Curobi Pro.
Mint a key
In your Curobi admin, open API keys, name the key after the system that will use it, and tick only the scopes that system needs.
write:subscriptions is off by default and ticking it raises a warning: it lets the holder
cancel any contract on the shop. A reporting job never needs it.
The key is shown once. It’s stored as a salted hash and is not recoverable — if you lose it, revoke it and mint another.
Call the API
Every read is a plain HTTPS GET with one header, so any HTTP client will do. Writes add a second
header — see subscription writes.
cURL
curl -sS "https://app.curobi.com/api/admin/v1/subscriptions?status=ACTIVE&limit=100" \
-H "Authorization: Bearer $CUROBI_API_KEY"Every list endpoint answers with the same two-key envelope:
{
"data": [ { "contract_id": "gid://shopify/SubscriptionContract/1234", "status": "ACTIVE" } ],
"next_cursor": "eyJ0IjoiMjAy…"
}Every tab above reads the key from the server’s environment, and that is the point. A secret
key reads every subscription on the shop, and one holding write:subscriptions can cancel any of
them — it must never reach a browser bundle, a mobile app, a theme file or a committed .env. The
browser-safe credential is the publishable key (curobi_pk_…) on the
Storefront API; a secret key presented there is refused, and a publishable key
presented here is refused with invalid_credential.
Register a webhook endpoint
So you stop polling. Either from the Webhooks page in your Curobi admin, or over the API with a
manage:webhooks key — see Webhooks.
What exists today
| Surface | Status | What it does |
|---|---|---|
Admin API — /api/admin/v1 | ✅ Available | Server-to-server reads over subscriptions, plans, bundles, Mix & Match, gifts, win-back, notifications and analytics, behind a secret key |
Subscription writes — /api/admin/v1/subscriptions/{id}/… | ✅ Available | Pause, resume, cancel, skip, reschedule and line edits under write:subscriptions, each requiring an Idempotency-Key — see subscription writes |
| Outbound webhooks | ✅ Available | Fifteen signed lifecycle events pushed to your endpoint, with retries and a delivery log |
| Headless purchase path | ✅ Available | Needs no Curobi credential at all — see Headless & custom storefronts |
Export jobs — /api/admin/v1/exports | ✅ Available | Asynchronous CSV and JSONL exports as jobs: ask, poll, fetch a signed download |
Storefront API — /api/storefront/v1 | ✅ Available | Browser-safe reads on a publishable key: the Mix & Match catalogue, a live price preview, and the selling_plan_id a cart line needs |
Customer API — /api/customer/v1 | ✅ Available | A headless customer portal — the shopper’s Shopify customer token, exchanged for a Curobi session |
| Reference React components | ✅ Available | Eleven fork-and-restyle components for the headless purchase path and portal, including cart-line property helpers |
| Plan, bundle, Mix & Match, gift and win-back writes | Not built | write:plans, write:bundles, write:mixmatch, write:gifts and write:winback are published vocabulary, not working endpoints. They are not offered when you mint a key |
v1 is otherwise read-only, with three exceptions, in order of how much they can break.
- Subscription writes under
write:subscriptions. These change a merchant’s own data and move money, so they carry obligations nothing else on this surface does: a mandatoryIdempotency-Key, a tenancy check against contracts Curobi created, and a receipt rather than the resource. - Webhook endpoint management under
manage:webhooks— the API’s own plumbing, so a key that can start and stop event delivery still cannot change a contract, a plan or a price. POST /exports, a write in HTTP grammar only: it queues a read of rows the same key could already page through, and demands exactly the read scopes that paging would.
Everything else answers 405 method_not_allowed to a POST,
PUT, PATCH or DELETE — after authenticating, so an unauthenticated probe still gets a
401 and learns nothing about which paths exist.
Two limits worth knowing before you design around them
Curobi can only see contracts Curobi created. The app holds Shopify’s
read_own_subscription_contracts / write_own_subscription_contracts scopes, so a subscription
another app created is invisible to this API even on a store where Curobi is installed. This is a
Shopify permission boundary, not a Curobi decision. To bring old subscriptions across, use the
CSV import, which creates real Curobi-owned contracts.
The data is a mirror, not the ledger. Every value the API returns is Curobi’s local copy of what Shopify last said. Shopify owns the contract and the money. Reconcile against Shopify before you bill anything against these figures.
Conventions at a glance
Cursor-based, opaque cursors, { data, next_cursor }.
One envelope, a stable code, and a request_id on every response.
- Versioning is in the path (
/v1) and additive-only. New fields may appear; existing fields never change meaning and are never removed. Parse defensively — an unknown field is not an error. - Rate limits are per shop: 60 requests/minute sustained, burst 120.
- Request ids (
X-Curobi-Request-Id) are on every response. Quote one in a support request and we can find the exact call. - Protected Customer Data — names, email addresses and gift messages — comes back only to a key
holding
read:customers, and never over webhooks at any scope.