# Views — lenses and share views

Two different things called "view":

1. **Lenses** — how a calendar page renders: `month`, `week`, `schedule`,
   `timeline`. Same events, different shapes.
2. **Share views** — scoped, shareable projections of a calendar at their own
   URL. The audience sees ONLY the events the view's filter passes; filtering
   runs server-side, so nothing outside the scope ever reaches their client.

## Lenses (presentation settings)

On any calendar you own (`PATCH https://youragentcal.com/v1/calendars/<id>`):

| field | meaning |
| --- | --- |
| `default_view` | the lens a visitor lands on (`?view=` in the URL still wins) |
| `views` | which lenses the switcher offers; one entry hides the switcher entirely; `[]` 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 '{"default_view": "timeline", "views": ["timeline", "month"]}'
```

## Share views

A share view = a filter + a display config + its own URL under `/v/`.
Owner role + `calendar:write` scope required. The share page and its JSON
never reveal the parent calendar: no name, no slug, no ids, no agent, no
purpose doc. It keeps serving even if you make the calendar `private` —
the view URL is exactly what you chose to hand out, revocable on its own.

**Slugs are the access model.** Omit `slug` and you get an unguessable
address (`/v/3f9a1c04be7d`) — a capability for a specific audience. Set a
custom `slug` and the view becomes a broadcast face (`/v/chatroyale`) —
the memorable link you publish while the raw calendar stays your back office.
Slugs are immutable; deleting the view kills the URL.

```sh
curl -X POST https://youragentcal.com/v1/calendars/CALENDAR_ID/views \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H 'Content-Type: application/json' \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"name": "Client milestones",
       "filter": {"categories": ["milestone", "release"], "include_someday": true},
       "display": {"default_view": "timeline", "views": ["timeline"]}}'
```

Returns the view with its `url`. Routes:

```text
POST   https://youragentcal.com/v1/calendars/<id>/views              create (Idempotency-Key; optional custom "slug")
GET    https://youragentcal.com/v1/calendars/<id>/views              list yours (incl. revoked)
PATCH  https://youragentcal.com/v1/calendars/<id>/views/<view_id>    update name/filter/display (filter and display replace whole)
DELETE https://youragentcal.com/v1/calendars/<id>/views/<view_id>    revoke — the URL 404s from then on
```

## Filter semantics

| field | default | behavior |
| --- | --- | --- |
| `layers` | absent = `["main"]` | which layers to compose (https://youragentcal.com/layers.md): `"main"` is the calendar's own events, other entries are attached layers' keys. Unknown keys → `400 unknown_layer`. Events arrive tagged with their `layer`; a layer detached later goes quiet, a layer turned private drops out |
| `categories` | absent = all | only events whose `category` is in the list; uncategorized events are excluded when set |
| `from` / `to` | absent | `YYYY-MM-DD` inclusive range for dated events |
| `include_recurring` | `true` | recurring events pass regardless of range |
| `include_someday` | `false` | dateless "someday" events |

A composed status page — project milestones plus two teams' streams, one URL:

```sh
curl -X POST https://youragentcal.com/v1/calendars/CALENDAR_ID/views \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H 'Content-Type: application/json' \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"name": "Acme status",
       "filter": {"layers": ["main", "engineering", "marketing"], "categories": ["milestone", "release"]},
       "display": {"default_view": "timeline"}}'
```

The share page never reveals the layers' calendars — visitors see only the
keys you chose. `view = layers × filters × display`.

The audience reads a view like a calendar: `/v/<slug>` is live HTML for
browsers and JSON with `Accept: application/json` — same shape as a
calendar read, minus anything that identifies the parent.

## Which sharing tool when

- Another **agent** should read or write the calendar itself → a **grant**
  (https://youragentcal.com/grants.md).
- A **human audience** should see a slice → a **share view**.
