---
title: "Self-enroll an agent"
method: POST
path: "/v1/agents/enroll"
tags: ["Agents"]
---

# Self-enroll an agent

`POST /v1/agents/enroll`

## Request

- Base URL: `https://api.1claw.co`
- URL: `https://api.1claw.co/v1/agents/enroll`
- Auth: HTTP bearer

Public endpoint (no auth required).

**With `human_email`:** Creates a pending enrollment for that account's org,
emails Allow/Deny links, and returns `approval_url` in the JSON body (use if email
is delayed). The API key is NOT returned until the human approves.

**Name only (omit `human_email`):** Creates a link-only pending enrollment.
The response includes `approval_url`; the human opens it while signed in to
approve the agent into their org.

Anti-spam: IP rate limiting, per-email cooldown, caps on pending rows.

## Request body

- EnrollAgentRequest
  - `name` string, required: Display name for the new agent
  - `human_email` string, email: Optional. If set, pending enrollment is bound to that 1Claw account email and Allow/Deny links are emailed. If omitted, only `approval_url` is used (link-only enrollment; human must open the URL while signed in).
  - `description` string: Optional agent description
  - `public_key` string: Pairing ceremony. The agent's own Ed25519 public key (`ssh-ed25519 AAAA…` or base64 of the raw 32 bytes). Its `SHA256:` fingerprint is shown to the human on the approval page for visual verification, and the agent collects its API key itself by polling `GET /v1/agents/enroll/{pairing_id}/status?poll=<poll_token>` — no key in an email, nothing to copy. `1claw agent enroll --pair` does all of this.

## Response `201`

Enrollment processed (uniform response to prevent email enumeration)

- EnrollAgentResponse
  - `agent_id` string, uuid: UUID of the created agent (nil UUID until approved — uniform response)
  - `message` string: Status message (worded to limit email enumeration where applicable)
  - `approval_url` string, uri: Present when a pending enrollment was created and the client should show this link (email flow includes it as a fallback; name-only flow requires it).
  - `pairing_id` string, uuid: Pairing only.
  - `fingerprint` string: Pairing only. `SHA256:<base64>` of the key, as `ssh-keygen -lf` prints it. Show it to the human.
  - `poll_token` string: Pairing only. Presented as `?poll=` on the status endpoint. Shown once.
  - `expires_at` string, date-time

## Other responses

- `429`: Rate limit exceeded

---

[API](https://skmtc.dev/1claw/apis/1claw-api.md) · [All operations](https://skmtc.dev/1claw/apis/1claw-api/llms.txt) · [OpenAPI document](https://skmtc.dev/1claw/apis/1claw-api/revisions/ae109b496830?raw)
