API Reference
The Two Minute Reports API is a REST API that lets you manage your account, teams, connections, and clients, and run data queries programmatically — the same capabilities available in the app, exposed over HTTP with JSON.
v1. All endpoints are prefixed with /v1.Base URL
https://api.twominutereports.com/v1
All paths in this reference are relative to this base URL. For example, GET /users/me means GET https://api.twominutereports.com/v1/users/me.
Authentication
Every request must include a bearer token in the Authorization header:
curl https://api.twominutereports.com/v1/users/me \
-H "Authorization: Bearer tmrc_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
Create and manage keys from your account settings. See Authentication for full details.
Response format
Every response uses a consistent envelope so you can branch on a single success flag.
{
"success": true,
"data": { }
}
On success, data holds the result — an object or an array depending on the endpoint.
{
"success": false,
"error": {
"code": "NOT_FOUND",
"message": "The requested resource was not found"
}
}
On failure, error.code is a stable machine-readable string and error.message is human-readable. See Errors.
Conventions
- Content type: Request bodies are JSON (
Content-Type: application/json), except file uploads which usemultipart/form-data. - IDs: Resource IDs such as
teamId,userId, andsessionIdare UUID v7 strings. Account IDs are provider-defined strings prefixed with the connector ID (e.g.gadw_1234567890). - Timestamps: All timestamps are ISO 8601 strings in UTC (e.g.
2026-06-16T09:30:00.000Z). - Roles: Team-scoped endpoints require a minimum role —
viewer,editor, orowner. Each endpoint notes its requirement.
Keys, scopes and permissions
Two separate checks run on every team-scoped request, and a call has to pass both.
- What the key is allowed to do. Every key has scopes, chosen when you create it, and a call outside them is refused.
- What the person who created the key is allowed to do. A key carries the team permissions of its holder.
The effective permission is the intersection: a key's scopes can only narrow its holder's permissions, never widen them. A key created by a member who can only read cannot write, whatever scopes it was given. If that member's access on the team is later reduced, the key's access is reduced with it — without the key being touched.
- A key belonging to somebody who leaves the team stops working. If an integration matters, create its key under an account that is staying.
- Permissions are per team. The same key can be accepted for one team and refused for another, because the person behind it has different access in each. A
403on one team and a200on another is not a broken key — read the team in the error message. See Seats.
Using the API itself never requires a seat, so an integration set up by somebody who later loses their seat keeps reading. What stops is the writes.
The user object
Several resources tell you who did something — who created a connection, who last edited it, who enabled an account, who sent an invite. Wherever that appears it is the same object rather than a bare ID, so you can render a name and an avatar without a second lookup.
{
"id": "0190f8b7-3c4d-7e5f-9a0b-1c2d3e4f5a6b",
"name": "Priya Raman",
"firstName": "Priya",
"lastName": "Raman",
"avatarUrl": "https://assets.gox.ai/tmr/avatars/priya.png",
"email": "[email protected]"
}
null if the user has not set one. It is firstName and lastName joined with a
space, so it is never something the two parts do not say.null if not set.null if not set. A one-word name is a firstName with no lastName, so do not
read an absent lastName as missing data.null if the user has no avatar.The object itself may be null. A record created before we started tracking who acted on it has
nobody to name, and that is reported as null rather than as a placeholder user — so always check the
object before reading its fields.
updatedBy always names a person. Background work — cache refreshes, vote and view counters,
scheduled recomputes — updates records without touching it, so it never reports a machine as the
editor and never blanks whoever edited last.
createdBy used to be a bare UUID string on
connections, clients and the team dashboards list. It is now the
object above. If you were reading createdBy as an ID, read createdBy.id instead.Reference
| Resource | Description |
|---|---|
| Authentication | Bearer tokens and API keys |
| Rate limits | Request quotas and the 429 response |
| Errors | Error envelope and status codes |
| Users | Profile and preferences |
| Teams | Teams, members, roles, and seats |
| Connections | OAuth/data connections for a team |
| Connectors | Connectors, accounts, and fields |
| Clients | Clients and their linked accounts |
| Data | Run data queries |
| Platform | Plans, connectors, roadmap, and changelog |