Margin Data API

Get margin trend

Returns time-series margin data (revenue - cost) with adaptive granularity: - <= 30 days: daily - 31-90 days: weekly - > 90 days: monthly Periods with no revenue and no cost activity are omitted from data_points rather than returned as zero values. Call it with a GET request to /margin-data/trend, authenticated with a restricted API key and the "revenue:read" scope.

Returns time-series margin data (revenue - cost) with adaptive granularity: - <= 30 days: daily - 31-90 days: weekly - > 90 days: monthly Periods with no revenue and no cost activity are omitted from data_points rather than returned as zero values. Zero-fill client-side if you need a continuous series. Margin requires revenue data from your connected Stripe account; connect it in your dashboard under Settings then Integrations. Note that a not-yet-connected account and a genuine zero-revenue period both return "0", so verify the connection before interpreting zeros. If no revenue has been synced for a period, its revenue field returns "0" and margin_percent is null (division by zero is undefined). Revenue is recognized on an accrual basis: each revenue record's amount is attributed across its billing period. Costs are attributed to the time the usage event occurred. Requests count toward your per-API-key rate limit; sustained overruns return 429 with the standard error envelope.

Authentication and scopes

Authenticate with a restricted API key in the Authorization: Bearer <key> header. This endpoint requires the revenue:read scope.

Parameters

NameInTypeRequiredDescription
start_datequerystringYesStart of date range (ISO 8601, inclusive).
end_datequerystringYesEnd of date range (ISO 8601, exclusive).
end_user_idquerystringNoOptional end user to filter by. Pass the end_user_id (UUID) returned by GET /margin-data/by-end-user. This is Bear Lumen's internal end-user ID, not the external ID you send on usage events.

Response fields

Fields returned in the 200 response body. Nested objects are listed under their parent. A field marked optional may be absent from the body; one marked nullable is always present but its value may be null.

FieldTypeDescription
data_pointsobject[]Time-ordered margin data points. Periods with no revenue and no cost activity are omitted rather than returned as zero values; zero-fill client-side if you need a continuous series.
datestringStart of the period bucket (ISO 8601, UTC). Buckets are days, weeks, or months depending on the response granularity.
revenuestringRevenue for this period bucket, decimal string in USD.
coststringCost for this period bucket, decimal string in USD.
margin_amountstringRevenue minus cost for this period bucket, decimal string in USD. Negative when cost exceeds revenue.
margin_percentnumber (double) nullableMargin percentage ((revenue - cost) / revenue * 100), rounded to 2 decimal places. Null when revenue for this period bucket is zero.
granularitydaily | weekly | monthlySize of each period bucket, chosen from the requested date range: `daily` for ranges of 30 days or less, `weekly` for 31 to 90 days, `monthly` for more than 90 days.

Error codes

Errors return the standard error envelope with a code, message, and a correlationId you can quote to support.

StatusWhen it happens
400Invalid query parameters. Check that start_date and end_date are valid ISO 8601 dates.
401Missing or invalid API key. Send your key as Authorization: Bearer YOUR_API_KEY.
403API key lacks the revenue:read scope. Use a key that includes the revenue:read scope.
422Date range exceeds 12 months. Narrow start_date and end_date to a span of 12 months or less.
429Rate limit exceeded. Reduce request frequency and retry after the interval indicated in the Retry-After header.

Rate limits and retries

Rate limit exceeded. Reduce request frequency and retry after the interval indicated in the Retry-After header.