# pollicms

> A private relationship keeper: track how often you want to see the people you care about, log meetups, get a weekly nudge when someone slips, and schedule meetings that fit everyone's calendar. Every page action is also a JSON REST API call.

## How to operate this site

- Signed in as the person whose browser this is: call the API from a page of this site with fetch(url, { credentials: "same-origin" }). The session cookie is the credential.
- Send JSON: `content-type: application/json` on every POST, PUT, PATCH and DELETE that has a body. Cross-site writes are refused.
- Times in responses are epoch milliseconds (UTC). Input times take epoch milliseconds or ISO 8601 with an offset.
- Errors: `{ "error": { "code", "message", "issues"? } }` with 400 (input), 403, 404 (missing or not yours), 409 (duplicate), 429 (rate limit).
- Invitations, meetings, connection requests and group invites send real email to real people. Confirm with the human before you send them, and before you delete anything.
- Prefer the API over clicking: read with GET, change with the listed calls, then reload the page so the human sees the result.
- Not signed in (401)? Ask the human to sign in at /sign-in. The API has no sign-in call.

Example, from the browser console of any page of this site:

```js
const people = await (await fetch("/api/v1/people")).json();
await fetch("/api/v1/interactions", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ date: "2026-10-18", channel: "in_person", people: [{ personId: people[0].personId, mood: 4 }], note: "Her new job at the museum.", promisedByMe: "Send her the photographer's number." }) });
```

## API

