API & automatic connections
Included in Starter, Growth, Scale and Scale Plus. An active or trialing paid subscription is required for every synchronization. Each workspace keeps its existing record limit. Administrators manage connections in API & connections.
Choose a connection
- Shopify: enter the myshopify.com address and app client credentials for a store in your own organization, or an offline Admin API token. Client credentials are exchanged automatically for renewed access tokens. Required scopes: read_products, read_inventory, read_orders; product-cost visibility is required for unit costs. Older orders require read_all_orders. This is a merchant-configured connection; it does not claim Shopify App Store approval.
- WooCommerce: create a read-only consumer key/secret under Settings → Advanced → REST API and enter your store URL. Products, product variations, sales, line-level refunds and tracked available stock are read automatically.
- JSON / REST / ERP: provide an HTTPS URL returning an array of records or
{"records": [...], "nextCursor": "..."}. When nextCursor exists it is sent as the cursor query parameter on the next request. Choose product, order or inventory and optionally map source field names to API field names. A Bearer token is supported. - CSV / Excel / Google Sheets: provide a direct UTF-8 CSV export URL. Use a published Sheets CSV export, an authenticated CSV endpoint, or an ERP export URL. Excel workbook URLs and private Google Sheets share pages are not CSV sources. Local files require an export process to publish changes. Maximum 1,000 rows and 2 MB per page/file.
- REST API / HTTP webhooks: call the endpoint below from your ERP, application, script, n8n, Make or Zapier HTTP action. No dedicated account connector is required. Native platform webhook payloads must be mapped to the documented format.
Automatic execution
Connections run on the server while the browser is closed. The scheduler checks due connections every five minutes. Choose a 30-minute, hourly, six-hour or daily interval between completed cycles. Large stores progress in paginated batches. The first complete import can take longer than the chosen cycle interval. Each scheduler invocation processes up to ten pages for each of ten due connections; busy queues can delay runs. Source failures retry with backoff up to six hours. The panel shows the last successful page, cycle completion and errors; you can pause, resume, disconnect or run the next page now.
Inventory from store connectors is the total available stock across the store, stored as a store-specific warehouse. It is not a per-location warehouse synchronization. Products and orders use SKUs; items without a SKU use stable provider IDs. Set consistent unique SKUs before connecting multiple sources. Connectors merge only fields they provide and preserve manually entered costs. Missing fees, shipping, advertising or costs stay unknown. Cancellations and unpaid orders have zero sales. Removed products and deleted source rows are not deleted automatically; clear obsolete stock explicitly through a zero-stock record. Source-specific financial adjustments without line allocation require a normalized API feed.
Authentication
Create a named API key with read/write and entity permissions. Send it as Authorization: Bearer YOUR_API_KEY. Keys are shown once, stored as hashes, expire after one year by default and can be revoked immediately. A key stops working when its creator loses administrator access or the workspace loses its paid subscription. Never put keys in browser JavaScript or query parameters. Connection credentials and source URLs are encrypted on the server.
POST /api/v1/sync
Headers: Content-Type: application/json, Authorization: Bearer YOUR_API_KEY, Idempotency-Key: YOUR_UNIQUE_BATCH_ID. A request contains 1–1,000 records, maximum 2 MB. Send complete required fields; optional fields omitted in the default merge mode preserve existing values. Use "mode":"replace" only to intentionally replace all fields with schema defaults for omitted optional values.
{
"source": "ERP",
"observedAt": "2026-10-26T10:00:00Z",
"records": [
{
"entity": "product",
"data": {
"sku": "SKU-001",
"name": "Example product",
"cogs": 12,
"currency": "EUR"
}
},
{
"entity": "inventory",
"data": {
"sku": "SKU-001",
"warehouse": "Main",
"country": "DE",
"stock": 50,
"snapshotDate": "2026-10-26"
}
}
]
}curl https://stockandmargin.com/api/v1/sync -H "Authorization: Bearer $STOCK_MARGIN_API_KEY" -H "Content-Type: application/json" -H "Idempotency-Key: erp-batch-00001" --data-binary @batch.json
observedAt is the time the source snapshot was captured, including timezone. Keep it and the batch ID unchanged on retries. Older snapshots cannot overwrite newer API data. The same timestamp with different data is ignored as stale; use a newer source snapshot timestamp for corrections. Identifiers must not contain the pipe character. Requests are atomic: one invalid row or exceeding the record limit rejects the whole batch. Repeat the same key and normalized payload to replay a response without applying changes again. Reusing a batch ID with different data returns 409. Replay receipts are kept for 90 days; natural-key upserts still prevent duplicates after expiry.
Response: {"ok":true,"processed":2,"changed":2,"unchanged":0,"stale":0,"replayed":false}. Identity: product = sku; order = channel + country + orderId + sku; inventory = sku + warehouse + country. Repeat rows update existing records. Source connectors group repeated SKU lines within the same order. Use one authoritative source for each record; integration timestamps do not protect manual edits from a future source update.
Fields
- Product required: sku, name. Optional: ean, brand, category, supplier, cogs (unit cost or null), currency, annualRevenue, role.
- Order required: orderId, sku, date (YYYY-MM-DD), channel, country (ISO 2 letters), units (positive integer), revenue (non-negative, excluding tax). Optional: currency, discounts, returns, cogs, fees, fulfilment, logistics, advertising, otherCosts. Monetary order fields are totals for the complete order/SKU line, not per-unit values. Unknown optional costs must be omitted or null.
- Inventory required: sku, warehouse, country, stock (non-negative), snapshotDate. Optional: allocated, dailySales, leadDays, targetDays, moq.
Shopify connector sales are net after source discounts and excluding included tax; discounts are therefore recorded as zero to avoid deducting them twice. WooCommerce records pre-discount net subtotal and discounts separately. Shipping revenue, unallocated adjustments and processor settlements require your own normalized feed if needed. Negative available stock and unsupported records produce visible errors rather than silently changing values. Very large Shopify orders exceeding 100 lines or refund lines require a complete normalized API feed.
GET /api/v1/records
Requires read permission. Parameters: entity=product|order|inventory, limit=1..1000 (default 100), cursor=the previous nextCursor. Returns records and nextCursor, scoped to the key's workspace and allowed entities. Pages follow stable record IDs. This is not an immutable export snapshot.
Limits & errors
600 requests per workspace per hour across API keys. 400 = invalid data; 401 = invalid, expired or revoked key; 402 = inactive paid plan or record limit; 403 = missing permission; 409 = idempotency conflict; 429 = rate limit; 500 = temporary server failure. Retry network errors, 429 and 5xx using the same payload and idempotency key with exponential backoff. Honor Retry-After for 429. Fix validation, permission and quota errors before retrying. Request bodies and credentials are not included in activity logs. Integration activity is kept for 90 days.