Two Minute Reports Logo

API reference

The Two Minute Reports REST API. Authenticate with a bearer token, then manage teams, connections and clients, and run data queries.

The Two Minute Reports API is a REST API that sends and receives JSON. Use it to manage your profile, teams, connections, and clients, and to run data queries from your own code.

The API is currently versioned at 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 the key with the intended use API: in the Hub, on the Automations tab of the AI tools page, or in Settings › API keys. A key made for the MCP server does not work here. See Authentication.

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. It is an object or an array, depending on the endpoint.

Conventions

  • Content type: Request bodies are JSON (Content-Type: application/json), except file uploads which use multipart/form-data.
  • IDs: Resource IDs such as teamId, userId, and clientId are UUID v7 strings. Account IDs are strings that the platform defines, such as 1234567890 for a Google Ads account. In a data query, an account ID starts with its connector ID, such as gadw_1234567890.
  • Timestamps: All timestamps are ISO 8601 strings in UTC (for example 2026-06-16T09:30:00.000Z).
  • Team permissions: Team-scoped endpoints need a team permission, such as clients.read. The role of the person who created the key must include it. Each endpoint page names the permission it needs.

Keys, scopes and permissions

Two separate checks run on every team-scoped request, and a call has to pass both.

  1. What the key is allowed to do. Every key has scopes, chosen when you create it, and a call outside them is refused.
  2. 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. Nobody has to change the key.

Two consequences worth designing for:
  • 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 403 on one team and a 200 on another is not a broken key. Check the role the key holder has in the team that the request names. See Seats.

Using the API itself does not need a seat. An integration set up by somebody who later loses their seat can still read teams, connections and clients. Writes stop, and so do data queries, because running a query needs a seat.

The user object

Several resources tell you who did something: who created a connection, who last edited it, or who enabled an account. Wherever that appears, it is the same object rather than a bare ID. You can show 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]"
}
id
string · uuid v7
The user's unique identifier.
name
string | null
Full name, or 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.
firstName
string | null
First name, or null if not set.
lastName
string | null
Last name, or null if not set. A one-word name is a firstName with no lastName, so do not read an absent lastName as missing data.
avatarUrl
string | null
Avatar image URL, or null if the user has no avatar.
email
string
Email address. Present on team-scoped endpoints only. The public roadmap and changelog do not include this field, because people outside the team that owns the content can read them.

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. Always check the object before you read its fields.

updatedBy always names a person. Background work (cache refreshes, vote and view counters, scheduled recomputes) updates records without changing it. It never reports a machine as the editor, and it never clears whoever edited last.

Breaking change, August 2026.createdBy used to be a bare UUID string on connections and clients. It is now the object above. If you were reading createdBy as an ID, read createdBy.id instead.

Reference

ResourceDescription
AuthenticationBearer tokens and API keys
Rate limitsRequest quotas and the 429 response
ErrorsError envelope and status codes
UsersProfile and preferences
TeamsTeams, members, roles, and seats
ConnectionsA team's connections
ConnectorsConnectors, accounts, and fields
ClientsClients, their contacts, and their assigned accounts
DataRun data queries
PlatformPlans, connectors, roadmap, and changelog
Copyright © 2026