> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mnemom.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Claim an agent into an org

> Binds an unclaimed (or legacy hash-claimed) agent to the authenticated caller and an organization.

Claim an agent: prove you hold its provider API key, take ownership, and place
it in one of your orgs. This is the canonical second half of the **gateway-first
lifecycle** — an agent provisioned by its first gateway traffic starts unclaimed
in the **Mnemom Sandbox** holding org, and `claim` is how it gets an owner and a
real org.

```
gateway first-traffic  →  Mnemom Sandbox (unclaimed)  →  claim  →  your org
```

<Warning>
  **Breaking change: claim now requires authentication.** Earlier, claim accepted a body-only `hash_proof` with no authenticated caller. It now requires an authenticated principal (session or API key) — that principal becomes the agent's owner. An unauthenticated request returns `401`. If you previously called claim anonymously, add authentication. (Self-register via [`POST /v1/agents`](/api-reference/endpoint/post-agents) was already authenticated and is unaffected.)
</Warning>

<Note>
  **Which one do you need?** One question decides it: *are you the agent, or adopting a pre-existing one?* If your own key **is** the agent's identity, you're self-registering — use [`POST /v1/agents`](/api-reference/endpoint/post-agents), which does ownership and org placement in that one authenticated call (no separate claim step). Use `claim` to **adopt** an agent that already exists with an identity not derived from your key — typically one the gateway auto-provisioned into the Mnemom Sandbox before an authenticated owner existed. These answer different questions; neither is legacy. See [Agent identity](/concepts/agent-identity#registration).
</Note>

## Proving possession

`hash_proof` is the full 64-character hex `SHA256(apiKey + '|' + agentName)`
(or `SHA256(apiKey)` for an unnamed singleton agent) — the same value used at
registration. It proves you hold the provider key without transmitting it; the
API compares it against the stored proof and never sees your raw key.

## Choosing the org

* **Pass `org_id`** (an `org-…` or `pers-…` id) to place the agent in a specific
  org. You must hold a member role on it (`owner`, `admin`, or `member`).
  Claiming into an org you don't belong to is rejected with
  `403 agent_org_not_member`; the error `details` carry `requested_org_id` and
  `claimable_orgs` — the orgs you *can* claim into, as
  `{ org_id, name, is_personal }` objects. An **unknown** `org_id` returns
  `400` instead.
* **Omit `org_id`** and the agent lands in your **personal org**. This default
  is the smallest-blast-radius choice: a personal org contains only you, so an
  accidental claim can never over-share the agent to a team. To place the agent
  in a shared or company org, name it explicitly with `org_id`.

The `200` response always reports the **resolved** `org_id`, so you know exactly
where the agent landed regardless of which path you took.

To discover which orgs you can claim into, use
[`GET /v1/orgs`](/api-reference/endpoint/get-orgs) (or `mnemom org list`).
[`GET /v1/me/context`](/api-reference/endpoint/get-me-context) returns your
active org plus your full membership list — the same set echoed in the `403`
body.

## Authentication

Claim is an **authenticated** call — the principal you authenticate as becomes
the agent's owner. An unauthenticated request returns `401`. (This is what
distinguishes adoption from self-register: there must be an owner to assign.)

## Idempotency, re-home, and ownership

Think of claim as a **declarative assertion**: *"this agent is mine, and it
lives in the org I name."* Repeating that assertion as the rightful owner is
always safe, so claim is **idempotent for the same owner** (`200`, never `409`):

* **Re-claim with the same (or no) `org_id`** → no-op success. The original
  `claimed_at` is preserved.
* **Re-claim with a *new* `org_id`** → the agent is **re-homed** (moved) to that
  org. Claim is therefore also how you *move* an agent you own between your orgs.

An agent already owned by a *different* principal is **not** adoptable: that
returns `403 agent_cross_tenant`. Holding a valid `hash_proof` lets you claim an
*unowned* agent; it never lets you take over one that already has an owner.


## OpenAPI

````yaml POST /agents/{agent_id}/claim
openapi: 3.1.0
info:
  title: Mnemom API
  description: >-
    Trust infrastructure for AI agents. Transparent alignment verification,
    behavioral drift detection, and accountability primitives.
  version: 1.0.0
  contact:
    name: Mnemom
    url: https://mnemom.ai
    email: support@mnemom.ai
  license:
    name: Apache 2.0
    url: https://www.apache.org/licenses/LICENSE-2.0
servers:
  - url: https://api.mnemom.ai/v1
    description: Production
security:
  - BearerAuth: []
  - ApiKeyAuth: []
