Download OpenAPI specification:
Public WordPress API Endpoints by OBS
The authentication is realized with an additional WordPress user that has a specific user role, only allowing it to access certain endpoints, no other WordPress access (you need the matching OBS plugin to provide that user role). To authenticate with the API, you need to create an Application Password for that user as username/password is not allowed for WordPress API access. Use the username and Application Password with BasicAuth
Get all order numbers of the last 30 days of orders that were already transferred to the middleware (done every 2 minutes).
| newer_than | string <date-time> Filter the orders (of the last 30 days) to be newer than the passed ISO 8601 / RFC 3339 timestamp |
[- "1698243392.125004871",
- "1697624864.125008737",
- "1697549911.125007887"
]Only returns orders with status = 2
| order_number required | string (Order_Number) [0-9]{10}\.[0-9]{8,9} Example: 1639331260.125003824 (Required) The order number |
{- "order_number": "1697624864.125008737",
- "shop_id": 125,
- "erp_order_number": "",
- "status": 1,
- "type": 0,
- "products": [
- {
- "id": "18871",
- "item_wrapper_id": "101231",
- "amount": 3,
- "name": "Nices Produkt 1",
- "price": 194.15,
- "price_currency": "EUR",
- "voucher_absolute_reduction": 19.42,
- "tax_percentage": 19,
- "unit_amount": 1,
- "unit_type": "kg",
- "unit_price_per_unit": 12,
- "weight": 2.5,
- "weight_unit": "kg",
- "brand": "KTM",
- "category_path": "bekleidung/accessoires/fan-artikel",
- "delivery_date_string": "21.12.2021 - 25.12.2021",
- "variant_values_string": "Farbe: blau, Größe: XL",
- "item_number_main": "76105979670",
- "item_numbers": "76105979670, 76105979570",
- "gtin": "string",
- "markings": [ ],
- "hazardous_materials": {
- "pictograms": [
- "GHS01"
], - "signal_word": "Danger",
- "statements": [
- [
- "H200",
- "H300+H310",
- "H441",
- "EUH 006",
- "EUH 451"
]
]
}, - "language": "de",
- "type": "product",
- "url": "string",
- "shipping_method_id": [
- 0
]
}
], - "customer_data": {
- "invoice_address": {
- "firstname": "Vorname",
- "lastname": "Nachname",
- "company_name": "CSB",
- "street": "Teststraße 123",
- "address_line_2": "Hinterhof 2",
- "city": "Teststadt",
- "zip_code": "23422",
- "country_code": "DE",
- "vat_id": "123456789",
- "vat_id_prefix": "DE",
- "vat_verification_id": "string"
}, - "email_address": "vorname.nachname@example.com",
- "phone_number": "012334534563",
- "use_extra_invoice_address": true,
- "advertising": {
- "email": false,
- "telephone": false,
- "post": false,
- "sms": "false"
}
}, - "shipping": {
- "shipping_address": {
- "firstname": "Vorname",
- "lastname": "Nachname",
- "company_name": "CSB",
- "street": "Teststraße 123",
- "address_line_2": "Hinterhof 2",
- "city": "Teststadt",
- "zip_code": "23422",
- "country_code": "DE"
}, - "send_to_parcel_locker": true,
- "shipping_sets": [
- {
- "shipping_set_id": "string",
- "shipping_id": 9,
- "payment_id": 0,
- "status": 1,
- "type": 0,
- "name": "Abholung",
- "description": "Abholung direkt im CSB-Schuppen",
- "price": 6.99,
- "free_from": 0,
- "product_ids": [
- "18871"
], - "product_amounts": {
- "2345": 3,
- "12345": 1
}, - "products_total_price": 194.15
}
], - "message": "Bitte schnell liefern!",
- "consent_use_telephone_number_order_updates": true,
- "consent_pass_on_email_delivery_updates": true
}, - "payment": {
- "id": 21,
- "type": 4,
- "name": "PayPal",
- "description": "mit PayPal bezahlen",
- "price": 0,
- "external_payment_response": { },
- "external_payment_response_error": { }
}, - "price": {
- "products": 126.99,
- "shipping": 6.99,
- "payment_method": 0,
- "voucher": {
- "voucher_data": {
- "id": 1077,
- "description": "Geschenkgutschein - 10€",
- "value_string": "- 10,00€",
- "voucher_percent": 0,
- "voucher_absolute": 10,
- "amount_valid_from": 10,
- "voucher_code": "WHN10"
}, - "voucher_reduction": 100,
- "shipping_reduction": 3.5,
- "product_tax_reduction": 19
}, - "sum_tax": 19,
- "sum_total": 100,
- "is_test_purchase": true
}, - "erp_customer_id": 0,
- "customer_id": "",
- "zip": "12345",
- "order_created": "2021-12-12 19:52:03",
- "shipping_handler_details": [
- {
- "name": "Versand2",
- "description": "Versand per Fuchs",
- "tracking_number": "Fuchs123",
- "tracking_url": "fuchsversand.org/tracking/Fuchs123",
- "product_ids": [
- "123234",
- "1234"
], - "product_amounts": {
- "1234": 1,
- "123234": 2
}
}, - {
- "name": "Abholung",
- "description": "Abhulung bei CSB",
- "product_ids": [
- "2342"
]
}
]
}Replaces the current value, to add details, first get the current value
| order_number required | string (Order_Number) [0-9]{10}\.[0-9]{8,9} Example: 1639331260.125003824 (Required) The order number |
Array of objects (Shipping_Handler_Details) | |||||||||||||||||
Array
| |||||||||||||||||
{- "shipping_handler_details": [
- {
- "name": "DHL Paketversand",
- "description": "Schnellerster Versand",
- "tracking_number": "Fuchs123",
- "tracking_url": "fuchsversand.org/tracking/Fuchs123",
- "product_ids": [
- "18871",
- "18571",
- "234871"
], - "product_amounts": {
- "18571": 3,
- "18871": 1,
- "234871": 1
}, - "timestamp_change": "2022-12-10 19:52:03",
- "expected_delivery": "2022-12-12 19:52:03"
}
]
}Retrieves the shipping handler details of the order, adds the new set to it, and saves it back to the database.
| order_number required | string (Order_Number) [0-9]{10}\.[0-9]{8,9} Example: 1639331260.125003824 (Required) The order number |
object (Shipping_Handler_Details) Real shipping/ delivery details entered by ERP or external: Tracking data, parcel info, etc. Empty when order created | |||||||||||||||||
| |||||||||||||||||
{- "shipping_handler_details": {
- "name": "DHL Paketversand",
- "description": "Schnellerster Versand",
- "tracking_number": "Fuchs123",
- "tracking_url": "fuchsversand.org/tracking/Fuchs123",
- "product_ids": [
- "18871",
- "18571",
- "234871"
], - "product_amounts": {
- "18571": 3,
- "18871": 1,
- "234871": 1
}, - "timestamp_change": "2022-12-10 19:52:03",
- "expected_delivery": "2022-12-12 19:52:03"
}
}Reports whether the OBS Metrics sales and tracking tables exist. Does not require OBS Metrics to be active.
{- "data": {
- "source_mode_effective": "metrics_local",
- "obs_metrics_present": true,
- "obs_tracking_present": true,
- "obs_reviews_present": true,
- "tracking_enabled": true,
- "reviews_enabled": true,
- "last_import_at": "string"
}, - "meta": {
- "generated_at": "2019-08-24T14:15:22Z",
- "source": "metrics_local"
}
}Oldest order date, last successful import time and whole-table record counts. Not period-scoped.
{- "data": {
- "oldest_order_date": "2019-08-24T14:15:22Z",
- "last_import_at": "string",
- "records": {
- "orders": 0,
- "order_products": 0,
- "vouchers": 0,
- "tracking_daily": 0,
- "product_reviews": 0,
- "inquiries": 0,
- "order_traffic": 0
}
}, - "meta": {
- "generated_at": "2019-08-24T14:15:22Z",
- "source": "metrics_local"
}
}revenue is SUM(orders.sum_total): the final order total (incl. shipping + payment, after voucher). Tax-inclusive, except for tax-exempt orders (delivery outside the EU, EU reverse charge), whose total is net -- the sum can therefore mix gross and net totals. Percentage vouchers are rounded to the cent per item before being multiplied by the quantity, so recomputing a total from its parts can differ by a few cents. See meta.revenue_basis.
| range | string^\d{1,3}d$ Default: "30d" X full local days ending yesterday (1..548). Default 30d. Not combinable with month. |
| end | string <date> Inclusive last day (YYYY-MM-DD), default yesterday in the shop timezone. Today is allowed but returns the partial current day; a future date is 400 invalid_date. Not combinable with month. |
| month | string^\d{4}-\d{2}$ Whole calendar month YYYY-MM. Not combinable with range/end (else 400 ambiguous_period). This selects the window; it is unrelated to granularity=month and the month dimension, which split a window into monthly rows. |
| status | string Enum: "1" "2" "100" "accepted" Optional order processing-stage filter: 1 (new), 100 (in progress), 2 (accepted), or the alias 'accepted' (= 2). Default: all. This is a processing stage, NOT a cancellation filter. Other values are ignored (= all). |
{- "data": {
- "revenue": 0,
- "net_revenue": 0,
- "tax_total": 0,
- "order_count": 0,
- "aov": 0,
- "products_total": 0
}, - "meta": {
- "generated_at": "2019-08-24T14:15:22Z",
- "range": "string",
- "start": "2019-08-24",
- "end": "2019-08-24",
- "source": "metrics_local",
- "revenue_basis": "order_total_after_voucher"
}
}revenue is SUM(order_products.amount * price): product line value before voucher, excluding shipping/payment, tax-inclusive. Ordered by revenue DESC. See meta.revenue_basis.
| by required | string Enum: "brand" "category" "product" Grouping for the top list. |
| range | string^\d{1,3}d$ Default: "30d" X full local days ending yesterday (1..548). Default 30d. Not combinable with month. |
| end | string <date> Inclusive last day (YYYY-MM-DD), default yesterday in the shop timezone. Today is allowed but returns the partial current day; a future date is 400 invalid_date. Not combinable with month. |
| month | string^\d{4}-\d{2}$ Whole calendar month YYYY-MM. Not combinable with range/end (else 400 ambiguous_period). This selects the window; it is unrelated to granularity=month and the month dimension, which split a window into monthly rows. |
| status | string Enum: "1" "2" "100" "accepted" Optional order processing-stage filter: 1 (new), 100 (in progress), 2 (accepted), or the alias 'accepted' (= 2). Default: all. This is a processing stage, NOT a cancellation filter. Other values are ignored (= all). |
| limit | integer [ 1 .. 100 ] Default: 10 Row limit, clamped server-side to 1..100. |
{- "data": [
- {
- "key": "string",
- "label": "string",
- "qty": 0,
- "revenue": 0
}
], - "meta": {
- "generated_at": "2019-08-24T14:15:22Z",
- "range": "string",
- "start": "2019-08-24",
- "end": "2019-08-24",
- "source": "metrics_local",
- "revenue_basis": "order_total_after_voucher"
}
}The general form of sales/top: the same aggregation over order lines, but grouped by whatever you ask for (including day), not capped at a ranking, and pageable via a keyset cursor -- so a consumer can pull an entire period and know from pagination.has_more that it saw every row. Rows only exist where there was a sale; a product with no sale on a day is simply absent, which after a complete pull is exactly what makes a zero derivable. Revenue is always item_gross_before_voucher. Dimensions: day, month, product, wrapper, brand, category, attribute, traffic_group. traffic_group is the traffic group of the order (Direct, Organic, Paid; same classification as the tracking traffic groups), so dimensions=traffic_group closes the funnel of tracking/breakdown per channel. Like the tracking data it is recorded only in the shop itself, not by the ERP: OBS Metrics copies it daily from the shop's order queue, which keeps orders for 28 days. Data therefore starts 28 days before the shop's OBS Metrics update that introduced it; older orders, and orders placed without a traffic group (visitor tracking off), are grouped as Unknown. records.order_traffic in data-foundation counts the orders recorded so far: null means the shop's OBS Metrics does not record traffic groups; a count that stops growing means recording has stopped (it runs with the daily OBS Metrics import, so that import must be set up). A shop whose OBS Metrics is too old answers the traffic_group dimension with 400 invalid_dimensions and the traffic_group filter with 409 metrics_required.
| dimensions required | string Example: dimensions=day,product Comma-separated grouping dimensions. Order matters: it defines the row order and therefore the cursor. Any unknown name is 400 invalid_dimensions. Use month for monthly groups (e.g. month,brand); the breakdown endpoints have no granularity parameter. A shop whose OBS Metrics predates the month dimension answers it with 400 invalid_dimensions. |
| sort | string Enum: "revenue" "qty" "orders" Omit for the pageable mode: rows ordered by the dimensions ascending, cursor supported, complete result set. Set it for the ranked mode: rows ordered by that measure descending, capped at limit, no cursor. Ranked mode is what /sales/top does. |
| range | string^\d{1,3}d$ Default: "30d" X full local days ending yesterday (1..548). Default 30d. Not combinable with month. |
| end | string <date> Inclusive last day (YYYY-MM-DD), default yesterday in the shop timezone. Today is allowed but returns the partial current day; a future date is 400 invalid_date. Not combinable with month. |
| month | string^\d{4}-\d{2}$ Whole calendar month YYYY-MM. Not combinable with range/end (else 400 ambiguous_period). This selects the window; it is unrelated to granularity=month and the month dimension, which split a window into monthly rows. |
| status | string Enum: "1" "2" "100" "accepted" Optional order processing-stage filter: 1 (new), 100 (in progress), 2 (accepted), or the alias 'accepted' (= 2). Default: all. This is a processing stage, NOT a cancellation filter. Other values are ignored (= all). |
| limit | integer [ 1 .. 10000 ] Default: 1000 Row limit, clamped server-side to 1..10000. Prefer large pages: every page re-runs the same aggregation, so a few big pages are much cheaper than many small ones. |
| cursor | string Opaque keyset cursor from pagination.next_cursor of the previous page. Stateless and non-expiring: it encodes the last row's dimension values plus a fingerprint of the query it belongs to. Replaying it against a different window, different dimensions or different filters is 400 invalid_cursor. Not combinable with sort (400 cursor_not_supported). |
| with_total | boolean Default: false Also return meta.total_rows, the total number of groups in the window ignoring limit and cursor. Off by default because it runs the aggregation a second time. |
| item_wrapper_id | string Restrict to one product (the wrapper that groups all variants). |
| item_id | string Restrict to one concrete product variant. |
| brand | string Restrict to one brand. Exact match on the stored value, as returned by the brand dimension. |
| category | string Restrict to one category path. Exact match on the stored value, as returned by the category dimension -- not a prefix match. |
| traffic_group | string Enum: "Direct" "Organic" "Paid" "Unknown" Restrict to orders of one traffic group. Unknown selects the orders without a recorded traffic group. Any other value is 400 rest_invalid_param. |
{- "data": [
- {
- "day": "2019-08-24",
- "month": "string",
- "product_id": "string",
- "item_wrapper_id": "string",
- "brand": "string",
- "category_path": "string",
- "variant_values": "string",
- "traffic_group": "Direct",
- "label": "string",
- "variants": "string",
- "thumbnail_url": "string",
- "order_count": 0,
- "quantity_sold": 0,
- "revenue": 0
}
], - "pagination": {
- "limit": 0,
- "has_more": true,
- "next_cursor": "string"
}, - "meta": {
- "generated_at": "2019-08-24T14:15:22Z",
- "range": "string",
- "start": "2019-08-24",
- "end": "2019-08-24",
- "source": "metrics_local",
- "revenue_basis": "order_total_after_voucher",
- "dimensions": [
- "string"
], - "sort": "string",
- "time_basis": "local_day",
- "total_rows": 0
}
}| range | string^\d{1,3}d$ Default: "30d" X full local days ending yesterday (1..548). Default 30d. Not combinable with month. |
| end | string <date> Inclusive last day (YYYY-MM-DD), default yesterday in the shop timezone. Today is allowed but returns the partial current day; a future date is 400 invalid_date. Not combinable with month. |
| month | string^\d{4}-\d{2}$ Whole calendar month YYYY-MM. Not combinable with range/end (else 400 ambiguous_period). This selects the window; it is unrelated to granularity=month and the month dimension, which split a window into monthly rows. |
| status | string Enum: "1" "2" "100" "accepted" Optional order processing-stage filter: 1 (new), 100 (in progress), 2 (accepted), or the alias 'accepted' (= 2). Default: all. This is a processing stage, NOT a cancellation filter. Other values are ignored (= all). |
{- "data": {
- "voucher_sum": 0,
- "count": 0,
- "by_voucher": [
- {
- "description": "string",
- "count": 0,
- "sum": 0
}
]
}, - "meta": {
- "generated_at": "2019-08-24T14:15:22Z",
- "range": "string",
- "start": "2019-08-24",
- "end": "2019-08-24",
- "source": "metrics_local",
- "revenue_basis": "order_total_after_voucher"
}
}| range | string^\d{1,3}d$ Default: "30d" X full local days ending yesterday (1..548). Default 30d. Not combinable with month. |
| end | string <date> Inclusive last day (YYYY-MM-DD), default yesterday in the shop timezone. Today is allowed but returns the partial current day; a future date is 400 invalid_date. Not combinable with month. |
| month | string^\d{4}-\d{2}$ Whole calendar month YYYY-MM. Not combinable with range/end (else 400 ambiguous_period). This selects the window; it is unrelated to granularity=month and the month dimension, which split a window into monthly rows. |
| status | string Enum: "1" "2" "100" "accepted" Optional order processing-stage filter: 1 (new), 100 (in progress), 2 (accepted), or the alias 'accepted' (= 2). Default: all. This is a processing stage, NOT a cancellation filter. Other values are ignored (= all). |
{- "data": [
- {
- "name": "string",
- "count": 0,
- "share": 1
}
], - "meta": {
- "generated_at": "2019-08-24T14:15:22Z",
- "range": "string",
- "start": "2019-08-24",
- "end": "2019-08-24",
- "source": "metrics_local",
- "revenue_basis": "order_total_after_voucher"
}
}| range | string^\d{1,3}d$ Default: "30d" X full local days ending yesterday (1..548). Default 30d. Not combinable with month. |
| end | string <date> Inclusive last day (YYYY-MM-DD), default yesterday in the shop timezone. Today is allowed but returns the partial current day; a future date is 400 invalid_date. Not combinable with month. |
| month | string^\d{4}-\d{2}$ Whole calendar month YYYY-MM. Not combinable with range/end (else 400 ambiguous_period). This selects the window; it is unrelated to granularity=month and the month dimension, which split a window into monthly rows. |
| status | string Enum: "1" "2" "100" "accepted" Optional order processing-stage filter: 1 (new), 100 (in progress), 2 (accepted), or the alias 'accepted' (= 2). Default: all. This is a processing stage, NOT a cancellation filter. Other values are ignored (= all). |
{- "data": {
- "avg_shipping": 0,
- "free_share": 1,
- "by_method": [
- {
- "name": "string",
- "count": 0,
- "share": 1
}
]
}, - "meta": {
- "generated_at": "2019-08-24T14:15:22Z",
- "range": "string",
- "start": "2019-08-24",
- "end": "2019-08-24",
- "source": "metrics_local",
- "revenue_basis": "order_total_after_voucher"
}
}One row per local day (default) or, with granularity=month, per local calendar month; buckets without orders are omitted. Month rows carry month instead of day and use exact local month boundaries (also across DST changes), so a full month row equals sales/summary?month=YYYY-MM. The first and last month are clipped to the requested window (see meta.start/meta.end). The window itself is unchanged: at most 548 days, i.e. up to 20 monthly rows.
| granularity | string Default: "day" Enum: "day" "month" Bucket size of the timeseries rows: day (default) or month. Any other value is 400 invalid_granularity. Not to be confused with the month parameter, which selects a whole month as the window. The window limit stays 548 days for both. |
| range | string^\d{1,3}d$ Default: "30d" X full local days ending yesterday (1..548). Default 30d. Not combinable with month. |
| end | string <date> Inclusive last day (YYYY-MM-DD), default yesterday in the shop timezone. Today is allowed but returns the partial current day; a future date is 400 invalid_date. Not combinable with month. |
| month | string^\d{4}-\d{2}$ Whole calendar month YYYY-MM. Not combinable with range/end (else 400 ambiguous_period). This selects the window; it is unrelated to granularity=month and the month dimension, which split a window into monthly rows. |
| status | string Enum: "1" "2" "100" "accepted" Optional order processing-stage filter: 1 (new), 100 (in progress), 2 (accepted), or the alias 'accepted' (= 2). Default: all. This is a processing stage, NOT a cancellation filter. Other values are ignored (= all). |
{- "data": [
- {
- "day": "2019-08-24",
- "revenue": 0,
- "order_count": 0,
- "products_total": 0
}
], - "meta": {
- "generated_at": "2019-08-24T14:15:22Z",
- "range": "string",
- "start": "2019-08-24",
- "end": "2019-08-24",
- "source": "metrics_local",
- "revenue_basis": "order_total_after_voucher",
- "granularity": "day"
}
}All-time (not period-scoped) basket combinations from local order history. base_orders_count reports how many orders contain the base product (0 = no local history; empty combinations then just means no data, not necessarily a non-existent product).
| item_wrapper_id required | integer The base product to find combinations for. |
| min_orders | integer >= 1 Default: 2 Minimum shared orders for a combination to count (default 2). |
| limit | integer [ 1 .. 100 ] Default: 10 Row limit, clamped server-side to 1..100. |
{- "data": {
- "item_wrapper_id": "string",
- "base_orders_count": 0,
- "combinations": [
- {
- "orders_count": 0,
- "products": [
- {
- "key": "string",
- "label": "string",
- "brand": "string"
}
]
}
]
}, - "meta": {
- "generated_at": "2019-08-24T14:15:22Z",
- "source": "metrics_local"
}
}| range | string^\d{1,3}d$ Default: "30d" X full local days ending yesterday (1..548). Default 30d. Not combinable with month. |
| end | string <date> Inclusive last day (YYYY-MM-DD), default yesterday in the shop timezone. Today is allowed but returns the partial current day; a future date is 400 invalid_date. Not combinable with month. |
| month | string^\d{4}-\d{2}$ Whole calendar month YYYY-MM. Not combinable with range/end (else 400 ambiguous_period). This selects the window; it is unrelated to granularity=month and the month dimension, which split a window into monthly rows. |
| item_wrapper_id | string Optional filter to a single product (item_wrapper_id). Empty is treated as not set. |
{- "data": {
- "views": 0,
- "add_to_cart": 0,
- "by_traffic_group": {
- "Direct": {
- "views": 0,
- "add_to_cart": 0
}, - "Organic": {
- "views": 0,
- "add_to_cart": 0
}, - "Paid": {
- "views": 0,
- "add_to_cart": 0
}
}
}, - "meta": {
- "generated_at": "2019-08-24T14:15:22Z",
- "range": "string",
- "start": "2019-08-24",
- "end": "2019-08-24",
- "source": "metrics_local",
- "revenue_basis": "order_total_after_voucher"
}
}| range | string^\d{1,3}d$ Default: "30d" X full local days ending yesterday (1..548). Default 30d. Not combinable with month. |
| end | string <date> Inclusive last day (YYYY-MM-DD), default yesterday in the shop timezone. Today is allowed but returns the partial current day; a future date is 400 invalid_date. Not combinable with month. |
| month | string^\d{4}-\d{2}$ Whole calendar month YYYY-MM. Not combinable with range/end (else 400 ambiguous_period). This selects the window; it is unrelated to granularity=month and the month dimension, which split a window into monthly rows. |
| item_wrapper_id | string Optional filter to a single product (item_wrapper_id). Empty is treated as not set. |
{- "data": [
- {
- "group": "Direct",
- "views": 0,
- "add_to_cart": 0,
- "share": 1
}
], - "meta": {
- "generated_at": "2019-08-24T14:15:22Z",
- "range": "string",
- "start": "2019-08-24",
- "end": "2019-08-24",
- "source": "metrics_local",
- "revenue_basis": "order_total_after_voucher"
}
}Both metrics are always returned; by selects the sort key. group selects whether rows are products (default), brands or categories.
| by required | string Enum: "views" "cart" Sort key for the tracking top list. |
| group | string Default: "product" Enum: "product" "brand" "category" Grouping for the tracking top list: product (default), brand or category. Other values are treated as product. |
| range | string^\d{1,3}d$ Default: "30d" X full local days ending yesterday (1..548). Default 30d. Not combinable with month. |
| end | string <date> Inclusive last day (YYYY-MM-DD), default yesterday in the shop timezone. Today is allowed but returns the partial current day; a future date is 400 invalid_date. Not combinable with month. |
| month | string^\d{4}-\d{2}$ Whole calendar month YYYY-MM. Not combinable with range/end (else 400 ambiguous_period). This selects the window; it is unrelated to granularity=month and the month dimension, which split a window into monthly rows. |
| item_wrapper_id | string Optional filter to a single product (item_wrapper_id). Empty is treated as not set. |
| limit | integer [ 1 .. 100 ] Default: 10 Row limit, clamped server-side to 1..100. |
{- "data": [
- {
- "key": "string",
- "label": "string",
- "views": 0,
- "add_to_cart": 0
}
], - "meta": {
- "generated_at": "2019-08-24T14:15:22Z",
- "range": "string",
- "start": "2019-08-24",
- "end": "2019-08-24",
- "source": "metrics_local",
- "revenue_basis": "order_total_after_voucher"
}
}The general form of tracking/top, with day and traffic_group available as dimensions in their own right, so per-product-per-channel-per-day is one request. Rows only exist where there was traffic. Note time_basis is utc_day here while sales/breakdown is local_day.
| dimensions required | string Example: dimensions=day,product Comma-separated grouping dimensions. Order matters: it defines the row order and therefore the cursor. Any unknown name is 400 invalid_dimensions. Use month for monthly groups (e.g. month,brand); the breakdown endpoints have no granularity parameter. A shop whose OBS Metrics predates the month dimension answers it with 400 invalid_dimensions. |
| sort | string Enum: "views" "cart" Omit for the pageable mode (dimension order, cursor supported, complete). Set for the ranked mode (measure descending, capped, no cursor). |
| range | string^\d{1,3}d$ Default: "30d" X full local days ending yesterday (1..548). Default 30d. Not combinable with month. |
| end | string <date> Inclusive last day (YYYY-MM-DD), default yesterday in the shop timezone. Today is allowed but returns the partial current day; a future date is 400 invalid_date. Not combinable with month. |
| month | string^\d{4}-\d{2}$ Whole calendar month YYYY-MM. Not combinable with range/end (else 400 ambiguous_period). This selects the window; it is unrelated to granularity=month and the month dimension, which split a window into monthly rows. |
| limit | integer [ 1 .. 10000 ] Default: 1000 Row limit, clamped server-side to 1..10000. Prefer large pages: every page re-runs the same aggregation, so a few big pages are much cheaper than many small ones. |
| cursor | string Opaque keyset cursor from pagination.next_cursor of the previous page. Stateless and non-expiring: it encodes the last row's dimension values plus a fingerprint of the query it belongs to. Replaying it against a different window, different dimensions or different filters is 400 invalid_cursor. Not combinable with sort (400 cursor_not_supported). |
| with_total | boolean Default: false Also return meta.total_rows, the total number of groups in the window ignoring limit and cursor. Off by default because it runs the aggregation a second time. |
| item_wrapper_id | string Restrict to one product (the wrapper that groups all variants). |
| item_id | string Restrict to one concrete product variant. |
| brand | string Restrict to one brand. Exact match on the stored value, as returned by the brand dimension. |
| category | string Restrict to one category path. Exact match on the stored value, as returned by the category dimension -- not a prefix match. |
| traffic_group | string Enum: "Direct" "Organic" "Paid" Restrict to one traffic group. Any other value is 400 rest_invalid_param. |
{- "data": [
- {
- "day": "2019-08-24",
- "month": "string",
- "product_id": "string",
- "item_wrapper_id": "string",
- "brand": "string",
- "category_path": "string",
- "variant_values": "string",
- "traffic_group": "Direct",
- "label": "string",
- "variants": "string",
- "thumbnail_url": "string",
- "views": 0,
- "add_to_cart": 0
}
], - "pagination": {
- "limit": 0,
- "has_more": true,
- "next_cursor": "string"
}, - "meta": {
- "generated_at": "2019-08-24T14:15:22Z",
- "range": "string",
- "start": "2019-08-24",
- "end": "2019-08-24",
- "source": "metrics_local",
- "revenue_basis": "order_total_after_voucher",
- "dimensions": [
- "string"
], - "sort": "string",
- "time_basis": "local_day",
- "total_rows": 0
}
}One row per UTC calendar day (default) or, with granularity=month, per month built from those UTC days. Month rows carry month instead of day. Unlike sales, tracking months therefore start at 00:00 UTC, not at local midnight. The window is unchanged: at most 548 days.
| granularity | string Default: "day" Enum: "day" "month" Bucket size of the timeseries rows: day (default) or month. Any other value is 400 invalid_granularity. Not to be confused with the month parameter, which selects a whole month as the window. The window limit stays 548 days for both. |
| range | string^\d{1,3}d$ Default: "30d" X full local days ending yesterday (1..548). Default 30d. Not combinable with month. |
| end | string <date> Inclusive last day (YYYY-MM-DD), default yesterday in the shop timezone. Today is allowed but returns the partial current day; a future date is 400 invalid_date. Not combinable with month. |
| month | string^\d{4}-\d{2}$ Whole calendar month YYYY-MM. Not combinable with range/end (else 400 ambiguous_period). This selects the window; it is unrelated to granularity=month and the month dimension, which split a window into monthly rows. |
{- "data": [
- {
- "day": "2019-08-24",
- "views": 0,
- "add_to_cart": 0
}
], - "meta": {
- "generated_at": "2019-08-24T14:15:22Z",
- "range": "string",
- "start": "2019-08-24",
- "end": "2019-08-24",
- "source": "metrics_local",
- "revenue_basis": "order_total_after_voucher",
- "granularity": "day"
}
}| range | string^\d{1,3}d$ Default: "30d" X full local days ending yesterday (1..548). Default 30d. Not combinable with month. |
| end | string <date> Inclusive last day (YYYY-MM-DD), default yesterday in the shop timezone. Today is allowed but returns the partial current day; a future date is 400 invalid_date. Not combinable with month. |
| month | string^\d{4}-\d{2}$ Whole calendar month YYYY-MM. Not combinable with range/end (else 400 ambiguous_period). This selects the window; it is unrelated to granularity=month and the month dimension, which split a window into monthly rows. |
| vendor | string Enum: "obs" "ekomi" "trusted_shops" Optional review-source filter: obs (this shop), ekomi or trusted_shops. Other values are ignored (= all sources). |
{- "data": {
- "review_count": 0,
- "avg_rating": 0,
- "unanswered": 0,
- "unanswered_share": 1
}, - "meta": {
- "generated_at": "2019-08-24T14:15:22Z",
- "range": "string",
- "start": "2019-08-24",
- "end": "2019-08-24",
- "source": "metrics_local",
- "revenue_basis": "order_total_after_voucher"
}
}| range | string^\d{1,3}d$ Default: "30d" X full local days ending yesterday (1..548). Default 30d. Not combinable with month. |
| end | string <date> Inclusive last day (YYYY-MM-DD), default yesterday in the shop timezone. Today is allowed but returns the partial current day; a future date is 400 invalid_date. Not combinable with month. |
| month | string^\d{4}-\d{2}$ Whole calendar month YYYY-MM. Not combinable with range/end (else 400 ambiguous_period). This selects the window; it is unrelated to granularity=month and the month dimension, which split a window into monthly rows. |
| vendor | string Enum: "obs" "ekomi" "trusted_shops" Optional review-source filter: obs (this shop), ekomi or trusted_shops. Other values are ignored (= all sources). |
| limit | integer [ 1 .. 100 ] Default: 10 Row limit, clamped server-side to 1..100. |
{- "data": [
- {
- "key": "string",
- "review_count": 0,
- "avg_rating": 0
}
], - "meta": {
- "generated_at": "2019-08-24T14:15:22Z",
- "range": "string",
- "start": "2019-08-24",
- "end": "2019-08-24",
- "source": "metrics_local",
- "revenue_basis": "order_total_after_voucher"
}
}The general form of reviews/top, and the only way to obtain a rating distribution: dimensions=wrapper,rating answers how many one-star reviews a product has, which an average cannot. vendor and locale are likewise not groupable anywhere else. Published reviews only. Dimensions: day, month, product, wrapper, rating, vendor, locale, brand, category. brand and category are not stored with a review but looked up per product from the imported orders (the product's brand and category as sold, not those of the reviewed order specifically); reviews of a product that appears in no imported order are grouped under an empty brand and category. The brand and category filters therefore only match reviews of products that have been sold in an imported order. A shop whose OBS Metrics is too old for brand and category answers those dimensions with 400 invalid_dimensions and those filters with 409 metrics_required.
| dimensions required | string Example: dimensions=day,product Comma-separated grouping dimensions. Order matters: it defines the row order and therefore the cursor. Any unknown name is 400 invalid_dimensions. Use month for monthly groups (e.g. month,brand); the breakdown endpoints have no granularity parameter. A shop whose OBS Metrics predates the month dimension answers it with 400 invalid_dimensions. |
| sort | string Enum: "reviews" "rating" Omit for the pageable mode (dimension order, cursor supported, complete). Set for the ranked mode (measure descending, capped, no cursor). |
| range | string^\d{1,3}d$ Default: "30d" X full local days ending yesterday (1..548). Default 30d. Not combinable with month. |
| end | string <date> Inclusive last day (YYYY-MM-DD), default yesterday in the shop timezone. Today is allowed but returns the partial current day; a future date is 400 invalid_date. Not combinable with month. |
| month | string^\d{4}-\d{2}$ Whole calendar month YYYY-MM. Not combinable with range/end (else 400 ambiguous_period). This selects the window; it is unrelated to granularity=month and the month dimension, which split a window into monthly rows. |
| vendor | string Enum: "obs" "ekomi" "trusted_shops" Optional review-source filter: obs (this shop), ekomi or trusted_shops. Other values are ignored (= all sources). |
| limit | integer [ 1 .. 10000 ] Default: 1000 Row limit, clamped server-side to 1..10000. Prefer large pages: every page re-runs the same aggregation, so a few big pages are much cheaper than many small ones. |
| cursor | string Opaque keyset cursor from pagination.next_cursor of the previous page. Stateless and non-expiring: it encodes the last row's dimension values plus a fingerprint of the query it belongs to. Replaying it against a different window, different dimensions or different filters is 400 invalid_cursor. Not combinable with sort (400 cursor_not_supported). |
| with_total | boolean Default: false Also return meta.total_rows, the total number of groups in the window ignoring limit and cursor. Off by default because it runs the aggregation a second time. |
| item_wrapper_id | string Restrict to one product (the wrapper that groups all variants). |
| item_id | string Restrict to one concrete product variant. |
| locale | string Restrict to one review locale. |
| brand | string Restrict to one brand. Exact match on the stored value, as returned by the brand dimension. |
| category | string Restrict to one category path. Exact match on the stored value, as returned by the category dimension -- not a prefix match. |
{- "data": [
- {
- "day": "2019-08-24",
- "month": "string",
- "product_id": "string",
- "item_wrapper_id": "string",
- "rating": 1,
- "vendor": "obs",
- "locale": "string",
- "brand": "string",
- "category_path": "string",
- "review_count": 0,
- "avg_rating": 0,
- "unanswered": 0
}
], - "pagination": {
- "limit": 0,
- "has_more": true,
- "next_cursor": "string"
}, - "meta": {
- "generated_at": "2019-08-24T14:15:22Z",
- "range": "string",
- "start": "2019-08-24",
- "end": "2019-08-24",
- "source": "metrics_local",
- "revenue_basis": "order_total_after_voucher",
- "dimensions": [
- "string"
], - "sort": "string",
- "time_basis": "local_day",
- "total_rows": 0
}
}Aggregates only (no message content). Inquiries counted by created_at.
| range | string^\d{1,3}d$ Default: "30d" X full local days ending yesterday (1..548). Default 30d. Not combinable with month. |
| end | string <date> Inclusive last day (YYYY-MM-DD), default yesterday in the shop timezone. Today is allowed but returns the partial current day; a future date is 400 invalid_date. Not combinable with month. |
| month | string^\d{4}-\d{2}$ Whole calendar month YYYY-MM. Not combinable with range/end (else 400 ambiguous_period). This selects the window; it is unrelated to granularity=month and the month dimension, which split a window into monthly rows. |
{- "data": {
- "inquiry_count": 0,
- "by_status": {
- "property1": 0,
- "property2": 0
}, - "responded": 0,
- "unanswered": 0,
- "unanswered_share": 1,
- "avg_first_response_seconds": 0,
- "by_context": [
- {
- "context": "string",
- "count": 0
}
]
}, - "meta": {
- "generated_at": "2019-08-24T14:15:22Z",
- "range": "string",
- "start": "2019-08-24",
- "end": "2019-08-24",
- "source": "metrics_local",
- "revenue_basis": "order_total_after_voucher"
}
}Reflects requests only (customers asking to withdraw/cancel); dealer/ERP resolution is not available. Local data cannot distinguish withdrawal from cancellation.
| range | string^\d{1,3}d$ Default: "30d" X full local days ending yesterday (1..548). Default 30d. Not combinable with month. |
| end | string <date> Inclusive last day (YYYY-MM-DD), default yesterday in the shop timezone. Today is allowed but returns the partial current day; a future date is 400 invalid_date. Not combinable with month. |
| month | string^\d{4}-\d{2}$ Whole calendar month YYYY-MM. Not combinable with range/end (else 400 ambiguous_period). This selects the window; it is unrelated to granularity=month and the month dimension, which split a window into monthly rows. |
{- "data": {
- "count": 0,
- "requests": [
- {
- "order_number": "string",
- "created_at": "string",
- "status": "string",
- "products": [
- {
- "product_id": "string",
- "item_wrapper_id": "string",
- "amount": 0
}
]
}
]
}, - "meta": {
- "generated_at": "2019-08-24T14:15:22Z",
- "range": "string",
- "start": "2019-08-24",
- "end": "2019-08-24",
- "source": "metrics_local",
- "revenue_basis": "order_total_after_voucher"
}
}Counts inquiries sent through the Ask block on a product page, created in the period and not deleted; inquiries from other pages, order inquiries and withdrawal requests are not included. Ordered by inquiry_count DESC, ties by item_wrapper_id and variant_id. Returns product IDs and counts only, no message content and no customer data. Inquiries without a selected variant are counted under variant_id null, so a product can appear both with null and with specific variants. meta.inquiry_count is the number of product-page inquiries in the period, meta.unattributed_count how many of them could not be linked to a product (no product reference stored, malformed IDs, or a reference that cannot be decrypted, e.g. after the shop's encryption key changed); these are not ranked. There is no filter for a single product.
| range | string^\d{1,3}d$ Default: "30d" X full local days ending yesterday (1..548). Default 30d. Not combinable with month. |
| end | string <date> Inclusive last day (YYYY-MM-DD), default yesterday in the shop timezone. Today is allowed but returns the partial current day; a future date is 400 invalid_date. Not combinable with month. |
| month | string^\d{4}-\d{2}$ Whole calendar month YYYY-MM. Not combinable with range/end (else 400 ambiguous_period). This selects the window; it is unrelated to granularity=month and the month dimension, which split a window into monthly rows. |
| limit | integer [ 1 .. 100 ] Default: 10 Row limit, clamped server-side to 1..100. |
{- "data": [
- {
- "item_wrapper_id": "string",
- "variant_id": "string",
- "inquiry_count": 0
}
], - "meta": {
- "generated_at": "2019-08-24T14:15:22Z",
- "range": "string",
- "start": "2019-08-24",
- "end": "2019-08-24",
- "source": "metrics_local",
- "revenue_basis": "order_total_after_voucher",
- "inquiry_count": 0,
- "unattributed_count": 0
}
}Returns price, tax, stock and availability information for the requested MPNs of a single brand. Used to feed the SPF spare-parts catalogue. The response is keyed by MPN; MPNs without a matching product are omitted. At most 100 MPNs are processed per request.
| mpns required | Array of strings [ 1 .. 100 ] items The MPNs (manufacturer part numbers) of the products to look up. Duplicate values are ignored. At most 100 MPNs are processed per request. |
| brand required | string non-empty The brand the requested products belong to |
{- "mpns": [
- "93505088000",
- "93503001000",
- "61430018000"
], - "brand": "KTM"
}{- "93503001000": {
- "price": 1147.05,
- "tax": 19,
- "stock_amount": 0,
- "reorderable": true,
- "item_id": "12312",
- "product_id": "100013478",
- "action": "add_product",
- "availability": "reorderable"
}, - "93505088000": {
- "price": 10.6,
- "tax": 19,
- "stock_amount": 12,
- "reorderable": false,
- "item_id": "323423",
- "product_id": "100013465",
- "action": "add_product",
- "availability": "in_stock"
}, - "61430018000": {
- "price": 1088.15,
- "tax": 19,
- "stock_amount": 0,
- "reorderable": false,
- "item_id": "34534532",
- "product_id": "100028239",
- "action": "request_product",
- "availability": "not_available"
}
}