on this page

Alerts and on callMaintenance windows

Maintenance windows

A maintenance window is a stretch of time when the alerts it covers reach your phone without a sound. They still arrive and still land in the feed, marked as held by maintenance, so you can read them. When the window ends, anything it held that is still a problem pages you once, at the level it was sent at.

There are two ways to open one. Make a window with the API when you know the work is coming: tonight's database upgrade, every Sunday's backup run. Or put hold= on a send when the sender itself knows it's about to be noisy, and the channel holds its own pages for that long.


What a window does

While a window covers an alert:

  • its push goes out quiet, page included. The feed records a held event naming the window,
  • an escalation waits. A page doesn't move to the next person, or to a teammate's phone, while the window that covers it is open,
  • repeats, escalation policy steps and the expiry timer wait too, rather than being used up in silence. A repeat comes one repeat interval after the window ends. The others keep the delay they had from the page, and land at least a minute after the window ends, so the re-page at the close reaches the phone first.

When the window ends, on time, by end or by being deleted, each alert it held is checked. It pages again if it's still open and unacknowledged and it's still an incident:

Held alert At the close
A probe that's still down, or a vital that's still flatlined Pages
Anything sent with ack=required, as loud, or as a page Pages
A normal notice that didn't ask for an answer Stays in the feed
Anything quiet or silent Stays in the feed
Anything acknowledged or closed during the window Nothing to do

A window that hold= opened is more generous: every held send that wasn't quiet or silent pages at the close, normal included.

Only alerts that arrived during the window are re-paged by its close. A page that was already ringing when the window began wasn't held by it. Its repeats wait for the window to end and then carry on where they left off.


Scope

A window covers the alerts its scope names. Name any mix of:

Field Matches
channels Alerts sent to these channels. Takes channel names or ids
probes Pages from these probes. Takes probe ids
hosts Alerts from any channel or probe whose host label is one of these. Case doesn't matter

An alert matching any one entry is covered. Each list takes up to 50 entries, and a blank entry is refused. A channel or probe that isn't yours answers 404.

To cover everything on the account, say so with "whole_owner": true and leave the lists out. A window with no channels, probes or hosts is refused with a 400 unless it has whole_owner, and the same goes for a PATCH that empties the last list. That's so a script that removes one channel too many can't quietly turn a narrow window into one that silences everything. whole_owner alongside a list with something in it is also a 400.


Making one

curl -X POST https://api.tissue.systems/v1/mast/maintenance \
  -H "Authorization: Bearer $TISSUE_TOKEN" -H "Content-Type: application/json" \
  -d '{"name": "db upgrade", "hosts": ["db-01", "db-02"], "minutes": 90}'
{
  "id": "mm_0c6e2a94d17b35f8a2c4e6081b3d5f79",
  "name": "db upgrade",
  "source": "api",
  "channels": [],
  "probes": [],
  "hosts": ["db-01", "db-02"],
  "whole_owner": false,
  "starts_at": "2026-10-06T21:00:00.000Z",
  "ends_at": "2026-10-06T22:30:00.000Z",
  "recurrence": null,
  "ended_at": null,
  "active": true,
  "active_until": "2026-10-06T22:30:00.000Z",
  "next_close_at": "2026-10-06T22:30:00.000Z",
  "last_closed_at": null,
  "created_at": "2026-10-06T21:00:00.000Z",
  "updated_at": "2026-10-06T21:00:00.000Z"
}

The answer is 201. The fields a window takes:

Field Meaning
name Up to 80 characters. Shown in the feed next to what the window held
channels, probes, hosts, whole_owner The scope, above
starts_at An ISO-8601 instant. Leave it out to start now
ends_at An ISO-8601 instant after starts_at
minutes The length instead of ends_at, 1 to 44,640. Give one or the other, not both
recurrence weekly, or leave it out for a one-off

A one-off window lasts up to 31 days and can't end in the past.