tags:
  - name: A2A
    description: >-
      Public A2A AgentCard projection of the canonical alignment card, with
      embedded AAP attestation extension (cards-as-primitive Phase 5).
  - name: Agents
    description: Agent registration, lifecycle, and metadata.
  - name: Agent Containment
    description: Containment policies and quarantine controls.
  - name: Alignment
    description: >-
      Alignment manifest CRUD — canonical `/v1/alignment/<scope>/<scope_id>`
      surface across platform / org / team / agent (cards-as-primitive Phase 4).
  - name: Analyze
    description: Behavioral analysis endpoints.
  - name: Attestation
    description: >-
      AAP attestation token JWKS surface and platform-admin signing-key rotation
      (cards-as-primitive Phase 5).
  - name: Auth
    description: Authentication, sessions, and access management.
  - name: Billing
    description: Subscription, usage, and invoicing.
  - name: Blog
    description: Public blog content.
  - name: Card Templates
    description: Org-level alignment and protection card templates.
  - name: Catalog
    description: >-
      Discovery surface for the 25-entry Mnemom value catalog v1
      (cards-as-primitive Phase 4).
  - name: Checkpoints
    description: Integrity checkpoints and proof artifacts.
  - name: Conscience Values
    description: Org-level conscience-value configuration.
  - name: Drift
    description: Drift detection and resolution.
  - name: Enforcement
    description: Enforcement-mode configuration and queries.
  - name: Governance
    description: Operator-actionable governance signals (ADR-048).
  - name: Integrity
    description: AIP integrity checkpoints and verdicts.
  - name: Intelligence
    description: Intelligence reports and queries.
  - name: Licensing
    description: License management.
  - name: Network
    description: >-
      Protection Network L4 thermometer read surface. Public-aggregate
      disclosure: any authenticated principal may read; rows carry no per-tenant
      identifiers.
  - name: OAuth
    description: >-
      OAuth 2.1 authorization-code + PKCE flow for MCP clients (MNE-328).
      Identity delegated to Supabase GoTrue; mnemom-api mints its own
      short-lived MCP-scoped tokens. Includes RFC 7591 dynamic client
      registration and RFC 7009 revocation.
  - name: On-Chain
    description: On-chain verification and proofs.
  - name: Organizations
    description: Org-level resources and management.
  - name: Policy
    description: Policy evaluation and configuration.
  - name: Postures
    description: Trust posture management (ADR-045).
  - name: Protection
    description: >-
      Protection manifest CRUD — canonical `/v1/protection/<scope>/<scope_id>`
      surface across platform / org / team / agent (cards-as-primitive Phase 4).
  - name: Recipes
    description: >-
      Customer-facing detection-recipe surface — FN/FP reports. Distinct from
      the Admin recipe-promotion surface and the Internal seeding surface.
  - name: Reclassification
    description: Reclassification workflows.
  - name: Reputation
    description: Per-agent reputation scores.
  - name: Risk
    description: Risk assessment endpoints.
  - name: Safe House
    description: Safe House threat detection and quarantine.
  - name: Sideband
    description: Sideband detection queries (legacy; sunsetting).
  - name: Team Reputation
    description: Team-level reputation aggregates.
  - name: Teams
    description: Team-scope resources.
  - name: Tools
    description: >-
      Mnemom-side tools registry — per-tool class+domain+schema metadata
      (cards-as-primitive Phase 4).
  - name: Traces
    description: AP-Trace artifacts and queries.
  - name: Transparency
    description: >-
      Append-only public log of every canonical card identity ever composed.
      Signed Merkle root + per-row inclusion proofs (cards-as-primitive Phase
      5).
  - name: Trust
    description: >-
      Protection Network L5 public-trust surface — security advisories, IoC feed
      (STIX 2.1), and platform-admin CMS for both.
  - name: Verification
    description: Trace verification endpoints.
  - name: Webhook Notifications
    description: Webhook event subscription management.
  - name: Webhooks
    description: Webhook delivery and lifecycle.
  - name: Misc
    description: >-
      Miscellaneous operator-facing endpoints (contact, enterprise inquiries,
      compliance).
  - name: Notifications
    description: >-
      Reactive notification channels — SSE stream + signed-webhook subscriptions
      for canonical card changes (cards-as-primitive Phase 5).
paths:
  /agents/{agent_id}/claim:
    post:
      tags:
        - Agents
      summary: Claim an agent into an organization
      description: >-
        Binds an unclaimed (or legacy hash-claimed) agent to the authenticated
        caller and an organization. Requires authentication — the caller proves
        possession of the agent via `hash_proof`, and the agent's `org_id` is
        set to the resolved org (the authz + listing boundary, ADR-062). Supply
        `org_id` to claim into a specific org the caller is a member of (role
        floor: member); omit it to claim into the caller's personal org.
        Idempotent: re-claiming an agent the caller already owns returns 200
        with the resolved org.
      operationId: claimAgent
      parameters:
        - $ref: '#/components/parameters/AgentId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - hash_proof
              properties:
                hash_proof:
                  type: string
                  pattern: ^[0-9a-f]{64}$
                  description: >-
                    Agent possession proof: the full 64-hex SHA-256 digest of
                    `${apiKey}|${agentName}` (or `${apiKey}` for an unnamed
                    singleton agent).
                org_id:
                  type: string
                  description: >-
                    Optional. The organization to claim the agent into (e.g.
                    `org-...` or `pers-...`). The caller must be a member of
                    this org (role floor: member). If omitted, the agent is
                    claimed into the caller's personal org.
      responses:
        '200':
          description: Agent claimed into the resolved organization
          content:
            application/json:
              schema:
                type: object
                required:
                  - claimed
                  - agent_id
                  - org_id
                  - claimed_at
                properties:
                  claimed:
                    type: boolean
                  agent_id:
                    type: string
                  org_id:
                    type: string
                    description: >-
                      The organization the agent was claimed into (echoes the
                      resolved org — the supplied `org_id`, or the caller's
                      personal org when omitted).
                  claimed_at:
                    type: string
                    format: date-time
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
      security:
        - BearerAuth: []
        - ApiKeyAuth: []
        - CookieAuth: []
