Introduction
The storeVero API lets you build themes, apps and integrations on top of every storeVero store. It is organised around REST: predictable resource URLs, form- or JSON-encoded request bodies, JSON responses, and standard HTTP verbs and status codes. If you have called Stripe or Shopify, this will feel familiar.
Base URL & versioning
All Admin API requests are made to the versioned base URL below. The Storefront API is public and scoped to a single store by its handle.
Admin API https://storevero.com/api/v1
Storefront API https://storevero.com/api/v1/ecommerce/storefront/{store-handle}
GraphQL https://storevero.com/api/v1/storefront/graphql
The current version is v1. Breaking changes ship under a new version prefix; additive changes (new fields, new endpoints) can arrive within v1, so write tolerant parsers that ignore unknown fields.
Authentication
The Admin API authenticates with a Bearer token. Create one in Settings → API keys, or exchange email + password at the auth endpoint. Send it in the Authorization header on every request. Never expose an admin token in client-side code.
Get a token
/auth/logincurl -X POST https://storevero.com/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"you@store.com","password":"••••••••"}'
const res = await fetch('https://storevero.com/api/v1/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email: 'you@store.com', password: '••••••••' })
});
const { token } = await res.json();
$res = Http::post('https://storevero.com/api/v1/auth/login', [
'email' => 'you@store.com',
'password' => '••••••••',
]);
$token = $res->json('token');
Authenticate a request
curl https://storevero.com/api/v1/ecommerce/products \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Accept: application/json"
const res = await fetch('https://storevero.com/api/v1/ecommerce/products', {
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
$res = Http::withToken($token)
->acceptJson()
->get('https://storevero.com/api/v1/ecommerce/products');
X-Shopify-Storefront-Access-Token header for GraphQL, or simply call the store-scoped REST routes under your store handle.
Rate limits
The Admin API uses a leaky-bucket limiter. Every response carries your current budget in headers, so you can back off before you are throttled.
| Plan | Requests / minute | Burst |
|---|---|---|
| Starter | 120 | 40 |
| Growth | 600 | 120 |
| Enterprise | Custom | Custom |
When you exceed the limit you receive 429 Too Many Requests with a Retry-After header. Watch X-RateLimit-Remaining and slow down as it approaches zero.
Errors
storeVero uses conventional HTTP status codes. 2xx means success, 4xx means the request was rejected (a missing field, a bad token), and 5xx means something went wrong on our side. Validation errors return 422 with a field-keyed errors object.
{
"message": "The name field is required.",
"errors": {
"name": ["The name field is required."],
"price": ["The price must be a number."]
}
}
200OK201Created401Unauthenticated — bad or missing token403Forbidden — token lacks scope404Resource not found422Validation failed429Rate limited500Server errorPagination
List endpoints are paginated. Pass page and per_page (max 100). Responses include a meta block with totals and the current page so you can build a pager or loop until you have everything.
{
"data": [ /* … 25 products … */ ],
"meta": { "current_page": 2, "per_page": 25, "total": 214, "last_page": 9 }
}
Products
Create, read, update and delete products, including variants, images, pricing and inventory. Products belong to the store tied to your token.
/ecommerce/products/ecommerce/products/ecommerce/products/{id}/ecommerce/products/{id}/ecommerce/products/{id}Create a product
curl -X POST https://storevero.com/api/v1/ecommerce/products \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Aroma Diffuser",
"price": 1499,
"sku": "AD-001",
"stock": 50,
"category_id": 3,
"is_active": true
}'
await fetch('https://storevero.com/api/v1/ecommerce/products', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'Aroma Diffuser', price: 1499,
sku: 'AD-001', stock: 50, category_id: 3, is_active: true
})
});
Http::withToken($token)->post(
'https://storevero.com/api/v1/ecommerce/products', [
'name' => 'Aroma Diffuser', 'price' => 1499,
'sku' => 'AD-001', 'stock' => 50, 'category_id' => 3, 'is_active' => true,
]);
Response
{
"data": {
"id": 41, "name": "Aroma Diffuser", "slug": "aroma-diffuser",
"price": "1499.00", "sku": "AD-001", "stock": 50,
"category_id": 3, "is_active": true,
"created_at": "2026-07-29T10:20:31Z"
}
}
Collections & categories
Organise your catalogue with collections, categories and brands. All three share the same CRUD shape and require only a name.
/ecommerce/collections/ecommerce/collections/ecommerce/categories/ecommerce/categories/ecommerce/brands/ecommerce/brandsOrders
Read orders, filter by status or customer, fulfil, refund and export. Orders are immutable ledgers — you transition their state rather than editing line items after the fact.
/orders/orders/{id}/orders/{id}/orders/{id}/fulfill/orders/{id}/refund/orders/exportFulfil an order
curl -X POST https://storevero.com/api/v1/orders/1042/fulfill \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "tracking_number": "IN123456789", "carrier": "Delhivery" }'
await fetch('https://storevero.com/api/v1/orders/1042/fulfill', {
method: 'POST',
headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' },
body: JSON.stringify({ tracking_number: 'IN123456789', carrier: 'Delhivery' })
});
Http::withToken($token)->post(
'https://storevero.com/api/v1/orders/1042/fulfill', [
'tracking_number' => 'IN123456789', 'carrier' => 'Delhivery',
]);
Customers
Look up customers, their order history and lifetime value, and honour privacy requests with a one-call GDPR export.
/customers/customers/{id}/customers/{id}/customers/{id}/orders/customers/{id}/gdpr-exportInventory
Adjust stock with an auditable movement. You send a delta (positive or negative) and a reason; storeVero records the movement and updates the on-hand balance.
/ecommerce/inventory/adjustcurl -X POST https://storevero.com/api/v1/ecommerce/inventory/adjust \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "product_id": 41, "quantity": -3, "reason": "sale" }'
await fetch('https://storevero.com/api/v1/ecommerce/inventory/adjust', {
method: 'POST',
headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' },
body: JSON.stringify({ product_id: 41, quantity: -3, reason: 'sale' })
});
Http::withToken($token)->post(
'https://storevero.com/api/v1/ecommerce/inventory/adjust', [
'product_id' => 41, 'quantity' => -3, 'reason' => 'sale',
]);
reason is one of purchase, sale, return, adjustment or transfer.
Reviews
Moderate product reviews. Reviews arrive pending from the storefront (see the Storefront API); approve, reply or remove them here.
/ecommerce/reviews/ecommerce/reviews/{id}/ecommerce/reviews/{id}Bulk operations
Import or mutate many records in one call — ideal for migrations and nightly syncs. Send an array of operations and receive a per-row result set.
/bulk/products/bulk/orders/bulk/customersStorefront REST
Public, store-scoped endpoints for building custom storefronts, mobile apps and headless experiences. Every route is prefixed with the store handle. No admin token required.
/…/{store}/products/…/{store}/products/{slug}/…/{store}/categories/…/{store}/search?q=/…/{store}/autocomplete?q=/…/{store}/delivery-options/…/{store}/reviews/{product}/…/{store}/reviews/…/{store}/ordersPlace an order
curl -X POST https://storevero.com/api/v1/ecommerce/storefront/demo/orders \
-H "Content-Type: application/json" \
-d '{
"customer_email": "buyer@example.com",
"items": [{ "product_id": 41, "quantity": 2 }],
"shipping_address": { "name": "A. Kumar", "city": "Pune", "pincode": "411001" }
}'
await fetch('https://storevero.com/api/v1/ecommerce/storefront/demo/orders', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
customer_email: 'buyer@example.com',
items: [{ product_id: 41, quantity: 2 }],
shipping_address: { name: 'A. Kumar', city: 'Pune', pincode: '411001' }
})
});
Http::post('https://storevero.com/api/v1/ecommerce/storefront/demo/orders', [
'customer_email' => 'buyer@example.com',
'items' => [['product_id' => 41, 'quantity' => 2]],
'shipping_address' => ['name' => 'A. Kumar', 'city' => 'Pune', 'pincode' => '411001'],
]);
Storefront GraphQL
A Shopify-shaped GraphQL Storefront API — edges, nodes and cart mutations — so tools and snippets from the Shopify ecosystem port over with minimal changes. Authenticate with a storefront access token.
/storefront/graphqlquery ProductByHandle($handle: String!) {
productByHandle(handle: $handle) {
id
title
handle
priceRange { minVariantPrice { amount currencyCode } }
images(first: 3) { edges { node { url altText } } }
}
}
curl -X POST https://storevero.com/api/v1/storefront/graphql \
-H "X-Shopify-Storefront-Access-Token: YOUR_STOREFRONT_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "query": "{ productByHandle(handle: \"aroma-diffuser\") { title } }" }'
mutation {
cartCreate(input: { lines: [{ merchandiseId: "41", quantity: 2 }] }) {
cart { id checkoutUrl
lines(first: 10) { edges { node { quantity } } }
}
}
}
Webhooks
Subscribe to events and storeVero will POST a JSON payload to your endpoint the moment they happen. Every delivery is signed with HMAC-SHA256 in the X-StoreVero-Hmac-Sha256 header — always verify it before trusting the body.
orders/createorders/paidorders/fulfilledorders/cancelledproducts/createproducts/updatecustomers/createcarts/abandonedapp/uninstalledreviews/createVerify a signature
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_STOREVERO_HMAC_SHA256'] ?? '';
$expected = base64_encode(hash_hmac('sha256', $payload, $webhookSecret, true));
if (! hash_equals($expected, $signature)) {
http_response_code(401); exit;
}
// ✓ verified — parse and handle
$event = json_decode($payload, true);
import crypto from 'crypto';
function verify(rawBody, signature, secret) {
const expected = crypto.createHmac('sha256', secret)
.update(rawBody, 'utf8').digest('base64');
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
}
SDKs & libraries
The API is plain HTTP + JSON, so any HTTP client works. These helpers make it faster.
npm i @storevero/sdkcomposer require storevero/sdkPostman collectionChangelog
Ready to build?
Create a free store, generate an API key, and make your first call in minutes.
Get your API key