Fetching records
POST /v1/query answers questions about your data — totals, trends, breakdowns.
Sometimes you want the records themselves: the orders, with their fields, so
you can load them into another system.
That is what these endpoints are for, and they need no query language:
curl -H "Authorization: Bearer $ECOMSOLO_API_KEY" \
"https://api.ecomsolo.com/v1/orders?financial_status=paid&page_size=50"
Available datasets
| Path | Contents |
|---|---|
/v1/orders | Orders across every connected store |
/v1/customers | Customers |
/v1/products | Products |
/v1/draft_orders | Draft orders |
Each returns the same fields you can query with SoloQL. GET /v1/datasets lists
every field of every dataset, and is the authoritative reference — if a field is
listed there, you can request it, filter on it, and receive it here.
The response
{
"data": [
{
"order_name": "#1001",
"created_at": "2026-03-14T09:22:11Z",
"financial_status": "paid",
"total_price": 129.5,
"customer_name": "Ada Lovelace",
"store_id": "6f2c…"
}
],
"page": 1,
"page_size": 50,
"has_more": true
}
has_more tells you whether another page exists. There is no total count — see
Paging for why.
Filtering
Any field of the dataset is a filter. Use the field name as the query parameter:
# one value
/v1/orders?financial_status=paid
# several values (OR)
/v1/orders?financial_status=paid,partially_refunded
# combined (AND)
/v1/orders?financial_status=paid&fulfillment_status=fulfilled
Dates use created_at_min and created_at_max (ISO 8601, UTC):
/v1/orders?created_at_min=2026-03-01&created_at_max=2026-04-01
Restrict to particular stores with store_ids (comma-separated). Omit it and
you get every store your key can read:
/v1/orders?store_ids=6f2c…,9a1b…
info
An unknown filter returns 400 naming the offending parameter, rather than
silently ignoring it and returning the wrong rows. If a filter is rejected,
check GET /v1/datasets for the exact field name.
Choosing fields
Ask for only what you need with fields:
/v1/orders?fields=order_name,total_price,created_at
Worth doing for two reasons: responses get smaller and faster, and you stop receiving personal data you have no use for. If you are syncing revenue figures, requesting only the money fields means customer names never leave our systems at all.
Paging
/v1/orders?page=1&page_size=100
/v1/orders?page=2&page_size=100
page_size defaults to 50 and maxes at 250. Keep requesting pages while
has_more is true.
There is no total_count. Producing one costs a second query on every
request, and for the common case — loop until has_more is false — it is not
needed. We would rather keep the endpoint fast than return a number most callers
discard.
warning
Paging is for reading, not for bulk extraction. If you are pulling tens of thousands of records — a full history load, a warehouse sync — use an export instead. Exports run in the background, handle any volume, and deliver a file to email, FTP, Google Drive or Sheets — and you can trigger one from code. Deep paging through a large dataset is slow for you and expensive for us, and results can shift underneath you if a store syncs midway.
A single record
curl -H "Authorization: Bearer $ECOMSOLO_API_KEY" \
"https://api.ecomsolo.com/v1/orders/6f2c8a1e…"
Returns the record directly, without the data wrapper. An id that does not
exist — or belongs to a store your key cannot read — returns 404. Those two
cases are deliberately indistinguishable, so the API never confirms the
existence of data you are not entitled to.
Which endpoint should I use?
| You want | Use |
|---|---|
| Revenue by month, top products, trends | POST /v1/query (SoloQL) |
| The orders themselves, to load elsewhere | GET /v1/orders |
| A specific record you have the id for | GET /v1/orders/{id} |
| Everything, in bulk, on a schedule | An export |
The two are complements, not alternatives. SoloQL answers questions — it aggregates and returns a flat table, and cannot hand you a record. These endpoints return records and never aggregate. Most integrations use both: a query for the summary, records for the detail behind it.
info
Not every field works on both. Aggregate-only fields like order_count exist so
COUNT has something to count and have no meaning on one record, so records
never return them — ask SoloQL for that number instead. GET /v1/datasets is
the authoritative field list for both surfaces.
Stability
The fields these endpoints return are a published contract. We may add new fields over time — your integration should ignore ones it does not recognise — but we will not remove a field or change its type without a new API version.
Fields are never added by accident: the published list is explicit, so internal changes on our side cannot quietly alter what you receive.