# API overview

The 42min Public REST API lets you read and write the same data you see in
the [dashboard](/360) — event types, availability, slots, and bookings — from
your own systems. It is JSON over HTTPS, versioned at `/v1`, authenticated with
either a [personal access token](/help/api/authentication#personal-access-tokens-pats)
or an [OAuth 2.1 access token](/help/api/authentication#oauth-2-1--pkce).

## Base URL

```
https://api.42min.us
```

All paths in this reference are relative to that origin. Every request must use
HTTPS — plain `http://` is refused at the edge.

## Versioning

The current major version is **`v1`**. It appears in every resource path:

```
GET https://api.42min.us/v1/me
```

Within a major version, additive changes (new fields, new endpoints, new optional
parameters) are made without bumping the version. Breaking changes ship as a
new major version. Discovery endpoints are unversioned and live under
[`/.well-known/`](/help/api/discovery).

## Response envelope

Every successful JSON response is wrapped in a small envelope:

```json
{
  "data": { /* the resource, or a list */ },
  "meta": {
    "request_id": "req_…",
    "next_cursor": "…",
    "has_more": false
  }
}
```

- `data` is the resource for single-resource responses, or an array for list
  endpoints.
- `meta.request_id` is unique per request and is the value to quote when
  reporting an issue.
- `meta.next_cursor` and `meta.has_more` appear only on paginated list
  endpoints.

A handful of OAuth and discovery endpoints (the `/v1/oauth/*` family and
`/.well-known/*`) return the spec-defined raw bodies — those are **not** wrapped.

## Errors

Errors share one shape — see [Error envelope](/help/api/errors):

```json
{
  "error": {
    "code": "insufficient_scope",
    "message": "This action requires the 'bookings:create' scope",
    "details": { "required_scope": "bookings:create" },
    "request_id": "req_…"
  }
}
```

## Pagination

List endpoints (`/v1/event-types`, `/v1/bookings`) use **cursor pagination**.
Pass `limit` (default 20, max 100) and follow `meta.next_cursor` until
`meta.has_more` is `false`. Cursors are opaque base64url strings — don't parse
them.

```bash
curl -H "Authorization: Bearer $TOKEN" \
  "https://api.42min.us/v1/bookings?limit=50&cursor=eyJpZCI6Ii4uLiJ9"
```

## Identifiers

- **Event types** can be addressed by **UUID** *or* by `username/event-slug`
  (the same path segments as the public booking page).
- **Bookings** are always addressed by their UUID (`uid`).
- All timestamps are ISO 8601 with offset — typically UTC (`…Z`).
- All durations are integers in **minutes**.

## What's in scope

| Resource | Read | Create | Mutate |
|---|---|---|---|
| [`/v1/_ping`](/help/api/ping) | ✓ | — | — |
| [`/v1/me`](/help/api/me) | ✓ | — | — |
| [`/v1/event-types`](/help/api/event-types) | ✓ | — | — |
| [`/v1/slots`](/help/api/slots) | ✓ | — | — |
| [`/v1/bookings`](/help/api/bookings) | ✓ | ✓ | cancel · reschedule · PATCH |
| [`/v1/webhooks`](/help/api/webhooks) | ✓ | ✓ | PATCH · DELETE · rotate-secret · test |

Webhooks have two sides: **managing** subscriptions over the API
([`/v1/webhooks`](/help/api/webhooks)) and **receiving** the signed callbacks
(verification, retries, auto-pause — see
[API & webhooks](/help/team-and-admin/api-and-webhooks)).

## Conventions

- **Authentication** — bearer tokens in the `Authorization` header. See
  [Authentication](/help/api/authentication).
- **Scopes** — every endpoint declares a required scope; see
  [Scopes](/help/api/scopes).
- **Rate limits** — 120 rpm authenticated, 30 rpm anonymous; see
  [Rate limits](/help/api/rate-limits).
- **Idempotency** — every write requires an `Idempotency-Key`; see
  [Idempotency](/help/api/idempotency).
- **Optimistic locking** — PATCH requires a matching ETag via `If-Match`; see
  [Optimistic locking](/help/api/optimistic-locking).

## Where to mint credentials

- **Personal access tokens** are minted in
  [Admin Center → API](/360/api) on the **API keys** tab.
- **OAuth clients** are registered on the **OAuth apps** tab of the same page.