- [OpenAPI 3.1 spec](https://pollicms.serve.beshu.tech/api/v1/openapi.json): every operation with its JSON input schema

### Account

- `GET /api/v1/me`: Who is signed in, unread notifications, and whether setup is still open
- `GET /api/v1/home`: The home dashboard: who is due, meetups to rate, connection requests, merge suggestions
- `POST /api/v1/setup/finish`: Close the first-run setup wizard
- `GET /api/v1/export`: Everything stored about you, as JSON
- `DELETE /api/v1/me`: Delete your account for good

### Connections

- `GET /api/v1/connections/requests`: Connection requests sent to you and by you
- `POST /api/v1/connections/requests`: Ask someone to connect, by email (emails them when they have no account)
- `POST /api/v1/connections/requests/{requestId}/respond`: Accept or decline a connection request
- `DELETE /api/v1/people/{personId}/connection`: Remove the connection with an account person
- `GET /api/v1/blocks`: Accounts you blocked
- `POST /api/v1/blocks`: Block an account (ends the connection, hides their invitations)
- `DELETE /api/v1/blocks/{userId}`: Unblock an account
- `PUT /api/v1/mutes/{userId}`: Mute or unmute an account

### Notifications

- `GET /api/v1/notifications`: Your notifications, newest first, 50 per page
- `POST /api/v1/notifications/read`: Mark notifications as read

### Settings

- `GET /api/v1/settings`: Your preferences and weekly hours
- `PATCH /api/v1/settings`: Change any preferences; fields you leave out keep their value
- `POST /api/v1/settings/guest-history`: Add (or not) the meetings you were invited to as a guest before you had an account

### Calendars

- `GET /api/v1/calendars`: Connected calendar accounts and their calendars
- `POST /api/v1/calendars/ics`: Connect a calendar by its ICS or webcal link (busy times only)
- `PUT /api/v1/calendars/{calendarId}/busy`: Count (or stop counting) one calendar's events as busy
- `PUT /api/v1/calendars/{calendarId}/destination`: Put meetings and reminders in this calendar
- `DELETE /api/v1/calendar-accounts/{accountId}`: Disconnect a calendar account and all its calendars

### People

- `GET /api/v1/people`: List everyone you keep track of
- `POST /api/v1/people`: Add a private contact
- `POST /api/v1/people/bulk`: Add up to 200 private contacts at once (all or none)
- `GET /api/v1/people/merge-candidates`: Private contacts that look like the same person as a connection
- `GET /api/v1/people/{personId}`: One person: summary, how you met, what they are like, details, recent meetups with notes, tags, mute and block state
- `PATCH /api/v1/people/{personId}`: Change label, notes or cadence
- `DELETE /api/v1/people/{personId}`: Delete a private contact and everything private about them
- `PUT /api/v1/people/{personId}/identity`: Rename a private contact or change their email
- `PUT /api/v1/people/{personId}/about`: Relationship, birthday, how you met, what they are like, contact details and shared interests
- `POST /api/v1/people/{personId}/snooze`: Pause nudges about a person for some days (0 ends the snooze)
- `POST /api/v1/people/{personId}/check-in`: Answer the cadence check-in: keep it, change it, or stop tracking
- `POST /api/v1/people/{personId}/merge`: Merge a private contact into another person (see /people/merge-candidates)

### Tags

- `GET /api/v1/tags`: Your tags, each with the people who carry it
- `POST /api/v1/tags`: Put a tag (new or existing) on people
- `PATCH /api/v1/tags/{tagId}`: Rename a tag (merges into a tag that already has the new name)
- `DELETE /api/v1/tags/{tagId}`: Delete a tag (people stay)
- `POST /api/v1/people/{personId}/tags`: Tag one person
- `DELETE /api/v1/people/{personId}/tags/{tagId}`: Take a tag off one person

### Meetups

- `GET /api/v1/interactions/prompts`: Recent meetups waiting for a rating (newest first, at most 5)
- `GET /api/v1/interactions`: Your meetups with their notes, newest first; optionally only those with one person
- `GET /api/v1/interactions/{interactionId}`: One meetup with all your notes
- `POST /api/v1/interactions`: Log a meetup ("I met…") with your notes
- `PATCH /api/v1/interactions/{interactionId}`: Change the notes, channel, ratings or (for meetups you logged) the date of a meetup
- `POST /api/v1/interactions/{interactionId}/rating`: Rate a meetup (null skips the rating and closes the prompt)
- `POST /api/v1/interactions/{interactionId}/people/{personId}/mood`: Set how one person in a meetup seemed to you (their mood)
- `POST /api/v1/interactions/{interactionId}/people/{personId}/rating`: How it felt for you with this person (legacy; prefer mood and eventAffect)
- `DELETE /api/v1/interactions/{interactionId}`: Delete a meetup and its notes ("I did not go")

### Meetings

- `GET /api/v1/meetings`: Meetings you organize or were invited to, soonest first
- `POST /api/v1/meetings`: Create a meeting and invite people, groups or email addresses
- `GET /api/v1/meetings/{meetingId}`: One meeting: details, the participants you may see, dates, open poll and your RSVPs
- `PATCH /api/v1/meetings/{meetingId}`: Organizer: change title, description, place or length for the whole meeting
- `GET /api/v1/meetings/{meetingId}/times`: Organizer: free times for everyone who shares availability
- `POST /api/v1/meetings/{meetingId}/confirm`: Organizer: confirm the start time (sends the confirmation and calendar invites)
- `POST /api/v1/meetings/{meetingId}/poll`: Organizer: let invitees vote on 2 to 4 start times
- `POST /api/v1/meetings/{meetingId}/cancel`: Organizer: cancel the whole meeting (tells everyone)
- `POST /api/v1/meetings/{meetingId}/respond`: Invitee: accept or decline
- `POST /api/v1/meetings/{meetingId}/rsvp`: Participant: RSVP to one date of a meeting
- `POST /api/v1/occurrences/{occurrenceId}/move`: Organizer: move one date
- `POST /api/v1/occurrences/{occurrenceId}/split`: Organizer: move this date and every later one of a series
- `POST /api/v1/occurrences/{occurrenceId}/cancel`: Organizer: cancel one date

### Groups

- `POST /api/v1/meetings/{meetingId}/join`: Group member: opt in to a group meeting series
- `GET /api/v1/groups`: Groups you belong to or asked to join
- `POST /api/v1/groups`: Create a group (you become its owner)
- `GET /api/v1/groups/{slug}`: One group by slug: members and meetings when you are an active member, else the join view
- `POST /api/v1/groups/{groupId}/join`: Join (open group) or ask to join (request group)
- `POST /api/v1/groups/{groupId}/leave`: Leave a group (the last member leaving deletes it)
- `PUT /api/v1/groups/{groupId}/subscription`: Get or stop emails about new group meetings
- `POST /api/v1/groups/{groupId}/members/{userId}/approve`: Admin: approve a join request
- `POST /api/v1/groups/{groupId}/invitations`: Admin: invite someone by email
- `POST /api/v1/group-invitations/{token}/accept`: Accept a group invitation (the token is the last part of the /g/<token> link)
- `POST /api/v1/groups/{groupId}/meetings`: Admin: start a group meeting series (members opt in)

## Pages

- [/](https://pollicms.serve.beshu.tech/): Home: who is due for a meetup, meetups to rate, connection requests
- [/people](https://pollicms.serve.beshu.tech/people): Everyone you keep track of; search and filter by tag
- [/people/new](https://pollicms.serve.beshu.tech/people/new): Add a person or send a connection request
- [/people/{personId}](https://pollicms.serve.beshu.tech/people/): One person: cadence, notes, birthday, how you met, what they are like, shared interests, contact details, tags, recent meetups
- [/people/{personId}/meetups](https://pollicms.serve.beshu.tech/people/): Every meetup with one person, newest first, with your notes
- [/log](https://pollicms.serve.beshu.tech/log): Log a meetup ("I met…")
- [/meetups/{interactionId}](https://pollicms.serve.beshu.tech/meetups/): One meetup: read and edit what you talked about, plans, decisions, promises and moods; delete it
- [/meetings](https://pollicms.serve.beshu.tech/meetings): Your meetings and calendar
- [/meetings/new](https://pollicms.serve.beshu.tech/meetings/new): Find a time: create a meeting and invite people
- [/meetings/{meetingId}](https://pollicms.serve.beshu.tech/meetings/): One meeting: respond, confirm a time, poll, RSVP, move or cancel dates
- [/groups](https://pollicms.serve.beshu.tech/groups): Your groups
- [/groups/{slug}](https://pollicms.serve.beshu.tech/groups/): One group: members, meetings, invitations
- [/notifications](https://pollicms.serve.beshu.tech/notifications): Notifications
- [/settings](https://pollicms.serve.beshu.tech/settings): Name, time zone, weekly hours, nudges, calendars, blocked accounts, export, delete account
- [/setup](https://pollicms.serve.beshu.tech/setup): First-run setup wizard

## Optional

- [Manifesto](https://pollicms.serve.beshu.tech/manifesto): why the product exists
- [Insights](https://pollicms.serve.beshu.tech/insights): articles
