Margin

Get cost and revenue, bucketed by period and optionally grouped by customer, alongside the resulting margin and risk status.

Margin is computed on revenue-linked projects (the default project type). On an internal project (tracked by key metrics, not revenue), this route returns a 400: use Get performance instead.

import weflayr

client = weflayr.client(api_key="wf-...")
const weflayr = require('weflayr');

const client = weflayr.client({ apiKey: 'wf-...' });
# Passed as a Bearer token on every request
export WEFLAYR_API_KEY="wf-..."

Get margin

from weflayr.openapi.models import MarginInput

client.get_margin(body=MarginInput.from_dict({
    "date_from": "2026-06-01",
    "aggregate": "week",
    "group_by": "customer",
    "customers": ["c_123", "c_456"],
}))
await weflayr.api.getMargin({
  client,
  throwOnError: true,
  body: {
    dateFrom: '2026-06-01',
    aggregate: 'week',
    groupBy: 'customer',
    customers: ['c_123', 'c_456'],
  },
});
curl -X POST https://app.weflayr.com/api/margin/ \
  -H "Authorization: Bearer $WEFLAYR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "date_from": "2026-06-01",
    "aggregate": "week",
    "group_by": "customer",
    "customers": ["c_123", "c_456"]
  }'

Output:

{
  "rows": [
    {"date_from": "2026-06-01", "date_to": "2026-06-07", "customer": "c_123", "revenue": 1200.5, "cost": 420.0, "margin": 780.5, "margin_pct": 65.02, "risk_status": "healthy"},
    {"date_from": "2026-06-01", "date_to": "2026-06-07", "customer": "c_456", "revenue": 800.0, "cost": 950.0, "margin": -150.0, "margin_pct": -18.75, "risk_status": "unprofitable"}
  ],
  "next_cursor": null,
  "has_more": false
}

customer is omitted when group_by isn’t set.

Input params: passed in the request body.

Field Accepts Behaviour
date_from
Required
"YYYY-MM-DD" Start of the period, inclusive.
date_to
Optional
"YYYY-MM-DD" End of the period, inclusive. Defaults to today.
aggregate
Optional
"day" | "week" | "month" | "quarter" | "year" | "all" One row per period; "all" collapses the whole date range into a single row (per group_by, if set). Defaults to "day".
group_by
Optional
"customer" Split each period into one row per customer. Omit for one row per period.
customers
Optional
list[string] Restrict to these customers. Omit for every customer’s. See Get customers.
filter_customers_based_on_features
Optional
list[string] Restrict to customers who used any of these feature tags in the period (i.e. if a customer did not use the feature, all its rows are removed)
apply_credits
Optional
boolean Apply free AI credits discounts to cost. Defaults to false.
limit
Optional
integer Max number of rows to fetch. Defaults to 100, max 1000.
cursor
Optional
string The route is paginated: pass the previous page’s next_cursor to fetch the next page. PS: has_more from the output says whether another page exists.