A weekly window repeats the same span every seven days from starts_at, until you delete it. It has to be shorter than seven days. The times are UTC instants, so a window set for 02:00 UTC stays at 02:00 UTC, and the local time it falls on moves when the clocks change.

# every Sunday 02:00 to 04:00 UTC, for the backup job
curl -X POST https://api.tissue.systems/v1/mast/maintenance \
  -H "Authorization: Bearer $TISSUE_TOKEN" -H "Content-Type: application/json" \
  -d '{"name": "sunday backup", "channels": ["backups"], "starts_at": "2026-10-11T02:00:00Z", "minutes": 120, "recurrence": "weekly"}'

A window that starts now is on every plan. One that starts later, more than two minutes from the request, and any weekly window, need Solo or above, and Free answers 402 plan_limit. An account can have 100 windows that aren't over yet, counting every weekly one, and the next answers 409 too_many_windows.

Reading, changing and ending

GET /v1/mast/maintenance lists every window you haven't deleted, newest start first, as {"items": [...]}. active says whether it's holding alerts right now, and active_until when the current stretch ends.

# change the scope or the name, any time
curl -X PATCH https://api.tissue.systems/v1/mast/maintenance/mm_0c6e… \
  -H "Authorization: Bearer $TISSUE_TOKEN" -H "Content-Type: application/json" \
  -d '{"hosts": ["db-01", "db-02", "db-03"]}'

# the work finished early: end it now
curl -X POST https://api.tissue.systems/v1/mast/maintenance/mm_0c6e…/end \
  -H "Authorization: Bearer $TISSUE_TOKEN"

# remove it
curl -X DELETE https://api.tissue.systems/v1/mast/maintenance/mm_0c6e… \
  -H "Authorization: Bearer $TISSUE_TOKEN"

A PATCH takes the same fields as the create. A list you leave out keeps what the window had. The scope can change while a window is open, and the close re-pages what's in the scope it has when it closes.

The times can't change once a window is in progress: starts_at, ends_at, minutes or recurrence on an open window answers 409 window_in_progress. Moving the end would risk losing what it already held. End it and make another. On a window that hasn't started, moving starts_at alone keeps its length.

end closes the window now and pages what it held before it answers. A weekly window ends this week's stretch and comes back next week. A window that isn't open answers 409 window_not_active.

DELETE answers 204. Deleting an open window ends it first, and what it held pages just as it would at the end.


hold= on a send

curl -X POST https://mast.tissue.dev/mk_1c9f… \
  -d title="deploy 2026.10.004" -d body="restarting the api, errors expected" -d hold=600

hold=N holds every page on this channel for the next N seconds, starting with this send. It's on every plan. N is a whole number of seconds from 1 to 21,600 (six hours), and 0 or leaving it out holds nothing. hold can't go with silent=1: that's a 400, since a silent send makes no sound to hold.

Each channel has one hold window. A later send with hold= stretches it, including one that folds into a card that's already open, but never past six hours from when it opened. At six hours the window closes and pages whatever it's still holding, however many sends keep arriving, so a sender stuck in a loop can't keep a channel quiet forever. If the window can't be written for any reason, the send pages as it normally would.

Hold windows show up in GET /v1/mast/maintenance with source: "hold" and the channel as their scope. They can be ended and deleted like any other. Their times and scope come from the sends, so a PATCH that touches them answers 409 hold_window. A rename is fine.


Destinations during a window

Destinations that a person reads, Slack, Discord, Teams and email, are held along with the phone. They hear nothing about a held alert while the window is open. At the close, every held alert that's still open gets its opening event sent to them, and the events after it follow, whether or not the close pages your phone again for it. An alert that opened and was acknowledged or closed inside the window never reaches them. Alerts that weren't held, because they were already open when the window began or were quiet, silent, or quieted by quiet hours or a mute before the window saw them, reach them as usual.

Webhooks and callback= URLs aren't held. They get every event as it happens, window or not, so a ticketing system or a log keeps a full record.

A window doesn't post anything to a status page. If you want visitors to see planned work, post a Planned maintenance update there by hand.