---
title: "POST /v1/consents"
method: POST
path: "/v1/consents"
---

# POST /v1/consents

`POST /v1/consents`

## Request

- The document declares no server URL.
- Auth: one of:
  - HTTP bearer
  - API key in cookie `__Secure-better-auth.session_token`

Install the agent a founder has just consented to. Idempotent per (organisation, client).

## Request body

- AgentConsent
  - `clientId` string, required: The OAuth client from the authorize request the founder is answering. Under client-id metadata documents this is an HTTPS URL naming the agent PRODUCT, which is why the same value legitimately appears in many organisations.
  - `name` string, required: What this organisation will call the agent. Display and audit only.
  - `orgCapabilities` string[]: The estate ceiling approved on the CONTROL surface's screen. Omitted means none. ⚠️ Narrowed to the known `org.*` vocabulary on arrival rather than trusted — this comes from a screen, and a scope the resource server does not enforce would be a ceiling raised by whoever typed it.
  - `grants` ConsentedGrant[]: The mailboxes approved on the MAIL surface's screen. Omitted means none.
    - `mailboxId` string, required: From `listMailboxes`.
    - `capabilities` string[], required: From the engine's supported set, as the founder approved them.

## Response `201`

The request has succeeded and a new resource has been created as a result.

- Principal
  - `id` string, required
  - `kind` 'human' | 'agent', required
  - `name` string, required: What the org calls this principal. Display and audit only.
  - `userId` string, nullable, required: Humans: the member's user id. Null for agents — nobody is behind one.
  - `oauthClientId` string, nullable, required: Agents: the OAuth client this principal IS. Null for humans. Minted with the principal, not claimed later: the authorization server holds a per-client capability ceiling and refuses to issue against an empty one, so the client cannot reach a mailbox before a grant says it may. That server-owned ceiling is what the one-time enrolment code used to stand in for.
  - `status` 'enrolled' | 'active' | 'revoked', required: Agents are `enrolled` from birth (→ `revoked`); humans are `active` (→ `revoked`).
  - `orgCapabilities` string[], required: What this principal may do to the ESTATE, as opposed to what it may do with a mailbox. Empty for every human — a person's authority over the organisation is their membership ROLE, resolved per request, and they never authenticate as an OAuth client. For an agent it is the ceiling an admin set at creation, and it is published because an agent that can create mailboxes is an agent that can spend this organisation's capacity: that should be visible on the list, not buried in a token.
  - `createdBy` string, nullable, required: Agents: the member who minted it. Null for humans.
  - `expiresAt` string, date-time, nullable, required: Always null. Kept so a client reading this field does not break; nothing sets it.
  - `enrolledAt` string, date-time, nullable, required
  - `revokedAt` string, date-time, nullable, required
  - `createdAt` string, date-time, required

## Other responses

- `default`: An unexpected error response.

---

[API](https://skmtc.dev/foundermail/apis/org.md) - [All operations](https://skmtc.dev/foundermail/apis/org/llms.txt) - [OpenAPI document](https://skmtc.dev/foundermail/apis/org/revisions/8bbb36e378ab?raw)
