---
title: "Read what this version of the API can do"
method: POST
path: "/capabilities"
tags: ["Capabilities"]
---

# Read what this version of the API can do

`POST /capabilities`

## Request

- Base URL: `https://api.reportingninja.com/v1`
- URL: `https://api.reportingninja.com/v1/capabilities`
- Auth: HTTP bearer

Returns the ceilings, the vocabularies and the guarantees this version publishes, so a client can read them instead of hard-coding them: how many sections a report takes, which shapes a widget can have, which periods a report can be built for, how long a confirmation token lives, which endpoints confirm and which accept if_version, and whether write access is enabled for the account that is calling. Everything else in this document is fixed at publication time; this endpoint is the one that answers for today.

## Request body

- CapabilitiesRequest: No parameters.

## Response `200`

The call succeeded. This endpoint reports its errors with a real HTTP status, so a 200 always carries status=ok.

- CapabilitiesResponse
  - `status` 'ok', required
  - `data` CapabilitiesData, required: Twenty-six blocks describing what this version of the API can do, plus endpoints_note. Every one of them is answered on every call; they are documented here by what they carry rather than field by field, because the ceilings themselves are what the endpoint exists to publish and reading them from the answer is the point. The example shows every block, with the longer ones cut down to their first few fields.
    - `contract` object, required: The release this surface is at, which DSL and which composition vocabulary it speaks, whether this version adds anything to them, which keys it added and which limits have come down since the GA -- each with the day and the version that carried it -- how many problems an answer lists, and that unknown fields and characters outside the Basic Multilingual Plane are refused.
    - `widgets` object, required: The six shapes a widget can take, the rule each one imposes on its metrics and dimensions, how many of each it accepts, and which chart the two shapes that draw one can be drawn as.
    - `comparators` object, required: The comparator half of the widget DSL: the four shapes a comparator is drawn as, the three classes the DSL describes, the time axes, how many things each class compares, and the two kinds of comparator this API does not describe at all.
    - `integrations` object[], required: Every integration the DSL can build a widget for, with its data views and whether each one is covered. A data_view published as an empty string is the word of the DSL for a source with a single view: the widget sends it as an empty string too.
    - `sources_without_dsl` object[], required: The sources whose widgets cannot be expressed as a DSL, each named the way every other endpoint names an integration: their widgets can be read as not editable and cannot be created.
    - `query_not_available` object, required: The integrations whose structure is published and whose rows cannot be read through /v1/query, with the reason.
    - `date_presets` object, required: The periods a report can be built for, and the query presets that have no equivalent among them.
    - `composition` object, required: The ceilings and rules of a composition: sections per report, widgets per section and per composition, the data sources, the summary, the languages, the template parameters, the placement of a widget and what a section delete does.
    - `summary` object, required: What the AI report summary costs and where it can be placed.
    - `ai_briefs` object, required: The three levels of client brief an AI summary reads -- account, report and widget -- which two of them this API writes, and what a brief is not part of.
    - `schedules` object, required: The frequencies, the formats, the hours, the recipient ceilings, the length of every email field and the two kinds of row this version refuses to update.
    - `portal_views` object, required: The ceilings of a view, which fields an update replaces wholesale, and what asking for a notification implies.
    - `users` object, required: What creating a client user requires and what it sends.
    - `versioning` object, required: What if_version covers, which endpoints accept it, and that sending it anywhere else is refused rather than ignored.
    - `reports_get` object, required: The widget ceiling of /v1/reports/get and what happens above it.
    - `reports` object, required: The four writes of a report that already exists: which fields /v1/reports/update takes, what it never writes, what is not available in this version yet, and the rules of the bulk rebinding, the copy and the duplication for another client.
    - `editing` object[], required: What this surface deliberately cannot express, statement by statement: each entry carries a `key` to switch on, a `statement` a person reads, and, where a call really is refused for it, a `refused_with` with the `error_code` and the named `reason` that come back. An entry with no `refused_with` is a difference from the editor rather than a wall.
    - `guarantees` object, required: How long a confirmation token lives, how long an answer can be replayed, what a dry run costs, which call undoes which, the daily email budget, the ceilings of verify_data and, in `trash`, how long a deleted report stays restorable and what a restore does and does not bring back.
    - `endpoints` object[], required: One entry per write endpoint: whether it always confirms, confirms conditionally or never does, which fields trigger a conditional confirmation, whether it accepts if_version, and the endpoint that undoes it -- plus an undo_note where that endpoint does not put everything back. The undo published for /reports/delete holds only while permanent is false.
    - `endpoints_note` string, required: Says that endpoints[] describes the calls that change something. The reads are listed by the block that describes them.
    - `account` object, required: The only per-account block: the plan's room for reports and templates, how much of it is used, and whether write access is enabled for the key that is calling.
    - `filters` unknown, required
    - `calculated_metrics` unknown, required
    - `brand_templates` unknown, required
    - `language_files` unknown, required
    - `email_templates` unknown, required
    - `snapshots` unknown, required
  - `meta` Meta, required
    - `request_id` string, required: Id of this request, useful when reporting an incident.
    - `timestamp` string, date-time, required: When the answer was built, in UTC.

## Other responses

- `400`: The request was refused before anything was written. INVALID_REQUEST covers the framework refusals of every endpoint (the Content-Type is not application/json, the body could not be read, the body is not valid JSON). The report endpoints add their own: VALIDATION_FAILED with details.problems, UNKNOWN_PARAM with the path of the field the endpoint does not read, and the single-field refusals MISSING_REQUIRED_FIELD, INVALID_VALUE and APPEND_NOT_ALLOWED. The description of each operation lists the ones it emits. Everything else a body can get wrong arrives as an entry of details.problems rather than as the code of the envelope.
- `401`: Invalid or missing Bearer token.
- `404`: A key of the request does not name anything this account owns. NOT_FOUND covers reports, sections, widgets, schedules, portal views, brand templates, email templates and language files; TEMPLATE_NOT_FOUND covers a catalog slug, version or section position that stopped being published between the validation and the write. An entity of another account is reported the same way as one that does not exist.
- `413`: The request body is over 1 MB. The cap is applied before authentication, so this answer is refused without the key being read, and it carries the usual error envelope.
- `429`: A budget was spent. RATE_LIMITED is the per-key read budget (300/minute, 5000/day) or the per-account write budget (60/minute, 1000/day). EMAIL_QUOTA_REACHED is the separate budget of 50 calls per account per day that send email, and its Retry-After points at the next UTC midnight. The Retry-After header gives the seconds until the more restrictive window resets. The X-RateLimit-* headers report the read budget, except on the 429 of a write, where they report the write budget.
- `500`: Internal server error.

---

[API](https://skmtc.dev/reportingninja/apis/reporting-ninja-api.md) · [All operations](https://skmtc.dev/reportingninja/apis/reporting-ninja-api/llms.txt) · [OpenAPI document](https://skmtc.dev/reportingninja/apis/reporting-ninja-api/revisions/13876c71be34?raw)
