> For the complete documentation index, see [llms.txt](https://help.swarmia.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://help.swarmia.com/settings/integrations/swarmia-apis/custom-reports.md).

# Custom Reports

Any custom reports created at <https://app.swarmia.com/explore> become automatically available under this API. Go to Explore, save a report, then use its UUID to fetch results via the API. The specific properties available on the response rows depend on the report in question.

## Custom report saved in the app

> Executes a custom report and returns the results. Custom\
> reports are created at\
> \[app.swarmia.com/explore]\(<https://app.swarmia.com/explore).\\>
> The \`id\` parameter expected by the API is the UUID shown in the\
> report's URL in the app (query parameter \`activeReport=\<UUID>\`).\
> \
> The response shape (columns, aggregates, grouping) is fully\
> determined by the report. The \`schema\` object in the response\
> describes each column so consumers can interpret the dynamic\
> result.\
> \
> Results are paginated. Use \`limit\` / \`offset\` to page through the\
> rows; the response carries a \`pagination\` object (\`hasMore\`,\
> \`nextOffset\`, and \`totalRows\` when \`includeTotal=true\`). When more\
> rows are available, the next page's offset is also returned in the\
> \`Link: …; rel="next"\` and \`X-Swarmia-Next-Offset\` response headers,\
> which you can follow rather than computing offsets yourself.\
> \
> CSV output (\`output=csv\`) ignores \`limit\`/\`offset\` and streams the\
> full result set up to a cap of \`10000\` rows, setting the\
> \`X-Swarmia-Result-Truncated: true\` header when the result was capped.<br>

```json
{"openapi":"3.1.0","info":{"title":"Swarmia REST API","version":"1.0"},"tags":[{"name":"Custom reports","description":"Any custom reports created at https://app.swarmia.com/explore become\nautomatically available under this API. Go to Explore, save a report,\nthen use its UUID to fetch results via the API. The specific properties\navailable on the response rows depend on the report in question.\n"}],"servers":[{"url":"https://app.swarmia.com/api/v1"}],"security":[{"bearerToken":[]}],"components":{"securitySchemes":{"bearerToken":{"type":"http","scheme":"bearer","description":"API token passed as `Authorization: Bearer <token>`.\nThe token must have the `entityQuery` scope enabled.\nTokens can be provisioned at https://app.swarmia.com/settings/api-tokens.\n"}},"parameters":{"output":{"name":"output","in":"query","description":"Response format.","schema":{"type":"string","enum":["json","csv"],"default":"json"}},"limit":{"name":"limit","in":"query","description":"Maximum number of rows to return in one page. Must be a positive\ninteger no larger than `1000`. Defaults to `100` when omitted.\n\nIgnored for `output=csv`, which always streams the full result set\n(see the `text/csv` response).\n","schema":{"type":"integer","minimum":1,"maximum":1000,"default":100}},"offset":{"name":"offset","in":"query","description":"Number of rows to skip before the page starts, for paging through\na large result set. Must be a non-negative integer no larger than\n`100000`. Defaults to `0`.\n\nPrefer following the `nextOffset` value (or the `Link`/\n`X-Swarmia-Next-Offset` response header) rather than computing\noffsets yourself.\n\nIgnored for `output=csv`.\n","schema":{"type":"integer","minimum":0,"maximum":100000,"default":0}},"includeTotal":{"name":"includeTotal","in":"query","description":"When `true`, the response `pagination` object includes a `totalRows`\ncount of all rows matching the query (ignoring `limit`/`offset`).\nComputing the total is more expensive, so it is omitted by default.\n","schema":{"type":"boolean","default":false}}},"schemas":{"EntityReport_Custom_Result":{"type":"object","required":["schema","rows"],"properties":{"schema":{"type":"object","description":"Describes each property in `rows`. Keys are property names,\nvalues carry things like a human-readable `title`, `description`, etc.\nThe exact properties depend on the report's configuration.\n","additionalProperties":{"$ref":"#/components/schemas/SchemaEntry"}},"rows":{"type":"array","description":"Data rows from the report. Each row has a `_key` identifying the entity\nor group the row represents, plus dynamic properties matching the keys in `schema`.\n","items":{"type":"object","required":["_key"],"properties":{"_key":{"description":"Row identifier. Shape depends on the report's grouping —\nan entity reference for entity-grouped reports, or any\nproperty value for other groupings.\n","anyOf":[{"$ref":"#/components/schemas/EntityReference"},{}]}},"additionalProperties":true}},"summaryRow":{"type":"object","description":"Aggregate across all rows. Same dynamic properties as each\nrow but without `_key`. Only present when enabled in the report.\n","additionalProperties":true},"pagination":{"$ref":"#/components/schemas/Pagination"}}},"SchemaEntry":{"type":"object","required":["title","description"],"properties":{"title":{"type":"string"},"description":{"type":"string"},"aggregate":{"type":"string","description":"The aggregation function used (e.g. `CountDistinct`, `ArrayAggDistinct`)."}}},"EntityReference":{"description":"A reference to an entity. Discriminated by `type`.\n","oneOf":[{"$ref":"#/components/schemas/EntityReference_Team"},{"$ref":"#/components/schemas/EntityReference_Author"},{"$ref":"#/components/schemas/EntityReference_Organization"}]},"EntityReference_Team":{"type":"object","description":"Teams represent your organization structure and are the owners of other entities like Issues and Pull requests.","required":["type","id","name"],"properties":{"type":{"type":"string","const":"Team"},"id":{"type":"string","format":"uuid"},"name":{"type":"string"}}},"EntityReference_Author":{"type":"object","description":"Authors are the people or bots that can be attributed different kinds of work items (commits, pull requests, reviews). Authors can be linked to multiple identities across different systems (GitHub, Slack, Jira, etc.)","required":["type","id","name","email"],"properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string","const":"Author"},"name":{"type":["string","null"]},"email":{"type":["string","null"]}}},"EntityReference_Organization":{"type":"object","description":"The organization that the API token belongs to.","required":["type","id"],"properties":{"type":{"type":"string","const":"Organization"},"id":{"type":"string","format":"uuid"},"name":{"type":["string","null"]}}},"Pagination":{"type":"object","description":"Paging metadata for the current page. Only present on JSON\nresponses (CSV streams the full result set instead).\n","required":["hasMore","nextOffset"],"properties":{"hasMore":{"type":"boolean","description":"Whether more rows are available beyond this page."},"nextOffset":{"type":["integer","null"],"description":"The `offset` to request the next page, or `null` when there\nare no more rows (`hasMore` is `false`).\n"},"totalRows":{"type":"integer","description":"Total number of rows matching the query, ignoring\n`limit`/`offset`. Only present when `includeTotal=true` was\nrequested.\n"}}},"EntityReport_Error":{"type":"object","properties":{"error":{"type":"boolean"},"message":{"type":"string"}}}}},"paths":{"/reports/custom/{id}":{"get":{"tags":["Custom reports"],"operationId":"getReportsCustomById","summary":"Custom report saved in the app","description":"Executes a custom report and returns the results. Custom\nreports are created at\n[app.swarmia.com/explore](https://app.swarmia.com/explore).\nThe `id` parameter expected by the API is the UUID shown in the\nreport's URL in the app (query parameter `activeReport=<UUID>`).\n\nThe response shape (columns, aggregates, grouping) is fully\ndetermined by the report. The `schema` object in the response\ndescribes each column so consumers can interpret the dynamic\nresult.\n\nResults are paginated. Use `limit` / `offset` to page through the\nrows; the response carries a `pagination` object (`hasMore`,\n`nextOffset`, and `totalRows` when `includeTotal=true`). When more\nrows are available, the next page's offset is also returned in the\n`Link: …; rel=\"next\"` and `X-Swarmia-Next-Offset` response headers,\nwhich you can follow rather than computing offsets yourself.\n\nCSV output (`output=csv`) ignores `limit`/`offset` and streams the\nfull result set up to a cap of `10000` rows, setting the\n`X-Swarmia-Result-Truncated: true` header when the result was capped.\n","parameters":[{"name":"id","in":"path","required":true,"description":"UUID of a custom report.","schema":{"type":"string","format":"uuid"}},{"$ref":"#/components/parameters/output"},{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/offset"},{"$ref":"#/components/parameters/includeTotal"},{"name":"timeframe.start","in":"query","description":"Start of the reporting period (inclusive). When provided\ntogether with `timeframe.end`, overrides **all** timeframe\nfilters embedded in the report. When omitted, the\nreport's original timeframes are used as-is.\n","schema":{"type":"string","format":"date"}},{"name":"timeframe.end","in":"query","description":"End of the reporting period (inclusive). Must be provided\ntogether with `timeframe.start`.\n","schema":{"type":"string","format":"date"}},{"name":"timezone","in":"query","description":"IANA timezone used to interpret the date-only `timeframe.start`\nand `timeframe.end` values and for time bucketing. Defaults to `UTC`.\n","schema":{"type":"string","default":"UTC"}}],"responses":{"200":{"description":"Successful response.","headers":{"Link":{"description":"Present when more rows are available. Carries the next page\nas `<…?offset=N>; rel=\"next\"`.\n","schema":{"type":"string"}},"X-Swarmia-Next-Offset":{"description":"Present when more rows are available. The `offset` to request\nthe next page.\n","schema":{"type":"integer"}},"X-Swarmia-Result-Truncated":{"description":"Set to `true` on `output=csv` responses when the result set\nexceeded the CSV row cap and was truncated.\n","schema":{"type":"string","enum":["true"]}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntityReport_Custom_Result"}},"text/csv":{"schema":{"type":"string"}}}},"400":{"description":"Invalid or unknown parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntityReport_Error"}}}},"401":{"description":"Missing or invalid API token."},"404":{"description":"Report not found."}}}}}}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://help.swarmia.com/settings/integrations/swarmia-apis/custom-reports.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