components:
  parameters:
    AgentId:
      name: agent_id
      in: path
      required: true
      schema:
        type: string
      description: Agent identifier (e.g. smolt-abc123)
  responses:
    BadRequest:
      description: Bad request
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Unauthorized:
      description: Authentication required
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Forbidden:
      description: Forbidden
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    NotFound:
      description: Resource not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    TooManyRequests:
      description: >-
        Rate-limit exceeded. The global per-IP limiter (100 requests/minute,
        applied to every `/v1/*` route) rejected this request. Back off until
        the window resets — `Retry-After` carries the cooldown in seconds and
        `X-RateLimit-Reset` the absolute reset time.
      headers:
        Retry-After:
          description: Seconds to wait before retrying.
          schema:
            type: integer
            minimum: 1
        X-RateLimit-Limit:
          description: Requests permitted per window.
          schema:
            type: integer
        X-RateLimit-Remaining:
          description: Requests remaining in the current window (0 on a 429).
          schema:
            type: integer
            minimum: 0
        X-RateLimit-Reset:
          description: Unix epoch seconds at which the current window resets.
          schema:
            type: integer
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    InternalServerError:
      description: >-
        Server error — request was well-formed but the server failed to fulfill
        it. Typically a downstream dependency (DB / RPC / external API) returned
        an unexpected error.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    ServiceUnavailable:
      description: >-
        An upstream dependency is currently unavailable. The request was not
        processed; retry after the cooldown window.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  schemas:
    Error:
      type: object
      description: >-
        Canonical error envelope (ADR-API-001 conv 1). `error` is always an
        object — never a bare string. Every 4xx/5xx response across the API
        conforms to this shape; the runtime helper is
        `src/http-errors.ts::buildErrorBody`.
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              pattern: ^[a-z][a-z0-9_]*$
              description: >-
                Stable, machine-matchable failure identifier (lowercase
                snake_case). Clients may branch on this; the string is part of
                the contract.


                **Status-class defaults** — emitted when no caller code is
                supplied (`errorCodeForStatus(status)`): `bad_request` (400),
                `unauthorized` (401), `forbidden` (403), `not_found` (404),
                `method_not_allowed` (405), `conflict` (409), `gone` (410),
                `precondition_failed` (412), `payload_too_large` (413),
                `unsupported_media_type` (415), `unprocessable_entity` (422),
                `precondition_required` (428), `rate_limited` (429),
                `internal_error` (500), `not_implemented` (501), `bad_gateway`
                (502), `service_unavailable` (503), `gateway_timeout` (504).
                Fallback `error` for unmapped statuses.


                **Caller-supplied codes** — handlers may pass an explicit `code`
                for a specific failure class. Examples: `agent_not_found`,
                `invalid_hash_proof`, `already_linked`, `idempotency_conflict`,
                `feature_gated`, `schema_validation_failed`, `no_token`,
                `bad_canonical_payload`.


                **Care-framed sub-resource codes** — the cards-as-primitive
                surface passes its stable care code-string straight through as
                `error.code`. Examples: `if_match_absent`, `if_match_stale`,
                `if_match_malformed`, `primitive_validation_failed`.
            message:
              type: string
              description: Human-readable, care-framed explanation of the failure.
            details:
              description: >-
                Optional structured context for the failure (any JSON value:
                object, array, or primitive). Common shapes: validation findings
                list, idempotency-conflict diff, `{presented_etag,
                current_etag}` on a stale `If-Match`, etc. Mirrors the helper's
                `details?: unknown`.
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: 'Supabase JWT token in Authorization: Bearer header'
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-Mnemom-Api-Key
      description: Mnemom API key (mnm_... format)
    CookieAuth:
      type: apiKey
      in: cookie
      name: mnemom_session
      description: >-
        HttpOnly, Secure, SameSite=Lax cookie issued by /v1/auth/sign-in (or the
        SSO / email-callback flows). The value is an AES-256-GCM-encrypted blob
        of {access_token, refresh_token, issued_at, auth_method}. Browser
        clients include this automatically with `credentials: "include"`.

````