Announcements
An announcement tells people something has changed, and makes the knowledge base agree with what was said. It has words (the author’s own, and anything drawn from the library), a set of people who are told, and a plan: the changes to topics and items that sending it would make.
Reading announcements needs the read scope. Writing them needs a token granted
the announcement:write scope, which is an OAuth path today, and the person
behind the token must hold the matching permission. Admins, owners and billing admins hold them.
Who may read it, and who is told
Section titled “Who may read it, and who is told”These are two separate settings, and both have to be chosen before a send.
| Setting | Field | What it decides |
|---|---|---|
| Visibility | everyone |
Whether everyone in the organization may read the announcement, or admins only. |
| Audience | audience |
Who is told. A person, a team, a company role, a kind of role, or the whole organization. |
An audience wider than who may read the announcement is refused, because it would send people a message they cannot open.
States
Section titled “States”status |
Meaning |
|---|---|
DRAFT |
Being written. The only state in which the words, the title and everyone can change. |
PLANNING |
The plan is being worked out in the background. |
PLANNED |
The plan is ready to read. |
IN_REVIEW, READY |
Reserved for a reviewer’s confirmation. READY is reached by confirming the plan. Sending does not require it. |
SENDING |
Delivery is under way. |
SENT |
Delivered. Can be withdrawn for 48 hours. |
FAILED |
Some people were not reached. Sending again finishes the job. |
RETRACTED |
Withdrawn. |
GET /v1/announcements
The organization’s announcements, most recent first, in every state. Filter with
?status=. Requires announcement.read. The list is not paginated.
GET /v1/announcements/{id}
One announcement as its author sees it, with the same shape the write routes return.
{ "id": "…", "title": "Hard hats on every site", "everyone": true, "status": "DRAFT", "authorName": "Ada Admin", "selections": [ { "id": "…", "kind": "TOPIC", "topicId": "…", "title": "Head protection", "isAuthored": false, "excludedItemIds": [], "sequence": 1 } ], "audience": [ { "id": "…", "actorType": "TEAM", "actorId": "…", "displayName": "Site crews" } ], "composition": [ { "kind": "TEXT", "text": "From Monday, hard hats are required on every site." } ], "teaser": null, "requiresPopQuiz": false, "popQuizDueDate": null, "sentAt": null, "retractedAt": null, "createdAt": "2026-09-01T09:00:00.000Z", "updatedAt": "2026-09-01T09:05:00.000Z", "url": "https://…"}composition is what recipients will read, resolved from the selections as they
stand now. It carries no thumbnails or internal ids.
GET /v1/announcements/{id}/plan
The changes sending would make, and which the author has excluded. plan is
null until planning has started.
GET /v1/announcements/{id}/delivery
How many people were addressed, reached, could not be told, are outstanding, or
failed. delivery is null until sent.
GET /v1/announcements/{id}/pop-quiz
Who has taken the pop quiz, and how they did. popQuiz is null when the
announcement did not ask for one.
GET /v1/announcements/{id}/retraction-preview
What withdrawing it would undo, what cannot be undone, and how many people would
be told. canRetract is false once the window has closed.
GET /v1/announcements/{id}/read
The announcement as a recipient reads it: the title, who wrote it, when it was
sent and what it says. Needs no permission beyond being someone it was visible
to. A draft, or one you cannot see, is a 404.
Every write route needs announcement:write on the token, and asks for the
person’s permission live on each request. Write routes return the announcement in
the shape above, except where noted.
POST /v1/announcements
Start a draft. Nothing is required. Needs announcement.create.
PATCH /v1/announcements/{id}
Change title, everyone, requiresPopQuiz or popQuizDueDate. The title and
everyone only change while the announcement is a draft. The due date must be in
the future and may carry any UTC offset, and null returns to the default window.
A field the route does not know is refused with a 400, not ignored.
DELETE /v1/announcements/{id}
Delete a draft. Returns 204. Needs announcement.delete.
POST /v1/announcements/{id}/text
Set the author’s own words. Repeating it replaces them.
POST /v1/announcements/{id}/selections
Draw on a topic, item or resource.
DELETE /v1/announcements/{id}/selections/{selectionId}
Remove a selection, or the author’s own words.
DELETE /v1/announcements/{id}/selections/{selectionId}/items/{itemId}
Keep the selection and leave one item out of it.
POST /v1/announcements/{id}/audience
Add someone to who is told.
DELETE /v1/announcements/{id}/audience/{audienceId}
Remove an entry from who is told.
POST /v1/announcements/{id}/plan
Start working out what sending would change. Returns 202 at once with the
announcement in PLANNING.
POST /v1/announcements/{id}/plan/exclusion
Leave a planned change out, or put it back. Returns 204. The body names the
change by its sequence and states the outcome, so repeating it is safe:
{ "sequence": 2, "excluded": true }POST /v1/announcements/{id}/plan/confirm
Accept the plan and move the announcement to READY. Optional.
POST /v1/announcements/{id}/notification-preview
The email and text as they would arrive, and how many people they would go to,
without sending anything. resolvedRecipients is everyone the audience resolves
to, exclusions says who would be left out and why, and willBeTold is the
number a send would actually tell. It is a POST because it writes the opening line if
there is not one yet, so the sentence you preview is the sentence delivered.
Returns the notification rather than the announcement.
POST /v1/announcements/{id}/send
Send. Returns 202 at once with the announcement in SENDING. See
Sending.
POST /v1/announcements/{id}/retract
Withdraw within 48 hours of sending. See Withdrawing.
POST /v1/announcements/{id}/reopen
Return to draft, from PLANNING, PLANNED, IN_REVIEW or READY. The plan is kept until you change what the announcement says or draws on, and a plan that survived can be sent as it is. After such a change, plan again.
Add something to an announcement
Section titled “Add something to an announcement”{ "kind": "TOPIC", "topicId": "…" }kind is RESOURCE, TOPIC or ITEM, and the body carries exactly the one id
that matches it: contentId, topicId or itemId.
Choose who is told
Section titled “Choose who is told”{ "actorType": "TEAM", "actorId": "…" }actorType is INDIVIDUAL, TEAM, ROLE, ORGANIZATION or ROLE_KIND. For
ORGANIZATION, actorId is the organization id, and for INDIVIDUAL it is a user id
of an active member, which GET /v1/people finds from a name or an
email. A response reports a person’s actorId as the organization’s own record of
them, which is a different id, so identify people by displayName; it is accepted
back when adding. Third parties cannot be added, because they may have no address
and no way to take a pop quiz.
Write the announcement’s own words
Section titled “Write the announcement’s own words”{ "body": "From Monday, hard hats are required on every site.", "title": "Hard hats" }title is optional and defaults to the announcement’s. An empty body clears
the words.
Sending
Section titled “Sending”Sending is not a single call. The order is:
POST /v1/announcementsto start a draft.POST …/textandPOST …/selectionsto say what it says.PATCH …to chooseeveryoneandrequiresPopQuiz. Each has to be chosen,trueorfalse, before a send.POST …/audiencefor everyone who should be told.POST …/plan, which returns at once with the announcement inPLANNING. PollGET …/planuntil it appears. The announcement needs its own words first, because every change the plan proposes cites them.- Read the plan, and optionally
POST …/plan/exclusionto leave changes out. ThenPOST …/notification-previewto see the email and text and how many people it would tell (willBeTold). POST …/sendwith that number asexpectedRecipientCount. It returns at once with the announcement inSENDING. Follow it withGET …/delivery.
Having a plan does not mean anyone has read it, and sending is itself agreement to
the plan as it stands. POST …/plan/confirm is available, and moves the
announcement to READY, but is not required.
Sending to the people you looked at
Section titled “Sending to the people you looked at”Audiences change. Someone joins a team, an address is removed, a role gains a
member. expectedRecipientCount is how a send says which audience it was meant
for:
{ "expectedRecipientCount": 39 }If the send would now tell a different number of people, nothing goes out and the
response is a 409 that says what the number is now. Read the preview again and
send when it is the number you mean. Leaving the body out sends without the check.
The count is checked when the request is accepted. The audience is resolved once
more a moment later, when delivery starts, so this guards against a stale preview
and not against someone joining a team in those few seconds.
The number is willBeTold from the preview, which is the audience less the people
who cannot be told, and for a send that is finishing after a failure it is the
people still outstanding.
Calling send again on a FAILED announcement finishes it: it reaches only the
people still outstanding.
Withdrawing
Section titled “Withdrawing”POST /v1/announcements/{id}/retract works for 48 hours after a send. It undoes
what the announcement changed in the knowledge base and tells everyone the send
attempted that it was withdrawn. A change that cannot be undone is left in place,
and an issue is filed for each. Call GET …/retraction-preview first to see
what it would do.
What can go wrong
Section titled “What can go wrong”| Status | Meaning |
|---|---|
400 |
The body is invalid, or the announcement is in a state that does not allow this (for example editing one that has been planned, or sending one with no audience). A field the route does not take is refused rather than ignored, so a misspelt one is caught. The message says which. |
403 |
The token lacks the scope, or the person lacks the permission. |
404 |
The announcement does not exist, or is in another organization. |
409 |
A send with expectedRecipientCount would now tell a different number of people. Nothing was sent, and the message says the number. |
429 |
Rate limited. Send and retract allow only a few calls a minute, and plan and preview a few more. See Rate limits. |