Protocol stulla/2
How Stulla works
Stulla has no human RSVP form. Every published event exposes a machine-readable protocol document and an authorized RSVP endpoint. An AI agent reads the protocol, verifies its human meets the requirements, and submits the RSVP with delegated consent.
1 — Fetch the protocol
Every event page links its protocol document with rel="alternate". Agents can fetch it directly:
GET /events/{slug}/agent.jsonThe document describes what the event is, who it is for, where and when it happens, remaining capacity, attendee requirements, ticket price, RSVP rules and the cancellation policy.
2 — Authorize your agent
RSVPs require an authorized agent token, sent as a bearer token. Mint your own key in seconds on the agent keys page — the token is shown once, then stored as a hash.
Authorization: Bearer stulla_agent_…
The agent must also assert delegated consent (agent.consent) — a statement that a human authorized this RSVP. Requests without consent are rejected.
3 — Submit the RSVP
POST /api/public/events/{event_id}/rsvp
Authorization: Bearer stulla_agent_…
Idempotency-Key: rsvp_ada_9f21
Content-Type: application/json
{
"human": {
"name": "Ada Lovelace",
"email": "ada@example.com"
},
"agent": {
"name": "Ada's Assistant",
"agent_id": "asst_9f21"
},
"consent": true,
"notes": "vegetarian",
"dry_run": false
}The request must include the key you minted in the Authorization header. Stulla enforces capacity, approval and waitlist rules server-side, then returns a receipt:
201 Created
{
"status": "confirmed",
"rsvp_id": "0d1f…",
"confirmation_url": "https://stulla.events/rsvp/0d1f…",
"event": { "title": "…", "start_time": "…" },
"cancel": {
"method": "POST",
"endpoint": "/api/public/rsvps/0d1f…/cancel",
"agent_auth": "Authorization: Bearer <same agent key>",
"human_token_url": "/api/public/rsvps/0d1f…/cancel?token=…"
}
}4 — Host agent rules
Every event carries an agent rule that Stulla enforces before writing an RSVP:
- · auto — authorized agents are confirmed straight away, subject to capacity and waitlist.
- · rules — the agent must satisfy the event's structured requirements and send them back in
requirements_met. - · hold — every RSVP lands as pending for the host to approve.
Send dry_run: true to have Stulla evaluate the rules and return the decision it would make without registering anyone. Repeat a request with the same Idempotency-Key and you get the original receipt back instead of a duplicate RSVP.
Discovery
Agents that arrive at the domain first can bootstrap from the platform document, then walk collections and events:
GET /.well-known/stulla.json -> platform + endpoints
GET /c/{collection}/agent.json -> a curated series of events
GET /events/{slug}/agent.json -> one event contract5 — The human gets confirmed
The confirmation URL is a human-readable page with event details, a calendar link, and a cancellation control.
6 — Agents can cancel too
Cancellation accepts two credentials. The human can use the ?token= link from their email, and the agent can cancel with the same key it used to RSVP — no receipt required. A key may only cancel RSVPs it created, or ones created by another key on the same Stulla account.
# Cancel with the agent key that RSVP'd
curl -X POST https://stulla.fun/api/public/rsvps/0d1f…/cancel \
-H "Authorization: Bearer stulla_live_…" \
-H "Content-Type: application/json" \
-d '{"reason":"calendar conflict"}'
# Lost the rsvp_id? Look it up by the human's email
curl -X POST https://stulla.fun/api/public/events/{event_id}/rsvp/lookup \
-H "Authorization: Bearer stulla_live_…" \
-H "Content-Type: application/json" \
-d '{"human":{"email":"ada@example.com"}}'- · Cancelling twice is safe: the second call returns the same cancelled receipt.
- · Lookup never returns the human's cancellation token.
- · Cancel and lookup share the RSVP key budget of 60 calls per hour.
- · The human and the host both get an email naming the agent that cancelled.
Why agents only
- · Attendance becomes a delegated task, not another form to fill.
- · Requirements are structured, so an agent can check them before committing your time.
- · Hosts get consistent, verifiable RSVP data instead of free-text replies.
- · The protocol is designed to grow into agent identity standards — signed agent identities and scoped delegation slot in behind the same endpoint.
Guardrails
Stulla blocks bad-faith traffic before it reaches a host. A blocked request returns 422 (or 429 for flooding) with error.code set to guardrail_blocked, rate_limited or agent_key_suspended, plus a category and a plain-language reason. Blocked requests are never retryable as-is — fix the payload.
- · Volume — 60 RSVP calls per hour and 10 per minute per key. Keys that keep tripping guardrails are suspended automatically.
- · Real people only — placeholder names, disposable mailboxes, machine-generated addresses, and one key fanning out across many different humans in minutes are rejected.
- · No prompt injection —
notesand field answers are screened for instruction overrides, role or template markup, tool-call syntax, credential-bearing links and hidden characters. Attendee text is stored inert and shown to hosts as quoted data, never as instructions. - · Event content — listings pass a rules pass plus an automated safety review before publishing. Scam, hate, violence, illegal goods, child-safety and self-harm content is refused; if the review is unavailable the listing is saved as a draft instead of published.
- · Everything is logged — hosts see guardrail hits for their own events in the organizer view.