Organisations

Developer·3 minutes to read

Verified against docs/superpowers/specs/2026-09-15-p4-a-typed-http-api-openapi-webhooks.md §4.3, §4.4, §5.1, §6; re-verified against the code at close-out.

What it does

Two different credentials meet on this page: an organisation key reads and renames the one organisation it belongs to, and the operator's platform key creates organisations, lists the ones it created and asks for one to be deleted (F-ID-2 — a personal organisation on sign-up, team organisations with roles).

Authentication

GET /organisation needs an organisation key of scope read or wider. PATCH /organisation needs admin. The four /organisations routes are the platform class and reach nothing else; an organisation key on them, or a platform key on anything else, is refused exactly as no credential is. See Authentication and keys.

Request

GET /organisation

<!-- generated:begin GET /organisation --> <!-- generated:end GET /organisation -->

PATCH /organisation

<!-- generated:begin PATCH /organisation --> <!-- generated:end PATCH /organisation -->

POST /organisations

<!-- generated:begin POST /organisations --> <!-- generated:end POST /organisations -->

GET /organisations

<!-- generated:begin GET /organisations --> <!-- generated:end GET /organisations -->

GET /organisations/{id}

<!-- generated:begin GET /organisations/{id} --> <!-- generated:end GET /organisations/{id} -->

DELETE /organisations/{id}

<!-- generated:begin DELETE /organisations/{id} --> <!-- generated:end DELETE /organisations/{id} -->

A name is 1 to 80 characters. POST /organisations takes the new owner's e-mail and, optionally, a first key to mint for them; when the e-mail already has a user, that person becomes the owner and no second identity is created. DELETE /organisations/{id} does not remove anything: it records a deletion request with the grace period the product gives every organisation, it is written as the organisation's own live owner, and calling it twice returns the same open request rather than opening a second one. A platform key only ever sees the organisations it created; another key's organisation reads as not_found.

curl -sS "$BOTSEON_API_ORIGIN/api/v1/organisation" \
  -H "authorization: Bearer $BOTSEON_API_KEY" \
  -H "accept: application/json"
const res = await fetch(`${process.env.BOTSEON_API_ORIGIN}/api/v1/organisation`, {
  headers: {
    authorization: `Bearer ${process.env.BOTSEON_API_KEY}`,
    accept: 'application/json',
  },
});
if (!res.ok) throw new Error(`organisation: ${res.status}`);
const org = (await res.json()) as {
  id: string;
  name: string;
  kind: 'personal' | 'team';
  createdAt: string;
  deletionRequestedAt: string | null;
};
console.log(org.name, org.kind, org.deletionRequestedAt ?? 'no deletion requested');

Response

{
  "id": "2b7c9d10-3e4f-4a5b-8c9d-0e1f2a3b4c5d",
  "name": "Nordic Supplies",
  "kind": "team",
  "createdAt": "2026-03-04T09:12:00.000Z",
  "deletionRequestedAt": null
}

kind is personal or team. A personal organisation is the one every person gets on sign-up; a team organisation is the one with roles. deletionRequestedAt is set once a deletion has been asked for and is null otherwise.

Errors

StatusCodeWhenWhat to do
401unauthenticatedThe credential is missing, refused, of the wrong class, or below the scope the route needs.Check the key's class and scope.
400invalid_requestThe name is outside 1 to 80 characters, the owner e-mail is not an address, or the POST carries no Idempotency-Key.Read details.
404not_foundThe organisation is not one this platform key created.List the key's own organisations first.
409conflictThe organisation has no live owner or admin to write a deletion request as.Restore a member to the organisation, or use the app.
429rate_limitedA bucket is full.Wait for Retry-After.
503unavailableThe service could not answer.Retry with backoff.

Rate limits

Every call on this page is counted against three one-minute buckets: 300 requests per key, 1 000 per organisation, and — for the platform-key routes — 60 per platform key. A full bucket answers rate_limited with Retry-After: 60; wait that many seconds and retry. Failed authentication is counted separately, against the caller's address, so a working key's allowance is never spent by somebody else's bad credential. See Envelopes, errors, idempotency and paging.

Last verified against build c0f77aa.