API reference

Conventions

Everything on this page applies to every endpoint in the API: the base URL, versioning, authentication, pagination, date handling, error shapes, and rate limits. The endpoint pages assume these conventions and only document what is specific to each call.

Base URL

All endpoints are served from one base URL. Paths in this reference are shown as they appear on the wire, including the /api prefix.

https://toolboxminute.com/api
GET /api/v1/employees/{externalId}/today

All requests and responses are JSON over HTTPS. Plain HTTP is not served.

Versioning

The API version is the first path segment after the base URL. The current version is v1, so every path in this reference starts with /api/v1/.

  • Additive changes are non-breaking and ship within v1: new endpoints, new optional query parameters, and new response fields. Write your client to ignore response fields it does not recognize.
  • Breaking changes (removing or renaming a field, changing a type or a status value) only ever ship under a new version segment. v1 keeps working.

Authentication

Every request needs a per-tenant API key (only the health probes and the OpenAPI document are public). Send the key either way, on every request:

Authorization: Bearer tbm_live_••••
# or
X-Api-Key: tbm_live_••••

The key scopes every call to your organization's data; the tenant is always resolved from the key, never from anything in the request. See Authentication for creating and revoking keys, and for the public sandbox key you can use to try every example in this reference.

Pagination

List endpoints take page and pageSize query parameters and return a paged envelope:

ParameterTypeDescription
pagenumber1-based page number. Defaults to 1.
pageSizenumberRows per page. Each endpoint documents its default and any cap.
GET /api/v1/reports/activity?page=2&pageSize=50

{
  "items": [ /* the rows for this page */ ],
  "page": 2,
  "pageSize": 50,
  "total": 137
}

total is the full row count across all pages. Keep fetching while page * pageSize is less than total.

Dates and times

  • Dates (lessonDate, weekStart, and the from/to/date query parameters) are ISO yyyy-MM-dd strings and mean a calendar day in the tenant's timezone. Lessons are scheduled per local day, so the local date is the natural key.
  • Timestamps are UTC and the field name says so with a Utc suffix (completedAtUtc, expiresAtUtc). They are ISO 8601, for example 2026-07-15T13:04:11+00:00.

Errors

Error responses are JSON with content type application/problem+json. There are two shapes; both carry a stable machine-readable code your integration can switch on, plus the RFC 7807 title/detail/status fields.

Auth and rate-limit errors

Produced before the request reaches an endpoint: missing or invalid key, a plan without API access, or rate limiting. The code is in error:

# HTTP/1.1 401 Unauthorized
{
  "error": "invalid_api_key",
  "title": "Invalid API key",
  "message": "The API key is invalid or has been revoked.",
  "detail": "The API key is invalid or has been revoked.",
  "status": 401
}
CodeStatusMeaning
missing_api_key401No key was sent. Use Authorization: Bearer or X-Api-Key.
invalid_api_key401The key is unknown or has been revoked.
api_access_required402The tenant's plan does not include API access.
rate_limited429Too many requests. See rate limits below.

Endpoint errors

Produced by an endpoint: an unknown employee, an invalid parameter, a conflict. These are standard RFC 7807 problem details and the code is in title:

# HTTP/1.1 404 Not Found
{
  "type": "https://tools.ietf.org/html/rfc9110#section-15.5.5",
  "title": "unknown_user",
  "status": 404,
  "detail": "No employee was found for external id 'E-9999'."
}

Responses also include a traceId field; include it when contacting support. Endpoint-specific codes (like unknown_user and invalid_return_url) are documented with each endpoint.

Rate limits

Limits use fixed one minute windows and depend on how you authenticate:

CallerLimitCounted per
Sandbox key (tbm_test_)60 requests/minuteCaller IP (the sandbox key is shared)
Live key (tbm_live_)300 requests/minuteAPI key
Anonymous (/health, /openapi)30 requests/minuteCaller IP

Going over the limit returns 429 with a Retry-After header (seconds until the window resets):

# HTTP/1.1 429 Too Many Requests
# Retry-After: 60
{
  "error": "rate_limited",
  "title": "Too many requests",
  "message": "Rate limit exceeded. Wait for the current one minute window to reset, then retry.",
  "detail": "Rate limit exceeded. Wait for the current one minute window to reset, then retry.",
  "status": 429
}

Machine-readable spec

The whole API is described by an OpenAPI document, served without authentication:

GET https://toolboxminute.com/api/openapi/v1.json

Import it into Postman, Insomnia, or your client generator to stay in sync with this reference automatically.