MerchantFlow Public API - Read a Merchant's Profitability Data
How third-party applications connect to MerchantFlow with OAuth 2.1 and read order economics, products, and profit and loss on a merchant's behalf.
MerchantFlow Public API
The Public API lets your application read a MerchantFlow merchant's order economics, products, and profit and loss - with their explicit permission, and without ever receiving customer names, email addresses, phone numbers, or shipping addresses.
It is built for the case where you already know something about a merchant's store and want to attach real profit to it: a funnel or experiment platform matching a Shopify order to the campaign that produced it, an inventory tool that needs true landed cost, a reporting product consolidating several systems.
This API is read-only. Every endpoint is GET. There are no write scopes to
request, so connecting your application can never change a merchant's data.
Who can connect
Partner applications are provisioned by MerchantFlow. You cannot self-register: an application that has not been provisioned is refused at the consent screen and its tokens are refused by the API, even if it completes an OAuth flow.
To get credentials, contact MerchantFlow with your application name, the redirect
URI you will use, and the scopes you need. You will receive a client_id and a
client_secret.
Merchants on every paid plan can connect your application. Plans differ in how far back their history goes, not in whether the API works - see Incremental sync.
The shape of an integration
- Send the merchant through the OAuth flow. They sign in, choose which store
to share, and approve the scopes you asked for. Include
store:readso the next step works. See Authentication. - Call
/api/v1/accountto confirm which store you are connected to, what currency it reports in, and how far back its plan lets you read. - Backfill with
GET /api/v1/orders, paging through cursors. - Stay current by re-calling the same endpoint with
updated_after. This is the important part, and it is not the same as "orders created since": an order's COGS or fulfilment cost can change days after it was placed, andupdated_afterwill bring it back to you when it does.
Base URL and contract
https://merchantflow.ai/api/v1A machine-readable OpenAPI 3.1 description is published, unauthenticated, at:
https://merchantflow.ai/api/v1/openapi.jsonYou can point a code generator at it directly.
A first request
curl https://merchantflow.ai/api/v1/account \
-H "Authorization: Bearer $ACCESS_TOKEN"{
"success": true,
"data": {
"store": {
"id": "ten_9f2b...",
"name": "Northbound Supply",
"platform": "shopify",
"shop_domain": "northbound-supply.myshopify.com",
"currency": "AUD",
"timezone": "Australia/Adelaide"
},
"data_availability": {
"history_days": 365,
"available_from": "2025-09-03",
"last_sync_at": "2026-09-03T04:11:00Z",
"stale": false
}
},
"meta": {
"store_id": "ten_9f2b...",
"currency": "AUD",
"timezone": "Australia/Adelaide",
"as_of": "2026-09-03T04:11:00Z",
"stale": false,
"history_available_from": "2025-09-03",
"truncated": false
}
}Response envelope
Every response has the same shape.
| Field | Meaning |
|---|---|
success | true on a 2xx response |
data | The payload - an object for single resources, an array for lists |
meta | Provenance: store, currency, timezone, data freshness, plan window |
page | Present on list endpoints: has_more, next_cursor, limit |
meta.as_of is when the store last synced with its commerce and ad platforms -
not when you made the request. If meta.stale is true, that sync is more than
24 hours old and the numbers you are reading may lag the merchant's actual
storefront. Surfacing that to your own users is usually worth doing.
Errors use the same envelope inverted:
{
"success": false,
"error": { "code": "insufficient_scope", "message": "This endpoint requires the \"orders:read\" scope." }
}Two numbers to be careful with
MerchantFlow deliberately tells you when a figure is an estimate rather than a measurement. If you display these to a merchant, carry the caveat with them.
ad_spend_allocated is an allocation, not measured spend. No ad platform
reports spend at order granularity, so a day's total is divided across that day's
eligible orders. Every order says so in ad_spend_basis. Presenting it as the ad
spend for one specific order - or one specific funnel - is a claim MerchantFlow's
data does not support.
cogs_coverage_pct below 100 means the margin is overstated. It is the
percentage of units on an order that actually have cost data. An order showing a
92% margin and 10% coverage is not a profitable order; it is an order with
missing costs.
Both are covered in Data and privacy.
What you never receive
No customer names, email addresses, phone numbers, or shipping addresses. Orders
carry shipping_country_code and a pseudonymous customer_ref, and nothing else
that identifies a person.
This is a structural guarantee, not a filter applied on the way out - the fields are never read from the database. See Data and privacy.
Next
- Authentication - the OAuth 2.1 flow, step by step
- Scopes - what each one grants
- Incremental sync - pagination and staying current
- Endpoints - the full reference
- Data and privacy - what the numbers mean and what is excluded
Last updated: September 22, 2026
Last updated on
Power Up Your AI with the MerchantFlow Skill File
Download the MerchantFlow Skill file and install it in Claude, Cursor, or Windsurf for dramatically better answer quality from your AI assistant.
Public API Authentication - OAuth 2.1 with PKCE
Step-by-step OAuth 2.1 authorization code flow for connecting a partner application to a MerchantFlow merchant, including PKCE, the resource indicator, and refresh tokens.