Create Custom Report
POST/api/v2/custom-reports
Save a new custom report owned by you.
reports:writeGrant this scope to your token under Settings → Developer → Personal Access Tokens.
Body:
name(string, required, max 255)description(string, optional, max 1000)base_entity(string, required, max 100): entity key; the report'sdomainis derived from itdefinition(object, required): see belowvisibility(string, optional):private(default) orshared(visible to everyone in the account)
Definition fields (builder mode):
definition.version(integer, optional): schema version, default 1definition.base_entity(string, required): the entity the report is rooted on — an entitykeyfrom Get Report Builder Metadatadefinition.columns(array, required, min 1): each column hasid(string, required, unique within the report, conventionallyentity.field),kind(required,dimensionormeasure),entity(required, entity key),field(required, a dimension or measure key on that entity), and optionallabel,granularity(day,week,month,quarter,year— date dimensions only),aggregation(sum,avg,min,max,count,count_distinct),formula(max 2000, see Validate Formula Expression),format(max 50, e.g.currency,percentage,number) anddecimals(0-10)definition.filters(object, optional): filter tree{conjunction: and|or, children: [...]}; each child is{type: "condition", condition: {column, operator, value}}or{type: "group", conjunction, children}.columnisentity.fieldand must be a dimension. Operators:is,is_not,contains,does_not_contain,starts_with,ends_with,is_empty,is_not_empty,is_one_of,is_not_one_of,greater_than,greater_than_or_equal,less_than,less_than_or_equal,between(value is a 2-item array). Date filters on order dates are applied as whole days in your account's timezone.definition.sorts(array, optional):{column_id, direction: asc|desc}wherecolumn_idis a columniddefinition.limit(integer, optional, 1-5000): default row limitdefinition.display(object, optional): presentation settings stored with the report —view_type(table,chart,pivot,sql),chart_type,conditional_formatting(array of{column, type, config}),pivot_config
SQL reports: send definition as {"version": 2, "mode": "sql", "sql": "SELECT ...", "limit": 500} instead of a builder definition (sql max 20000 characters, limit 1-5000, display.view_type may only be table); base_entity is not needed (the report is stored under the sql domain with mode = sql). The statement is validated before it is saved (errors are returned as 422 on definition.sql). Creating or changing an SQL report requires the reports.sql permission (403 otherwise).
Returns 201 with the created report.
Authentication: Bearer token (Personal Access Token). Personal access tokens need the reports:write scope.
Request
Responses
- 201
- 401
- 403
- 422
- 429
Created
Response Headers
Unauthenticated — the bearer token is missing, revoked, expired, or malformed. Never retry automatically; fix the credential. See the Errors guide.
Forbidden — the token lacks a required scope, the endpoint is not available to API tokens, or the user behind the token lacks the permission. A human must adjust the token scopes or user permissions; do not retry.
Unprocessable Entity
Response Headers
Rate limited — platform limit is 1,000 requests/min; individual tokens may carry lower limits. Honor the Retry-After header before retrying. See the Rate Limits guide.