Composite query & includes¶
Two features let you fetch exactly what you need in as few round-trips as possible.
?include= — embed related objects¶
Most list and single endpoints accept ?include=a,b to embed related objects inline, resolved
in one batch (no N+1). For example, a sale with its client:
curl "https://crm.h-profit.com/bapi-v2/sales?include=client&limit=10" \
-H "Authorization: hp_live_your_key_here"
{
"id": 4603, "amount": "…", "client_id": 105424,
"client": { "id": 105424, "first_name": "Yaroslav", "phone": "…" }
}
An unknown include name returns 422. If a foreign key is null, the embedded value is null
(for expenses — an empty array).
Relations¶
| Resource | include values |
|---|---|
sales |
client |
orders |
client, sale |
shipments |
supplier, expenses |
expenses |
warehouse |
productions |
category |
products |
images |
POST /query — many resources in one call¶
Ask for several resources (each with its own filter, paging, field projection and includes) in
a single request. Requires a valid key; each sub-query is checked against its own
resource:read scope.
Request:
{
"queries": {
"recent_sales": {
"resource": "sales",
"filter": { "warehouse_id": 8562 },
"limit": 20,
"include": ["client"],
"fields": ["id", "amount", "sold_at", "client"]
},
"catalog": {
"resource": "products",
"filter": { "category_id": 18726 },
"limit": 100
}
}
}
Response — keyed by your alias:
{
"success": true,
"data": {
"recent_sales": { "data": [ /* … */ ], "meta": { "limit": 20, "offset": 0 } },
"catalog": { "data": [ /* … */ ], "meta": { "limit": 100, "offset": 0 } }
},
"meta": { "count": 2 }
}
queries may also be an array, where each item optionally carries as (defaults to the
resource name):
{ "queries": [ { "resource": "warehouses", "as": "wh" },
{ "resource": "clients", "filter": { "with_debt": 1 }, "limit": 50 } ] }
Sub-query fields¶
| Field | Meaning |
|---|---|
resource |
required — one of the resources |
filter |
object of the same filters the resource's GET accepts |
limit / offset |
paging (limit capped at 500) |
include |
array of relation names (relations) |
fields |
whitelist of top-level keys to keep (id is always kept) |
Error isolation¶
One bad sub-query never fails the batch — its slot carries an error instead of data:
{
"success": true,
"data": {
"ok_one": { "data": [ /* … */ ], "meta": { "limit": 100, "offset": 0 } },
"bad_one": { "error": { "code": "forbidden", "message": "insufficient scope",
"details": { "required": ["expenses:read"] } } }
}
}
Limits¶
- At most 10 sub-queries per request.
- Each sub-query
limitis capped at 500.
Queryable resources: sales, orders, shipments, expenses, clients, categories,
products, warehouses, suppliers, product_sync, productions.