Core Resources
View as Markdown

Meeting

A recurring session — Ops Core, Partner Core — with members, a schedule, and an agenda that builds itself from the decisions and informs queued for it.

A meeting is a recurring session the organisation actually holds. It carries three things: a purpose (what belongs here and what does not), members with roles, and an agenda — which nobody assembles by hand. Queue a decision or an inform for a meeting and it appears on that meeting's next sitting.

Scheduling is week-precise, deliberately. A meeting has a cadence (WEEKLY or BIWEEKLY) and a day, and timeLabel is display-only text like "Tue 3:00 PM ET" — it is never parsed. Real meetings move by a day or an hour and nobody re-files the calendar; committing to more precision than that would be committing to a lie. A bi-weekly meeting also needs an anchorDate — any date it actually sits — which is what tells the server which fortnight is the on week.

Members mirror Spaces and User Groups, on purpose: one vocabulary for "a named thing with people in it". A member is an OWNER (may edit the meeting and its roster) or a PARTICIPANT (in the room). There is no editor rung — there is nothing between running a meeting and attending it. A meeting always keeps at least one owner: demoting or removing the last one is refused, because a meeting with no owner has nobody who can appoint one.

The agenda is access-filtered per topic. Everyone in the beta can see that a meeting exists and who is on it; the topics on its agenda are each checked against your Droplet access, so you see only what you could already read. Adding a @group to the roster expands it to that group's members at that moment — the roster does not follow the group afterwards.

What you can do:

  • list / retrieve — the inventory, and one meeting with its agenda: what is on deck for the next sitting, what closed since the last one, and what is queued further out. Pass includeArchived to list to find archived meetings.
  • create / update — people admins create and edit; archive / restore take a meeting out of the listing without severing anything, so restoring brings the agenda back as it was.
  • members — list-attendees, add-attendees (people and/or @group slugs), remove-attendee, set-member-role.
  • set-topic / get-topic — queue a Droplet onto a meeting's agenda, or ask which meeting it is queued for. Queuing is a property of the TOPIC, so you do not need to own the meeting to put your own item on it.

Queuing writes App.meetingId, a real relationship rather than a field value — which is why archiving a meeting keeps its topics linked, and deleting one would clear the link rather than orphan it.

The Meeting object

Every Meeting carries these attributes.

Attributes

slug
string
Stable URL identifier, e.g. ops-core. Set at creation and never auto-derived afterwards, so links keep working.
name
string
Display name, e.g. "Ops Core".
description
string· nullable
The PURPOSE — what belongs at this meeting and what does not. This is the field that answers "does my topic go here or somewhere else".
cadence
string
WEEKLYBIWEEKLY
How often it sits.
dayOfWeek
int
ISO-8601 weekday: 1 = Monday … 7 = Sunday.
timeLabel
string· nullable
Display-only, e.g. "Tue 3:00 PM ET". NOT parsed — the schedule's precision is the week.
scheduleLabel
string
Human rendering of cadence + day, e.g. "Tuesdays, every two weeks".
nextWeekLabel
string
When it next sits, relative: "this week", "next week", or "week of 15 Sep".
nextWeekStart
string
ISO date of the Monday starting the next occurrence's week. The machine-readable counterpart to nextWeekLabel.
ownerName
string· nullable
Display name of the creating owner. Permission follows member roles, not this field.
attendeeCount
int
How many members the meeting has.
space
json· nullable
The Space carrying this meeting's content, when one is linked: { name, slug }.
queuedCount
int
Unclosed topics dated on or before the next occurrence — what is ON DECK.
laterCount
int
Unclosed topics dated beyond the next occurrence. Counted separately so something scheduled ahead is never invisible and never inflates this week.
More attributes+ Show 1
archivedAt
string· nullable
Set once archived. Only returned when includeArchived was requested; without it, archived meetings are absent entirely.
THE MEETING OBJECT
{
  "slug": "ops-core",
  "name": "Ops Core",
  "description": "Operations Core. Overlaps Partner Core on Tuesday afternoons — confirm alternating weeks.",
  "archivedAt": null,
  "cadence": "BIWEEKLY",
  "dayOfWeek": 2,
  "timeLabel": "Tue 3:00 PM ET",
  "scheduleLabel": "Tuesdays, every two weeks",
  "nextWeekLabel": "next week",
  "nextWeekStart": "2026-09-01",
  "ownerName": "Aurea Nunes",
  "attendeeCount": 6,
  "space": {
    "name": "Operations",
    "slug": "operations"
  },
  "queuedCount": 3,
  "laterCount": 1
}

Methods

Endpoints to operate on a Meeting. The example switches between curl, drop CLI, and MCP via the dropdown — your choice persists across the page.

GET

Which meeting is a topic queued for

/api/apps/{slug}/meeting

The meeting a Droplet is queued for, or null. Exists because the picker has to render its CURRENT value: without it the control always read "No meeting" even on a topic that had one, so setting a meeting looked like it had not saved.

GET/api/apps/{slug}/meeting
drop topics get-meeting ops-inform-infra
Response200
{
  "slug": "example",
  "meeting": "example"
}
GET

List meetings

/api/meetings

Every recurring meeting, with its cadence, when it next sits, and how many topics are queued for it. The answer to "what is coming up and where".

GET/api/meetings
drop meetings list
Response200
{
  "items": []
}
GET

Get a meeting and its agenda

/api/meetings/{slug}

A meeting with its generated agenda. The agenda is NOT stored — it is the unclosed topics pointing at this meeting, so it can never drift from their real state the way a written one does. Scoped to the caller: you only see topics you can read.

