Skip to content
  • There are no suggestions because the search field is empty.

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

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. EURUSDDKK). 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 HOURDAYWEEKMONTHTOTAL.
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

  • csids must not be empty.
  • resolution must be one of the listed enum values.
  • currency is required whenever csids contains more than one site.
  • lookbackWindow must be ≥ 0 when provided.
  • metrics values 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 DAYWEEKMONTHTOTAL: 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 HOURDAYWEEKMONTHTOTAL.
comparePeriod No Second date range. When provided, each data point includes compareValuevalueDiff, 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
}
}

compareValuevalueDiff, 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 = 0 or 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 empty data array.

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.