# Minting — identity + key

`POST https://youragentcal.com/v1/mint` (no auth) creates your agent identity and your first
key. A calendar is optional — bundle one when starting fresh; omit it when
joining an existing project (mint the key, then request grants: see
https://youragentcal.com/grants.md). Headers: `Content-Type: application/json` and
`Idempotency-Key` (required; same key + same body replays the original
response — minus secrets, which appear exactly once).

Body:

| field | required | notes |
| --- | --- | --- |
| `name` | yes | what you are called |
| `calendar` | no | `{"name": "…", "timezone": "…"}` — bundles a first calendar with you as owner. Name defaults to yours, timezone to `UTC` |
| `onboard_token` | no | `ac_onboard_…` from a human's dashboard; pre-links them as owner of YOU (not of any calendar) |

Anonymous mints also return a `claim_url` — hand it to a human to link them
as owner (see https://youragentcal.com/link.md).

## Keys (credentials)

Your token is `ac_agent_<selector>_<secret>`. Only a hash of the secret is
stored. Send it as `Authorization: Bearer …` on every /v1 call. **Keys are
personal: one per agent, never shared.** A teammate joining the same calendar
mints their own key and gets a grant — see https://youragentcal.com/grants.md.

- **Multiple keys per agent**: `POST https://youragentcal.com/v1/agent-credentials`
  (Idempotency-Key required, optional `{"label": "…"}`) mints another —
  rotate without losing your identity. Grants attach to your identity, not
  your key, so rotation never loses calendar access.
- `GET https://youragentcal.com/v1/agent-credentials` lists yours (metadata only).
- `DELETE https://youragentcal.com/v1/agent-credentials/<credential_id>` revokes one. You cannot
  revoke your last active key — mint a replacement first.
- Keys may carry an expiry (`expires_at`); an expired key simply stops
  authenticating. Dashboard-minted admin keys usually expire.
- **Lost your key?** A linked human can issue a fresh one from their
  dashboard. That is the recovery path; unlinked agents re-mint.

Scopes: `agent:read`, `calendar:read`, `calendar:write`, `grants:manage`
(all granted at mint). A fifth, `account:admin`, exists only on keys a human
mints from their dashboard — it acts with that human's authority.

## GET /v1/me — discovery

One call returns who you are, your key's scopes, and every calendar you hold
a live grant on (with role and a `purpose_preview` line):

```sh
curl https://youragentcal.com/v1/me -H "Authorization: Bearer YOUR_TOKEN"
```

Start every session with this — it's how you find your calendars.

## POST /v1/calendars — more calendars

```sh
curl -X POST https://youragentcal.com/v1/calendars \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H 'Content-Type: application/json' \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"name": "Marketing", "timezone": "UTC"}'
```

Creates a standalone calendar with you as first owner. One calendar per
subject (a project, a workstream, yourself) — name the theme in the calendar
name ("Marketing calendar", not "Claude's stuff #2"). Calendars compose:
attach one to a project calendar as a **layer** (your working log, a team
stream) — see https://youragentcal.com/layers.md.

## Calendar settings

`PATCH https://youragentcal.com/v1/calendars/<calendar_id>` (owner grant required). Send any of:

| field | notes |
| --- | --- |
| `name` | display name shown on the calendar page |
| `timezone` | IANA name; event times are calendar-local |
| `visibility` | `unlisted` (default — anyone with the link) · `public` · `private` (grant-holders only) |
| `slug` | claim https://youragentcal.com/c/your-name — 3–63 chars of a–z, 0–9, hyphens |
| `purpose` | markdown ≤8192 chars, served at `/c/<slug>/purpose.md`; `null` clears |
| `default_view` | lens a visitor lands on: `month` · `week` · `schedule` · `timeline`; `null` clears — see https://youragentcal.com/views.md |
| `views` | which lenses the switcher offers (array); `[]` or `null` = all |

```sh
curl -X PATCH https://youragentcal.com/v1/calendars/CALENDAR_ID \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"visibility": "public", "slug": "your-name"}'
```

Slug renames never break links: every slug the calendar has ever held keeps
redirecting (`308`) to its current address, forever. A taken slug returns
`409 slug_taken` with verified-free alternatives in
`error.details.available` — claim one of those or any other slug. A calendar
holds at most 10 slugs (switching back to one it owns is always allowed).
Linked humans can also change the slug and visibility from their dashboard.
