Exporting Your Data via the ProfitMetrics API
A complete reference for programmatically fetching revenue, profit, ad spend, and other dashboard metrics from your ProfitMetrics account.
ProfitMetrics exposes two JSON endpoints for pulling dashboard metrics into your own BI tools, spreadsheets, or data warehouse. This article is the full reference: it covers which endpoint to choose, authentication, every request and response field, the complete metrics catalogue, code examples in three languages, and the full error code list for both endpoints.
- What You Need
- Choosing the Right Endpoint
- Authentication
- Endpoint 1 — The Export Endpoint (
export/v2) - Endpoint 2 — The Reports Endpoint (
data/reports) - Resolutions and Time Buckets
- Behavioural Details
- Marketing Channel Calculation
- Discovering Available Metrics
- Metrics Catalogue
- Code Examples
- Related Endpoints
- Troubleshooting
What You Need
Before your first call, gather the following. Without these, the API will reject the request.
| Item | Details |
|---|---|
| API key | Generated in the ProfitMetrics dashboard. The key must hold the METRICS_READ scope. |
| Customer Site ID (CSID) | The numeric ID of the shop you want data for. Found in your dashboard URL or site settings. |
| Site authorisation | The API key must be authorised for every CSID listed in the request. Mixed access will reject the whole call. |
| HTTPS client | Anything that can send a JSON POST request — cURL, Postman, Python, Node, your ETL tool, etc. |
Choosing the Right Endpoint
There are two endpoints. Both return the same underlying metrics — they differ in how flexible the request is and how the response is shaped.
| Feature | export/v2 |
data/reports |
|---|---|---|
| Best for | Simple time-series exports | Compare periods, multi-report calls |
| Compare period | Not supported | Supported |
| Per-channel ad spend breakdown | Omitted | Included |
| Timestamp-type metrics | Omitted | Included |
| Multiple reports per call | One aggregation only | Many independent reports |
| Response keys | Human-readable labels | Enum names |
metrics field |
Optional — empty returns all | Required |
| Response shape | Flat array of {timestamp, metrics} |
Structured reports with full value objects |
Use export/v2 for a clean snapshot of one shop or a group of shops over a single date range. Reach for data/reports when you need to compare two periods, break out spend by channel, or fetch several differently-configured reports in one round trip.
Authentication
Both endpoints use the same header-based authentication. Send your key in X-ProfitMetrics-Action-KEY on every request.
| Header | Value |
|---|---|
X-ProfitMetrics-Action-KEY |
Your API key |
Content-Type |
application/json |
The key must grant the METRICS_READ scope and must be authorised for every CSID listed in the request body. If any CSID is not accessible, the entire request is rejected.
If a request includes any CSID your key is not authorised for, the entire call is rejected with NO_ACCESS_TO_SITES. Confirm site access before adding new CSIDs to an existing integration.
Endpoint 1 — The Export Endpoint
Use this endpoint when you want a single, flat time series across one or more sites. It is the simplest option and the right default for most exports.
URL
POST https://api.my.profitmetrics.io/api/key-auth/dashboard-metrics/export/v2
During testing, use https://api.my.profitmetrics.io. For production, your account manager will confirm the host.
Request body fields
| Field | Required | Description |
|---|---|---|
csids |
Yes | Array of Customer Site IDs. Must contain at least one. |
currency |
Conditional | ISO 4217 code (e.g. EUR, USD, DKK). Required when csids has more than one entry; otherwise defaults to the site's own currency. Must be a currency supported by ProfitMetrics. |
resolution |
Yes | One of HOUR, DAY, WEEK, MONTH, TOTAL. |
metrics |
No | Array of metric enum names. Empty or missing returns all available metrics. |
lookbackWindow |
No | Number of days back from today (integer ≥ 0). 0 or omitted uses the earliest first-order date on file. |
timezone |
No | IANA timezone ID used to interpret day/week/month boundaries. Defaults to Europe/Copenhagen. |
Validation rules
csidsmust not be empty.resolutionmust be one of the listed enum values.currencyis required whenevercsidscontains more than one site.lookbackWindowmust be ≥ 0 when provided.metricsvalues must belong to the Metrics catalogue. Unknown names fail validation.
Minimal example
{
"csids": [10000394],
"resolution": "DAY",
"currency": "EUR",
"lookbackWindow": 30,
"metrics": ["TURNOVER", "GROSS_PROFIT", "TOTAL_ADSPEND"]
}
Multi-site example
{
"csids": [10000394, 10000816],
"currency": "EUR",
"resolution": "MONTH",
"lookbackWindow": 365,
"timezone": "Europe/Copenhagen",
"metrics": [
"NUMBER_OF_ORDERS",
"TURNOVER",
"GROSS_PROFIT",
"TOTAL_ADSPEND",
"BLENDED_ROAS",
"BLENDED_POAS"
]
}
"Everything since the beginning" example
Omit lookbackWindow and metrics to get every metric for the full lifetime of the shop, aggregated into a single bucket.
{
"csids": [10000394],
"resolution": "TOTAL",
"currency": "EUR"
}
Response
The response is a chronological array of buckets under data.data. Each bucket contains a timestamp and a metrics object keyed by the human-readable label (not the enum name you sent).
{
"success": true,
"data": {
"data": [
{
"timestamp": "2025-03-06",
"metrics": {
"Revenue": 12450.25,
"Gross profit": 4210.10,
"Total adspend": 980.00
}
},
{
"timestamp": "2025-03-07",
"metrics": {
"Revenue": 13120.00,
"Gross profit": 4512.70,
"Total adspend": 1025.40
}
}
]
}
}
Response field reference
| Field | Description |
|---|---|
success |
Boolean. true on 2xx responses. |
data.data |
Array, one element per time bucket, in chronological order. |
timestamp |
For HOUR: ISO-8601 local date-time (e.g. "2025-03-06T11:00"). For DAY, WEEK, MONTH, TOTAL: ISO-8601 date (e.g. "2025-03-06"). For WEEK and MONTH, the timestamp is the first day of the bucket. For TOTAL, it is the first timestamp of the period. |
metrics |
Object keyed by the human-readable label (e.g. "Gross profit"). Value is a number, or the string "N/A" when the metric cannot be computed (typically because required settings are missing). |
Response keys are labels, not the enum names you sent. See the Metrics catalogue for the mapping. Non-numeric metric types — timestamps and per-channel ad spend breakdowns — are filtered out of this endpoint entirely. Use the Reports endpoint if you need those.
Endpoint 2 — The Reports Endpoint
Use this endpoint when export/v2 isn't expressive enough. It accepts a list of independently configured reports and supports a comparison period, per-site breakdowns, and metric types the export endpoint omits (such as per-channel ad spend breakdowns and timestamp metrics).
URL
POST https://api.my.profitmetrics.io/api/key-auth/dashboard-metrics/data/reports
Top-level request body
| Field | Required | Description |
|---|---|---|
reports |
Conditional | Array of report definitions. At least one of reports or chartReports must be present. |
chartReports |
No | Chart-format reports. Not covered in this document. |
calculateWithNotConfiguredMarketingChannels |
No | Defaults to false. When false, metrics that depend on Marketing Channel configuration return N/A if any required channel action is missing. When true, partial calculation is allowed (missing channels are treated as zero). |
Per-report definition
| Field | Required | Description |
|---|---|---|
id |
Yes | Identifier for this report. Must be unique within the request. The same value is echoed back in the response so you can match results. |
sites |
Yes | Array of Customer Site IDs to aggregate. One or more. |
currency |
Yes | ISO 4217 currency code. All monetary values are converted to this currency. |
period |
Yes | Main date range (see below). |
metrics |
Yes | Array of metric enum names. Cannot be empty (unlike export/v2). |
resolution |
Yes | One of HOUR, DAY, WEEK, MONTH, TOTAL. |
comparePeriod |
No | Second date range. When provided, each data point includes compareValue, valueDiff, and percentageDiff. |
timezone |
No | IANA timezone ID. Defaults to Europe/Copenhagen. |
exchangeType |
No | Exchange rate strategy. Only CURRENT is supported. |
allowPartialMarketingChannels |
No | Per-report refinement. Requires calculateWithNotConfiguredMarketingChannels = true on the outer request. When true, Marketing Channel metrics allow partial calculation for channels that have actions configured. |
Period object
| Field | Description |
|---|---|
fromIncl |
ISO-8601 local date-time. Start of the range, inclusive. Example: "2025-01-01T00:00:00". |
toExcl |
ISO-8601 local date-time. End of the range, exclusive. Example: "2025-02-01T00:00:00". |
Minimal example — single report, no compare
{
"reports": [
{
"id": "monthly-summary",
"sites": [10000394],
"currency": "EUR",
"resolution": "MONTH",
"period": {
"fromIncl": "2025-01-01T00:00:00",
"toExcl": "2025-04-01T00:00:00"
},
"metrics": ["TURNOVER", "GROSS_PROFIT", "TOTAL_ADSPEND", "BLENDED_ROAS"]
}
]
}
Compare period example — multiple sites
{
"reports": [
{
"id": "this-month",
"sites": [10000394, 10000816],
"currency": "EUR",
"resolution": "TOTAL",
"timezone": "Europe/Copenhagen",
"period": {
"fromIncl": "2025-03-01T00:00:00",
"toExcl": "2025-04-01T00:00:00"
},
"comparePeriod": {
"fromIncl": "2025-02-01T00:00:00",
"toExcl": "2025-03-01T00:00:00"
},
"metrics": [
"NUMBER_OF_ORDERS",
"TURNOVER",
"GROSS_PROFIT",
"TOTAL_ADSPEND",
"BLENDED_ROAS",
"BLENDED_POAS",
"NEW_CUSTOMERS",
"N_CAC"
]
}
],
"calculateWithNotConfiguredMarketingChannels": true
}
Multiple independent reports in one call
{
"reports": [
{
"id": "google-daily",
"sites": [10000394],
"currency": "EUR",
"resolution": "DAY",
"period": {"fromIncl": "2025-03-01T00:00:00", "toExcl": "2025-04-01T00:00:00"},
"metrics": ["GOOGLE_ADSPEND", "GOOGLE_IMPRESSIONS", "GOOGLE_CLICKS", "GOOGLE_ROAS", "GOOGLE_POAS"]
},
{
"id": "meta-daily",
"sites": [10000394],
"currency": "EUR",
"resolution": "DAY",
"period": {"fromIncl": "2025-03-01T00:00:00", "toExcl": "2025-04-01T00:00:00"},
"metrics": ["META_ADSPEND", "META_IMPRESSIONS", "META_CLICKS", "META_ROAS", "META_POAS"]
}
]
}
Response
Each requested report is returned under data.reports, identified by the id you supplied. Inside, metrics is an array of time buckets, and the data object inside each bucket is keyed by the metric enum name (not the human-readable label).
{
"success": true,
"data": {
"reports": [
{
"id": "monthly-summary",
"metrics": [
{
"timestamp": "2025-01-01T00:00:00",
"compareTimestamp": null,
"data": {
"TURNOVER": {
"value": {
"value": 48320.50,
"compareValue": null,
"valueDiff": null,
"percentageDiff": null
}
},
"GROSS_PROFIT": {
"value": {
"value": 16200.00,
"compareValue": null,
"valueDiff": null,
"percentageDiff": null
}
},
"BLENDED_ROAS": {
"value": {
"value": 4.35,
"compareValue": null,
"valueDiff": null,
"percentageDiff": null
}
}
}
}
]
}
],
"chartReports": []
}
}
When a comparePeriod is supplied, the numeric fields are populated:
"TURNOVER": {
"value": {
"value": 48320.50,
"compareValue": 43100.00,
"valueDiff": 5220.50,
"percentageDiff": 12.11
}
}
Response field reference
| Field | Description |
|---|---|
success |
Boolean. true on success. |
data.reports |
Array, one element per report definition sent. |
id |
Matches the id you sent in the request. |
metrics |
Array, one element per time bucket, in chronological order. |
timestamp |
ISO-8601 datetime. Start of the bucket in the requested timezone. |
compareTimestamp |
ISO-8601 datetime or null. Start of the corresponding comparison bucket. null when no comparePeriod was given. |
data |
Object. Map of metric enum name → value object. Only requested metrics appear. |
Value object shapes
Each metric's value is wrapped in an object whose shape depends on the metric type.
Numeric with compare — most metrics:
{
"value": {
"value": 48320.50,
"compareValue": 43100.00,
"valueDiff": 5220.50,
"percentageDiff": 12.11
}
}
compareValue, valueDiff, and percentageDiff are null when no comparePeriod was specified.
Not available — required configuration is missing:
{"value": "N/A"}
Returned when the metric cannot be computed (e.g. a required channel is not configured and calculateWithNotConfiguredMarketingChannels is false).
Per-channel ad spend — only used by ADSPEND_BY_CHANNEL:
{
"value": {
"Google": {"value": 980.0, "compareValue": 870.0, "valueDiff": 110.0, "percentageDiff": 12.64},
"Meta": {"value": 540.0, "compareValue": 500.0, "valueDiff": 40.0, "percentageDiff": 8.0}
}
}
Timestamp — used by GOOGLE_ADSPEND_TIMESTAMP:
{"value": "2025-03-01T01:00:00"}
Resolutions and Time Buckets
The resolution field controls how data is aggregated into buckets. Boundaries are computed in the timezone you supply.
| Resolution | One bucket per |
|---|---|
HOUR |
Hour |
DAY |
Day (00:00 local) |
WEEK |
Week (timestamp is the first day of the bucket) |
MONTH |
Month (timestamp is the first day of the bucket) |
TOTAL |
The entire period — one bucket only |
Period boundaries are right-exclusive: fromIncl is included, toExcl is excluded. To export the full month of March, use 2025-03-01T00:00:00 through 2025-04-01T00:00:00.
Behavioural Details
Both endpoints share the same underlying behaviour around time, currency, and request handling. Knowing these details up front prevents surprises.
Period selection (export/v2)
lookbackWindow = N(N > 0) — from today minus N days (at 00:00 in the configured timezone) through now.lookbackWindow = 0or omitted — from the earliest first-order timestamp across the provided CSIDs, through now. If no orders exist at all, the period collapses to "today 00:00 → now" and you receive an emptydataarray.
Timezone
Day, week, and month boundaries are computed in the supplied IANA timezone. Defaults to Europe/Copenhagen. The timestamp strings in the response are also expressed in that zone.
Currency conversion
Currency conversion uses current exchange rates — the same rates the dashboard uses — for all historic data. The Reports endpoint exposes this explicitly as exchangeType: "CURRENT", which is the only supported value.
Multiple sites in one report
Data is aggregated across all provided sites. Monetary values are converted to the requested currency before aggregation.
Missing metric values
If a metric requires configuration that isn't set up for the site (for example, a channel's cost settings), its value is the string "N/A" for that bucket. On export/v2, non-numeric and non-N/A metric types (timestamps, per-channel breakdowns) are filtered out of the response entirely.
Concurrency and timeouts
Requests are subject to per-API-key and global concurrency limits. If the server is busy, you receive HTTP 599 with TIMEOUT. Back off and retry with exponential delay.
Marketing Channel Calculation
Metrics like BLENDED_ROAS and TOTAL_ADSPEND depend on every connected Marketing Channel being fully configured. By default, if any channel is missing required setup, these metrics return "N/A".
The Reports endpoint exposes two flags to control this behaviour.
| Flag | Effect |
|---|---|
calculateWithNotConfiguredMarketingChannels |
Outer-request flag. false (default) returns N/A when any channel is missing. true calculates using only the channels that are configured; missing channels contribute zero. |
allowPartialMarketingChannels |
Per-report flag. Requires the outer flag to be true. When true, allows partial calculation for individual channels that have actions configured. |
Partial calculation makes results look complete even when channels are missing. If you enable it, communicate clearly to dashboard users that the figures may understate true ad spend until every channel is configured.
Discovering Available Metrics
The full list of metric enum names and their display labels is available from a third endpoint. Use it to populate dropdowns, validate user input, or keep your integration in sync as new metrics are added.
GET https://api.my.profitmetrics.io/api/key-auth/dashboard-metrics/export/metrics
The response is a list of {value, label} pairs, where value is the enum name you send in requests and label is the human-readable name shown in the dashboard. This endpoint is always authoritative — the catalogue below is current at the time of writing but may evolve.
Metrics Catalogue
Send the enum name in the metrics request array. On export/v2 the response is keyed by the human-readable label; on data/reports the response is keyed by the enum name itself.
Order metrics
| Enum | Display label |
|---|---|
NUMBER_OF_ORDERS |
Orders |
TURNOVER |
Revenue |
TURNOVER_WITH_VAT |
Revenue with VAT |
TURNOVER_AVG |
Avg order Revenue |
REVENUE_WITHOUT_SHIPPING_REVENUE |
Revenue after discounts |
GROSS_PROFIT |
Gross profit |
GROSS_PROFIT_RATIO |
Gross profit margin |
GROSS_PROFIT_AVG |
Avg order Gross profit |
SHIPPING_REVENUE_TOTAL |
Shipping revenue |
SHIPPING_FEE_COST_TOTAL |
Shipping cost |
SHIPPING_FEE_COST_TOTAL_AVG |
Avg order shipping cost |
PAYMENT_FEE_COST_TOTAL |
Payment cost |
PAYMENT_FEE_COST_TOTAL_AVG |
Avg order payment fee |
EXTRA_COST_TOTAL |
Packaging and handling cost |
EXTRA_COST_TOTAL_AVG |
Avg order handling cost |
EXPENSES_VARIABLE |
Variable Expenses |
EXPENSES_RECURRING |
Recurring expenses |
EXPENSES_ORDER |
Order expenses |
EXPENSES_ORDER_AVG |
Avg variable order cost |
EXPENSES_ORDER_COST_RATIO |
Order cost (%) |
EXPENSES_FIXED |
Fixed expenses |
PRODUCTS_COST_TOTAL |
Product cost |
PRODUCTS_COST_TOTAL_AVG |
Avg product cost |
CONTRIBUTION_MARGIN |
Contribution margin |
CONTRIBUTION_MARGIN_RATIO |
Contribution margin (%) |
CONTRIBUTION_MARGIN_AVG |
Avg order Contribution margin |
NET_PROFIT |
Net profit |
NET_PROFIT_RATIO |
Net profit margin |
TOTAL_ADSPEND |
Total adspend |
TOTAL_ADSPEND_RATIO |
Advertising Cost of Sales |
TOTAL_ADSPEND_AVG |
Avg order ad spend |
BLENDED_ROAS |
Blended ROAS (MER) |
BLENDED_POAS |
Blended POAS |
ADSPEND_BY_CHANNEL |
Adspend by channel (reports endpoint only — per-channel map) |
ADSPEND_MANUAL |
Ad Spend Manual |
FIRST_TIME_ORDERS |
First time orders |
FIRST_TIME_ORDERS_TURNOVER |
First orders Revenue |
FIRST_TIME_ORDERS_GROSS_PROFIT |
First orders Gross Profit |
FIRST_TIME_ORDERS_TURNOVER_AVG |
Avg. First Order Revenue |
FIRST_TIME_ORDERS_GROSS_PROFIT_AVG |
Avg. First Order Gross Profit |
RECURRING_ORDERS |
Returning orders |
RECURRING_ORDERS_TURNOVER |
Returning orders Revenue |
RECURRING_ORDERS_GROSS_PROFIT |
Returning orders Gross Profit |
RECURRING_ORDERS_TURNOVER_AVG |
Avg. Returning Order Revenue |
RECURRING_ORDERS_GROSS_PROFIT_AVG |
Avg. Returning Order Gross Profit |
FIRST_ORDERS_POAS |
First Order POAS |
FIRST_ORDERS_ROAS |
First Order ROAS |
FIRST_ORDERS_PROFIT_OVER_N_CAC |
First Order Gross Profit / nCAC |
FIRST_ORDERS_TURNOVER_OVER_N_CAC |
First Order Revenue / nCAC |
N_CAC |
nCAC |
CLV_PROFIT_OVER_N_CAC |
Gross Profit LTV / nCAC |
CLV_TURNOVER_OVER_N_CAC |
Revenue LTV / nCAC |
Customer metrics
| Enum | Display label |
|---|---|
UNIQUE_CUSTOMERS |
Total customers |
NEW_CUSTOMERS |
New customers |
NEW_CUSTOMERS_TURNOVER |
New customers Revenue |
NEW_CUSTOMERS_GROSS_PROFIT |
New customers Gross Profit |
NEW_CUSTOMERS_TURNOVER_AVG |
Avg. New Customer Revenue |
NEW_CUSTOMERS_GROSS_PROFIT_AVG |
Avg. New Customer Gross Profit |
NEW_CUSTOMERS_POAS |
New Customer POAS |
NEW_CUSTOMERS_ROAS |
New Customer ROAS |
RETURNING_CUSTOMERS |
Returning customers |
RETURNING_CUSTOMERS_TURNOVER |
Returning customers Revenue |
RETURNING_CUSTOMERS_GROSS_PROFIT |
Returning customers Gross Profit |
RETURNING_CUSTOMERS_TURNOVER_AVG |
Avg. Returning Customer Revenue |
RETURNING_CUSTOMERS_GROSS_PROFIT_AVG |
Avg. Returning Customer Gross Profit |
Ad spend — blended
| Enum | Display label |
|---|---|
ADSPEND_GOOGLE |
Ad Spend Google |
ADSPEND_META |
Ad Spend Meta |
ADSPEND_BING |
Ad Spend Bing |
ADSPEND_PARTNERADS |
Ad Spend Partner Ads |
ADSPEND_TIKTOK |
Ad Spend TikTok |
ADSPEND_SNAPCHAT |
Ad Spend Snapchat |
ADSPEND_WEBGAINS |
Ad Spend Webgains |
ADSPEND_PINTEREST |
Ad Spend Pinterest |
ADSPEND_OTHER |
Ad Spend Other |
ADSPEND_PRICERUNNER |
Ad Spend PriceRunner |
Ad spend — in-platform (Google)
| Enum | Display label |
|---|---|
GOOGLE_ADSPEND |
Google Ads Ad spend (in-platform) |
GOOGLE_IMPRESSIONS |
Google Ads Impressions (in-platform) |
GOOGLE_CLICKS |
Google Ads Clicks (in-platform) |
GOOGLE_CONVERSIONS |
Google Ads Conversions (in-platform) |
GOOGLE_REVENUE |
Google Ads Revenue (in-platform) |
GOOGLE_GROSS_PROFIT |
Google Ads Gross Profit (in-platform) |
GOOGLE_PROFIT_AFTER_ADSPEND |
Google Ads Profit after ad spend (in-platform) |
GOOGLE_CPA |
Google Ads CPA (in-platform) |
GOOGLE_ROAS |
Google Ads ROAS (in-platform) |
GOOGLE_POAS |
Google Ads POAS (in-platform) |
GOOGLE_ADSPEND_TIMESTAMP |
Google Ads Ad spend timestamp (reports endpoint only — timestamp type) |
GOOGLE_PROFIT_AFTER_ADSPEND_ORDER_BASED |
Google ads Profit after ad spend (orders with click based) |
GOOGLE_ROAS_ORDER_BASED |
Google Ads ROAS (orders with click based) |
GOOGLE_ROAS_WITH_VAT_ORDER_BASED |
Google Ads ROAS (vat included, orders with click based) |
GOOGLE_POAS_ORDER_BASED |
Google Ads POAS (orders with click based) |
GOOGLE_NUMBER_OF_ORDERS_WITH_CLICK |
Orders with Google Click |
GOOGLE_TURNOVER_FROM_ORDERS_WITH_CLICK |
Revenue from orders with Google Click |
GOOGLE_TURNOVER_WITH_VAT_FROM_ORDERS_WITH_CLICK |
Revenue with VAT from orders with Google Click |
GOOGLE_GROSS_PROFIT_FROM_ORDERS_WITH_CLICK |
Gross profit from orders with Google Click |
GOOGLE_DIFFERENCE_MODELLED_VS_ORDERS_WITH_CLICK |
% Difference: Google Modelled vs Click ID Orders |
GOOGLE_META_NUMBER_OF_ORDERS_WITH_BOTH_CLICKS |
Orders with Google and Meta Click |
Ad spend — in-platform (Meta)
| Enum | Display label |
|---|---|
META_ADSPEND |
Meta Ad spend (in-platform) |
META_IMPRESSIONS |
Meta Impressions (in-platform) |
META_CLICKS |
Meta Clicks (in-platform) |
META_REVENUE |
Meta Revenue (in-platform) |
META_GROSS_PROFIT |
Meta Gross Profit (in-platform) |
META_PROFIT_AFTER_ADSPEND |
Meta Profit after ad spend (in-platform) |
META_CPA |
Meta CPA (in-platform) |
META_ROAS |
Meta ROAS (in-platform) |
META_POAS |
Meta POAS (in-platform) |
META_NUMBER_OF_ORDERS_WITH_CLICK |
Orders with Meta Click |
Ad spend — in-platform (other channels)
| Enum | Display label |
|---|---|
PINTEREST_ADSPEND |
Pinterest Ad spend (in-platform) |
TIKTOK_ADSPEND |
TikTok Ad spend (in-platform) |
BING_ADSPEND |
Microsoft Ads Ad spend (in-platform) |
PARTNERADS_ADSPEND |
Partner Ads Ad spend (in-platform) |
SNAPCHAT_ADSPEND |
Snapchat Ad spend (in-platform) |
WEBGAINS_ADSPEND |
Webgains Ad spend (in-platform) |
PRICERUNNER_ADSPEND |
PriceRunner Ad spend (in-platform) |
ADTRACTION_ADSPEND |
Adtraction Ad spend (in-platform) |
DAISYCON_ADSPEND |
Daisycon Ad spend (in-platform) |
Returns — base counts and amounts (order time)
| Enum | Display label |
|---|---|
NUMBER_OF_RETURNS_ORDER_TIME |
Number of returns (order time) |
NUMBER_OF_RETURNED_PRODUCTS_ORDER_TIME |
Number of returned products (order time) |
RETURNED_REVENUE_EX_VAT_ORDER_TIME |
Returned Revenue (order time) |
RETURNED_REVENUE_INC_VAT_ORDER_TIME |
Returned Revenue with VAT (order time) |
RETURNED_COST_ORDER_TIME |
Returned Cost (order time) |
RETURNED_PAYMENT_COST_ORDER_TIME |
Returned Payment Cost (order time) |
RETURNED_EXTRA_COST_ORDER_TIME |
Returned Extra Cost ex VAT (order time) |
RETURNED_SHIPPING_COST_ORDER_TIME |
Returned Shipping Cost ex VAT (order time) |
RETURNED_COST_TOTAL_ORDER_TIME |
Returned Cost Total (order time) |
RETURN_EXTRA_COST_ORDER_TIME |
Return Extra Cost (order time) |
RETURN_EXTRA_SHIPPING_COST_ORDER_TIME |
Return Extra Shipping Cost (order time) |
RETURN_EXTRA_PAYMENT_COST_ORDER_TIME |
Return Extra Payment Cost (order time) |
NUMBER_OF_FIRST_ORDERS_RETURNS_ORDER_TIME |
Number of first orders returns (order time) |
NUMBER_OF_FIRST_ORDERS_RETURNED_PRODUCTS_ORDER_TIME |
Number of first orders returned products (order time) |
FIRST_ORDERS_RETURNED_REVENUE_EX_VAT_ORDER_TIME |
First Order Returned Revenue (order time) |
FIRST_ORDERS_RETURNED_REVENUE_INC_VAT_ORDER_TIME |
First Order Returned Revenue with VAT (order time) |
FIRST_ORDERS_RETURNED_COST_ORDER_TIME |
First Order Returned Cost (order time) |
FIRST_ORDERS_RETURNED_PAYMENT_COST_ORDER_TIME |
First Order Returned Payment Cost (order time) |
FIRST_ORDERS_RETURNED_EXTRA_COST_ORDER_TIME |
First Order Returned Extra Cost ex VAT (order time) |
FIRST_ORDERS_RETURNED_SHIPPING_COST_ORDER_TIME |
First Order Returned Shipping Cost ex VAT (order time) |
FIRST_ORDERS_RETURNED_COST_TOTAL_ORDER_TIME |
First Order Returned Cost Total (order time) |
FIRST_ORDERS_RETURN_EXTRA_COST_ORDER_TIME |
First Order Return Extra Cost (order time) |
FIRST_ORDERS_RETURN_EXTRA_SHIPPING_COST_ORDER_TIME |
First Order Return Extra Shipping Cost (order time) |
FIRST_ORDERS_RETURN_EXTRA_PAYMENT_COST_ORDER_TIME |
First Order Return Extra Payment Cost (order time) |
NUMBER_OF_RECURRING_ORDERS_RETURNS_ORDER_TIME |
Number of recurring orders returns (order time) |
NUMBER_OF_RECURRING_ORDERS_RETURNED_PRODUCTS_ORDER_TIME |
Number of recurring orders returned products (order time) |
RECURRING_ORDERS_RETURNED_REVENUE_EX_VAT_ORDER_TIME |
Recurring Order Returned Revenue (order time) |
RECURRING_ORDERS_RETURNED_REVENUE_INC_VAT_ORDER_TIME |
Recurring Order Returned Revenue with VAT (order time) |
RECURRING_ORDERS_RETURNED_COST_ORDER_TIME |
Recurring Order Returned Cost (order time) |
RECURRING_ORDERS_RETURNED_PAYMENT_COST_ORDER_TIME |
Recurring Order Returned Payment Cost (order time) |
RECURRING_ORDERS_RETURNED_EXTRA_COST_ORDER_TIME |
Recurring Order Returned Extra Cost ex VAT (order time) |
RECURRING_ORDERS_RETURNED_SHIPPING_COST_ORDER_TIME |
Recurring Order Returned Shipping Cost ex VAT (order time) |
RECURRING_ORDERS_RETURNED_COST_TOTAL_ORDER_TIME |
Recurring Order Returned Cost Total (order time) |
RECURRING_ORDERS_RETURN_EXTRA_COST_ORDER_TIME |
Recurring Order Return Extra Cost (order time) |
RECURRING_ORDERS_RETURN_EXTRA_SHIPPING_COST_ORDER_TIME |
Recurring Order Return Extra Shipping Cost (order time) |
RECURRING_ORDERS_RETURN_EXTRA_PAYMENT_COST_ORDER_TIME |
Recurring Order Return Extra Payment Cost (order time) |
Code Examples
Working examples in cURL, Python, and JavaScript for both endpoints. All examples assume your API key is in the PROFITMETRICS_API_KEY environment variable.
cURL — export/v2
curl -X POST "https://api.my.profitmetrics.io/api/key-auth/dashboard-metrics/export/v2" \
-H "X-ProfitMetrics-Action-KEY: $PROFITMETRICS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"csids": [10000394],
"currency": "EUR",
"resolution": "DAY",
"lookbackWindow": 30,
"metrics": ["TURNOVER", "GROSS_PROFIT", "TOTAL_ADSPEND", "BLENDED_ROAS"]
}'
Python — export/v2
import os, requests
resp = requests.post(
"https://api.my.profitmetrics.io/api/key-auth/dashboard-metrics/export/v2",
headers={
"X-ProfitMetrics-Action-KEY": os.environ["PROFITMETRICS_API_KEY"],
"Content-Type": "application/json",
},
json={
"csids": [10000394, 10000816],
"currency": "EUR",
"resolution": "MONTH",
"lookbackWindow": 365,
"metrics": [
"NUMBER_OF_ORDERS",
"TURNOVER",
"GROSS_PROFIT",
"BLENDED_ROAS",
"BLENDED_POAS",
],
},
timeout=60,
)
resp.raise_for_status()
buckets = resp.json()["data"]["data"]
for b in buckets:
print(b["timestamp"], b["metrics"])
JavaScript — export/v2
const res = await fetch(
"https://api.my.profitmetrics.io/api/key-auth/dashboard-metrics/export/v2",
{
method: "POST",
headers: {
"X-ProfitMetrics-Action-KEY": process.env.PROFITMETRICS_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
csids: [10000394],
currency: "EUR",
resolution: "DAY",
lookbackWindow: 7,
metrics: ["TURNOVER", "GROSS_PROFIT"],
}),
},
);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const { data } = await res.json();
console.log(data.data);
cURL — data/reports
curl -X POST "https://api.my.profitmetrics.io/api/key-auth/dashboard-metrics/data/reports" \
-H "X-ProfitMetrics-Action-KEY: $PROFITMETRICS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"reports": [{
"id": "march-summary",
"sites": [10000394],
"currency": "EUR",
"resolution": "TOTAL",
"period": {"fromIncl": "2025-03-01T00:00:00", "toExcl": "2025-04-01T00:00:00"},
"comparePeriod": {"fromIncl": "2025-02-01T00:00:00", "toExcl": "2025-03-01T00:00:00"},
"metrics": ["TURNOVER", "GROSS_PROFIT", "TOTAL_ADSPEND", "BLENDED_ROAS", "NEW_CUSTOMERS"]
}],
"calculateWithNotConfiguredMarketingChannels": true
}'
Python — data/reports
import os, requests
resp = requests.post(
"https://api.my.profitmetrics.io/api/key-auth/dashboard-metrics/data/reports",
headers={
"X-ProfitMetrics-Action-KEY": os.environ["PROFITMETRICS_API_KEY"],
"Content-Type": "application/json",
},
json={
"reports": [
{
"id": "march-summary",
"sites": [10000394],
"currency": "EUR",
"resolution": "TOTAL",
"period": {
"fromIncl": "2025-03-01T00:00:00",
"toExcl": "2025-04-01T00:00:00",
},
"comparePeriod": {
"fromIncl": "2025-02-01T00:00:00",
"toExcl": "2025-03-01T00:00:00",
},
"metrics": ["TURNOVER", "GROSS_PROFIT", "TOTAL_ADSPEND", "BLENDED_ROAS"],
}
],
"calculateWithNotConfiguredMarketingChannels": True,
},
timeout=60,
)
resp.raise_for_status()
for report in resp.json()["data"]["reports"]:
print(f"Report: {report['id']}")
for bucket in report["metrics"]:
print(f" {bucket['timestamp']}")
for metric, val in bucket["data"].items():
v = val["value"]
if isinstance(v, dict):
print(f" {metric}: {v['value']} (vs {v['compareValue']})")
else:
print(f" {metric}: {v}")
JavaScript — data/reports
const res = await fetch(
"https://api.my.profitmetrics.io/api/key-auth/dashboard-metrics/data/reports",
{
method: "POST",
headers: {
"X-ProfitMetrics-Action-KEY": process.env.PROFITMETRICS_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
reports: [
{
id: "march-summary",
sites: [10000394],
currency: "EUR",
resolution: "TOTAL",
period: { fromIncl: "2025-03-01T00:00:00", toExcl: "2025-04-01T00:00:00" },
metrics: ["TURNOVER", "GROSS_PROFIT", "BLENDED_ROAS"],
},
],
calculateWithNotConfiguredMarketingChannels: true,
}),
},
);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const { data } = await res.json();
for (const report of data.reports) {
for (const bucket of report.metrics) {
console.log(bucket.timestamp, bucket.data);
}
}
Related Endpoints
| Endpoint | Purpose |
|---|---|
GET /api/key-auth/dashboard-metrics/export/metrics |
Returns the live list of every available metric as {value, label} pairs. Use it to populate dropdowns or validate input. |
POST /api/key-auth/dashboard-metrics/export/v2 |
The Export endpoint covered in this article. |
POST /api/key-auth/dashboard-metrics/data/reports |
The Reports endpoint covered in this article. |
POST /api/key-auth/dashboard-metrics/export/csv |
Deprecated. CSV export for a single site. Use export/v2 and convert to CSV client-side. |
Troubleshooting
All error responses share the same envelope: success: false, an errorCode, and an optional errorDetails object with structured context (typically null except where noted).
export/v2 error codes
| HTTP | Error code | Meaning |
|---|---|---|
| 400 | CUSTOMER_SITE_NOT_FOUND |
A CSID in the request is unknown or the API key cannot access it. |
| 400 | Validation error | Body failed validation: missing required field, bad enum value, negative lookbackWindow, unsupported currency, or currency omitted with multiple CSIDs. |
| 401 / 403 | — | Missing or invalid API key, or the key lacks METRICS_READ. |
| 403 | INVALID_AUTHENTICATION_TYPE |
The request was not made with an API Key credential. |
| 500 | DB_ERROR |
Database error while computing the export. Retryable. |
| 500 | UNKNOWN |
Unhandled server error. Retryable; contact support if it persists. |
| 599 | TIMEOUT |
Server is busy processing other requests. Wait briefly and retry. |
data/reports error codes
| HTTP | Error code | Meaning |
|---|---|---|
| 400 | NO_REQUESTED_REPORTS |
Both reports and chartReports are absent or null. |
| 400 | MISSING_SETTING_FOR_SELECTED_METRIC |
One or more metrics require configuration that is missing. errorDetails maps each metric enum name to the list of affected CSIDs. |
| 403 | NO_ACCESS_TO_SITES |
The API key is not authorised for one or more requested CSIDs. |
| 403 | INVALID_AUTHENTICATION_TYPE |
The request was not made with an API Key credential. |
| 500 | FAILED_TO_PROCESS_REPORT |
Report processing failed internally. Retryable. |
| 500 | UNKNOWN |
Unhandled server error. Contact support if it persists. |
| 599 | TIMEOUT |
Server is busy. Wait a moment and retry. |
Example error response with errorDetails
{
"success": false,
"errorCode": "MISSING_SETTING_FOR_SELECTED_METRIC",
"errorDetails": {"GOOGLE_GROSS_PROFIT": [10000394, 10000816]}
}
If something looks off, include your request body, the full response, and the approximate UTC timestamp of the call when you reach out to support@profitmetrics.io.