---
title: Identity, spec & batch
description: GET /me to verify a credential, GET /organizations to list the organizations it can act on, the public OpenAPI document, the monitor-type catalog endpoint, and POST /batch to run up to 20 operations in one request.
canonical: https://watchfor.io/docs/api/meta
---

# Identity, spec & batch

GET /me to verify a credential, GET /organizations to list the organizations it can act on, the public OpenAPI document, the monitor-type catalog endpoint, and POST /batch to run up to 20 operations in one request.

Small endpoints that support everything else: identify the credential
you are using and the organizations it can act on, fetch the
machine-readable contract, and bundle several calls into one round trip.

| Method | Path | Scope | operationId |
| --- | --- | --- | --- |
| GET | `/v1/me` | read | `getMe` |
| GET | `/v1/organizations` | read | `listOrganizations` |
| GET | `/v1/openapi.json` | none | `getOpenApiSpec` |
| GET | `/v1/meta/monitor-types` | none | `listMonitorTypes` |
| POST | `/v1/batch` | per sub-operation | `batchOperations` |

## Identify the credential

`GET /v1/me` — the "does my auth work?" call. Returns the organization
the credential resolves to and its effective scope. Works for API keys
and OAuth tokens alike.

```bash
curl https://watchfor.io/api/v1/me \
  -H "Authorization: Bearer wf_live_YOUR_KEY"
```

```json
{
  "object": "api_key_identity",
  "organization": { "id": "6f0a…", "name": "Acme Cloud", "slug": "acme-cloud" },
  "scope": "read"
}
```

`scope` is `read` or `write`. For OAuth tokens it is `write` only when
the token was granted the `write` scope. See
[Authentication](/docs/api/authentication).

## List organizations

`GET /v1/organizations` — the organizations the credential can act on,
i.e. the ids the `X-WatchFor-Organization` header accepts (see
[How OAuth maps to your data](/docs/api/authentication#how-oauth-maps-to-your-data)).

```bash
curl https://watchfor.io/api/v1/organizations \
  -H "Authorization: Bearer YOUR_OAUTH_ACCESS_TOKEN"
```

```json
{
  "object": "list",
  "data": [
    {
      "id": "0b6c2f1e-6d2a-4c47-9a51-3f0f2a9c8e11",
      "object": "organization",
      "name": "Acme Cloud",
      "slug": "acme-cloud",
      "logo": null,
      "role": "owner",
      "plan": "Pro",
      "is_default": true,
      "is_current": true
    },
    {
      "id": "7f3d9a20-1c4e-4b8a-9d2f-5e6a7b8c9d01",
      "object": "organization",
      "name": "Globex",
      "slug": "globex",
      "logo": "https://watchfor.io/storage/…/globex.png",
      "role": "member",
      "plan": "Free",
      "is_default": false,
      "is_current": false
    }
  ],
  "has_more": false
}
```

| Credential | What it lists |
| --- | --- |
| OAuth token | Every organization the token's user belongs to, oldest membership first, with their `role` there (`owner`, `admin` or `member`) |
| API key | Only the key's own organization, with `role: null` (a key acts for the organization, it isn't a member) |
| WatchFor AI Agent (early access) | Only the organization the agent is running in |

- `is_default` marks the organization requests act on when
  `X-WatchFor-Organization` is omitted (the user's oldest owned
  organization, else their oldest membership); `is_current` marks the one
  this request acted on — the header's organization, else the default.
- The header is not needed, and the listing is not plan-gated, so a
  client can always discover the ids. A header naming an organization the
  user doesn't belong to is still `403 forbidden`, as everywhere.
- `plan` is the organization's current plan name. Not paginated:
  `has_more` is always `false`.

SDKs: `wf.organizations.list()` (Ruby: `wf.organizations.list`); CLI:
`watchfor organizations`.

## OpenAPI document

`GET /v1/openapi.json` — the OpenAPI 3.1 description of every operation,
schema, parameter and error shape. Public, no key needed, cached for an
hour. Also served at `/openapi.json` and `/.well-known/openapi.json`.
Every operation declares a stable `operationId`, and every authenticated
one an `x-required-scope` (the public spec, the public type catalog and
`POST /batch` — which inherits its sub-operations' scopes — carry none);
list envelopes are named component schemas (`MonitorList`,
`IncidentList`, …) so generated clients get typed pages.

## Monitor type catalog

`GET /v1/meta/monitor-types` — every monitor type with its label,
description, target format and example, the default alert rules the
system seeds, the alert metrics you can build rules from and the config
fields it accepts. Public, no key needed. The top-level `operators`
array lists the comparison operators valid for numeric metrics. The
human-readable rendering is the [Monitor types reference](/docs/api/monitor-types).

## Batch

`POST /v1/batch` — run up to **20** API operations in one request. Each
operation is executed against `/api/v1` with the same credential you
sent, so scopes, validation and rate limits apply per sub-operation
exactly as for direct calls (the batch request and each sub-operation
consume one request each from your budget; the batch response's
`X-RateLimit-*` headers show what is left after the fan-out). Send an
`Idempotency-Key` on the batch to retry it safely: a retry with the same
key and the same body replays the stored batch result (with
`Idempotency-Replay: true`) instead of running the operations again; the
same key with a different body is a `409`. Only `Authorization`,
`Content-Type` and `X-WatchFor-Organization` are forwarded to the
sub-operations. Results come back as a parallel array in request order; a
failing sub-operation does not abort the others.

```bash
curl -X POST https://watchfor.io/api/v1/batch \
  -H "Authorization: Bearer wf_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "operations": [
      { "method": "GET", "path": "/summary" },
      { "method": "GET", "path": "/monitors?status=down&limit=5" },
      { "method": "POST", "path": "/incidents/19351/acknowledge" }
    ]
  }'
```

```json
{
  "object": "batch_result",
  "results": [
    { "status": 200, "body": { "object": "summary", "…": "…" } },
    { "status": 200, "body": { "object": "list", "data": [], "has_more": false, "next_cursor": null } },
    { "status": 409, "body": { "error": { "code": "conflict", "message": "Cannot acknowledge a resolved incident" } } }
  ]
}
```

Rules:

- `operations` is required (a bare JSON array is also accepted);
  1–20 entries, each `{ "method", "path", "body"? }`.
- `method` is one of `GET`, `POST`, `PATCH`, `PUT`, `DELETE`; `path` is a
  relative `/api/v1` sub-path starting with `/` (query strings allowed).
  Absolute URLs, `..` and `/batch` itself are rejected with a per-item
  `400`.
- `body` is sent as JSON for non-GET operations.
- The batch endpoint itself needs a valid credential (`401` otherwise),
  and each sub-operation re-validates it.
- A batch body over 256 KiB is a `413 payload_too_large`.
- A sub-request that cannot be executed at all returns
  `{ "status": 502, "body": { "error": { "code": "internal_error", … } } }`.

Use batch for fan-out reads (several monitors' uptime at once) or a
handful of related writes; for large bulk pause/resume/delete use
[`POST /v1/monitors/bulk`](/docs/api/monitors#bulk-operations).

---

Canonical page: https://watchfor.io/docs/api/meta · All docs: https://watchfor.io/docs · Site guide: https://watchfor.io/llms.txt