GET/api/meetings/{slug}
drop meetings get ops-core
Response200
{
  "slug": "example",
  "archivedAt": "example",
  "name": "example",
  "description": "example",
  "cadence": "WEEKLY",
  "dayOfWeek": 0,
  "timeLabel": "example",
  "scheduleLabel": "example",
  "nextWeekLabel": "example",
  "nextWeekStart": "example",
  "ownerName": "example",
  "attendeeCount": 0,
  "space": {
    "name": "example",
    "slug": "example"
  },
  "queuedCount": 0,
  "laterCount": 0,
  "canManage": false,
  "anchorDate": "example",
  "attendees": [],
  "onDeck": [],
  "recentlyClosed": [],
  "later": []
}
POST

Queue a topic for a meeting

/api/apps/{slug}/meeting

Put a decision or an inform on a meeting's agenda, or take it off. Editor-gated. Optional by design — a decision made without a room is still a decision.

POST/api/apps/{slug}/meeting
drop topics set-meeting ops-inform-infra --meeting ops-core
Response200
{
  "slug": "example",
  "meeting": "example"
}
POST

Create a meeting

/api/meetings

Define a recurring meeting. People-admin gated, because a meeting is org structure rather than personal content. Cadence is WEEKLY or BIWEEKLY plus a day; bi-weekly needs an anchorDate to establish which fortnight is the on week, and without one it falls back to weekly rather than guessing.

POST/api/meetings
drop meetings create --name "Ops Core" --slug ops-core --cadence BIWEEKLY --day-of-week 2 --time-label "Tue 3:00 PM ET" --anchor-date 2026-08-31
Response201
{
  "slug": "example",
  "archivedAt": "example",
  "name": "example",
  "description": "example",
  "cadence": "WEEKLY",
  "dayOfWeek": 0,
  "timeLabel": "example",
  "scheduleLabel": "example",
  "nextWeekLabel": "example",
  "nextWeekStart": "example",
  "ownerName": "example",
  "attendeeCount": 0,
  "space": {
    "name": "example",
    "slug": "example"
  },
  "queuedCount": 0,
  "laterCount": 0
}
PATCH

Update a meeting

/api/meetings/{slug}

Change a meeting's name, schedule, owner or Space link. Owner or people admin. Every field is optional; omitted fields are left alone, and passing null clears the ones that allow it.

PATCH/api/meetings/{slug}
drop meetings edit ops-core --day-of-week 3 --time-label "Wed 3:00 PM ET"
Response200
{
  "slug": "example",
  "archivedAt": "example",
  "name": "example",
  "description": "example",
  "cadence": "WEEKLY",
  "dayOfWeek": 0,
  "timeLabel": "example",
  "scheduleLabel": "example",
  "nextWeekLabel": "example",
  "nextWeekStart": "example",
  "ownerName": "example",
  "attendeeCount": 0,
  "space": {
    "name": "example",
    "slug": "example"
  },
  "queuedCount": 0,
  "laterCount": 0
}
DELETE

Archive a meeting

/api/meetings/{slug}

Retire a meeting that has stopped sitting. Owner or people admin. Archiving rather than deleting on purpose: App.meetingId is SetNull, so a real delete would silently empty every agenda the meeting ever had. Topics keep their link and simply stop being listed.

DELETE/api/meetings/{slug}
drop meetings archive ops-core
Response200
{
  "slug": "example",
  "archived": false,
  "queuedTopics": 0
}
POST

Restore an archived meeting

/api/meetings/{slug}/restore

Bring an archived meeting back. Owner or people admin. Its topics reappear on the agenda exactly as they were, since the links were never broken.

POST/api/meetings/{slug}/restore
drop meetings restore ops-core
Response200
{
  "slug": "example",
  "archivedAt": "example",
  "name": "example",
  "description": "example",
  "cadence": "WEEKLY",
  "dayOfWeek": 0,
  "timeLabel": "example",
  "scheduleLabel": "example",
  "nextWeekLabel": "example",
  "nextWeekStart": "example",
  "ownerName": "example",
  "attendeeCount": 0,
  "space": {
    "name": "example",
    "slug": "example"
  },
  "queuedCount": 0,
  "laterCount": 0
}
GET

List members

/api/meetings/{slug}/attendees

The meeting's members, owners first. Same shape as a Space's members: everyone who belongs, each with a role.

GET/api/meetings/{slug}/attendees
drop meetings members list ops-core
Response200
{
  "slug": "example",
  "attendees": []
}
POST

Add members

/api/meetings/{slug}/attendees

Add people to the meeting, individually or by group. They join as PARTICIPANT; use set-role to make someone an owner. Owner or people admin. Groups expand server-side at the moment of adding and are not tracked afterwards. Idempotent — re-adding someone is a no-op, so pasting a full list is safe.

POST/api/meetings/{slug}/attendees
drop meetings members add ops-core --emails neil.murphy@himarley.com --groups 
Response200
{
  "slug": "example",
  "attendees": []
}
DELETE

Remove a member

/api/meetings/{slug}/attendees/{email}

Take someone off the meeting. Owner or people admin. Idempotent — removing someone who is not a member is a no-op. Refuses to remove the last OWNER, which would leave a meeting nobody can edit.

DELETE/api/meetings/{slug}/attendees/{email}
drop meetings members remove ops-core neil.murphy@himarley.com
Response200
{
  "slug": "example",
  "attendees": []
}
PATCH

Change a member's role

/api/meetings/{slug}/attendees/{email}

Promote a member to OWNER or return them to PARTICIPANT. Owner or people admin. Refuses to demote the last owner — a meeting with no owner has nobody who can appoint one.

PATCH/api/meetings/{slug}/attendees/{email}
drop meetings members set-role ops-core aurea.nunes@himarley.com --role OWNER
Response200
{
  "slug": "example",
  "attendees": []
}