Trips API
A public HTML pastebin for trip itineraries at /trips. Mounted at /api/trips. Wire fields are camelCase.
Trips
| Method | Path | Auth | Body | Notes |
|---|---|---|---|---|
| POST | / | optional (anonymous OK) | JSON {html (1..10MB), title?, filename?} OR multipart file (.html, 10MB) + title? | 201 {trip:{id, slug, title, ...}}; authed upload stamps ownerId, anonymous is ownerless |
| GET | / | public | ?limit=1..100&cursor=<createdAt ISO> | metadata only, no html |
| GET | /:slug | public | none | full row including html |
| PATCH | /:slug | optional + trips:write (PATs) | any of html/title/filename, or multipart | 403 if owned by someone else; anonymous trips are editable by anyone; slug never changes |
| DELETE | /:slug | optional + trips:write (PATs) | none | 204; same ownership rule |
Gotchas:
- Title precedence on create: body title, then the html
<title>tag, then first h1, then cleaned filename. trips:writeonly gates PATs; browser JWTs and anonymous callers pass the scope check. The real protection is per-trip ownership.- Slug is kebab-cased from the title (max 60 chars) with a random suffix on collision.
- No rate limiting on this module. Cursor is a createdAt timestamp, unlike the journal's date cursor.
Trip Groups (/api/trip-groups)
Group trip planning. Everything requires a browser session (requireAuth; no PAT scope exists for this module), except raw photo bytes which are public. Membership is join-by-slug: POST /:slug/join.
Highlights (all under /api/trip-groups/:slug unless noted):
POST /api/trip-groups{title}: create, caller becomes owner.GET /api/trip-groups: your groups.- Ideas:
POST /ideas{body}(1..4000), delete is author-only. POST /itinerary/consolidate: LLM call turning ideas into a structured itinerary. Owner writes directly (200); a non-owner member creates a pending suggestion (201). 502 when LLM providers are down.PUT /itinerary: manual structured edit (same owner/member fork).DELETE /itinerary: owner-only reset.- Suggestions:
GET /itinerary/suggestions(with conflict detection), owner-only approve/reject, race-safe 409 when already resolved. - Photos: multipart upload per day (5MB, sniffed types), public raw bytes at
.../photos/:photoId/raw, owner-onlyunsplash-fill. - Notes and todo sections: member CRUD with creator-or-owner deletes.
POST /itinerary/export-calendar: exports to the CALLER's Google Calendar; 409calendar_not_connecteduntil they connect.
Agents without a browser session cannot use trip-groups; use the plain trips API instead.