Replace a rotation's grid
using System.Net.Http.Headers;var client = new HttpClient();var request = new HttpRequestMessage{ Method = HttpMethod.Put, RequestUri = new Uri("https://api.roundrobinbot.eu/v1/rotations/example/coverage"), Headers = { { "If-Match", "example" }, { "Authorization", "Bearer <token>" }, }, Content = new StringContent("{ \"lanes\": [ { \"id\": \"example\", \"name\": \"example\" } ], \"windows\": [ { \"id\": \"example\", \"name\": \"example\", \"timeZone\": \"example\", \"coverage\": [ { \"startDay\": \"example\", \"startTime\": \"example\", \"endDay\": \"example\", \"endTime\": \"example\" } ], \"cadence\": { \"type\": \"example\", \"timeZone\": \"example\", \"startsAt\": \"example\", \"period\": 1, \"skipWeekends\": true, \"skipNationalHolidays\": true, \"countryCodes\": [ \"example\" ], \"daysOfWeek\": [ \"example\" ], \"dayOfWeek\": \"example\", \"weeksInMonth\": [ 1 ], \"times\": [ \"example\" ] } } ], \"cells\": [ { \"id\": \"example\", \"laneId\": \"example\", \"windowId\": \"example\", \"rosterId\": \"example\" } ], \"doubleCover\": true }") { Headers = { ContentType = new MediaTypeHeaderValue("application/json-patch+json") } }};using (var response = await client.SendAsync(request)){ response.EnsureSuccessStatusCode(); var body = await response.Content.ReadAsStringAsync(); Console.WriteLine(body);}package main
import ( "fmt" "strings" "net/http" "io")
func main() {
url := "https://api.roundrobinbot.eu/v1/rotations/example/coverage"
payload := strings.NewReader("{ \"lanes\": [ { \"id\": \"example\", \"name\": \"example\" } ], \"windows\": [ { \"id\": \"example\", \"name\": \"example\", \"timeZone\": \"example\", \"coverage\": [ { \"startDay\": \"example\", \"startTime\": \"example\", \"endDay\": \"example\", \"endTime\": \"example\" } ], \"cadence\": { \"type\": \"example\", \"timeZone\": \"example\", \"startsAt\": \"example\", \"period\": 1, \"skipWeekends\": true, \"skipNationalHolidays\": true, \"countryCodes\": [ \"example\" ], \"daysOfWeek\": [ \"example\" ], \"dayOfWeek\": \"example\", \"weeksInMonth\": [ 1 ], \"times\": [ \"example\" ] } } ], \"cells\": [ { \"id\": \"example\", \"laneId\": \"example\", \"windowId\": \"example\", \"rosterId\": \"example\" } ], \"doubleCover\": true }")
req, _ := http.NewRequest("PUT", url, payload)
req.Header.Add("If-Match", "example") req.Header.Add("Authorization", "Bearer <token>") req.Header.Add("Content-Type", "application/json-patch+json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close() body, _ := io.ReadAll(res.Body)
fmt.Println(res) fmt.Println(string(body))
}OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/json-patch+json");RequestBody body = RequestBody.create(mediaType, "{ \"lanes\": [ { \"id\": \"example\", \"name\": \"example\" } ], \"windows\": [ { \"id\": \"example\", \"name\": \"example\", \"timeZone\": \"example\", \"coverage\": [ { \"startDay\": \"example\", \"startTime\": \"example\", \"endDay\": \"example\", \"endTime\": \"example\" } ], \"cadence\": { \"type\": \"example\", \"timeZone\": \"example\", \"startsAt\": \"example\", \"period\": 1, \"skipWeekends\": true, \"skipNationalHolidays\": true, \"countryCodes\": [ \"example\" ], \"daysOfWeek\": [ \"example\" ], \"dayOfWeek\": \"example\", \"weeksInMonth\": [ 1 ], \"times\": [ \"example\" ] } } ], \"cells\": [ { \"id\": \"example\", \"laneId\": \"example\", \"windowId\": \"example\", \"rosterId\": \"example\" } ], \"doubleCover\": true }");Request request = new Request.Builder() .url("https://api.roundrobinbot.eu/v1/rotations/example/coverage") .put(body) .addHeader("If-Match", "example") .addHeader("Authorization", "Bearer <token>") .addHeader("Content-Type", "application/json-patch+json") .build();
Response response = client.newCall(request).execute();import axios from 'axios';
const options = { method: 'PUT', url: 'https://api.roundrobinbot.eu/v1/rotations/example/coverage', headers: { 'If-Match': 'example', Authorization: 'Bearer <token>', 'Content-Type': 'application/json-patch+json' }, data: '{ "lanes": [ { "id": "example", "name": "example" } ], "windows": [ { "id": "example", "name": "example", "timeZone": "example", "coverage": [ { "startDay": "example", "startTime": "example", "endDay": "example", "endTime": "example" } ], "cadence": { "type": "example", "timeZone": "example", "startsAt": "example", "period": 1, "skipWeekends": true, "skipNationalHolidays": true, "countryCodes": [ "example" ], "daysOfWeek": [ "example" ], "dayOfWeek": "example", "weeksInMonth": [ 1 ], "times": [ "example" ] } } ], "cells": [ { "id": "example", "laneId": "example", "windowId": "example", "rosterId": "example" } ], "doubleCover": true }'};
try { const { data } = await axios.request(options); console.log(data);} catch (error) { console.error(error);}const url = 'https://api.roundrobinbot.eu/v1/rotations/example/coverage';const options = { method: 'PUT', headers: { 'If-Match': 'example', Authorization: 'Bearer <token>', 'Content-Type': 'application/json-patch+json' }, body: '{ "lanes": [ { "id": "example", "name": "example" } ], "windows": [ { "id": "example", "name": "example", "timeZone": "example", "coverage": [ { "startDay": "example", "startTime": "example", "endDay": "example", "endTime": "example" } ], "cadence": { "type": "example", "timeZone": "example", "startsAt": "example", "period": 1, "skipWeekends": true, "skipNationalHolidays": true, "countryCodes": [ "example" ], "daysOfWeek": [ "example" ], "dayOfWeek": "example", "weeksInMonth": [ 1 ], "times": [ "example" ] } } ], "cells": [ { "id": "example", "laneId": "example", "windowId": "example", "rosterId": "example" } ], "doubleCover": true }'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request PUT \ --url https://api.roundrobinbot.eu/v1/rotations/example/coverage \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json-patch+json' \ --header 'If-Match: example' \ --data '{ "lanes": [ { "id": "example", "name": "example" } ], "windows": [ { "id": "example", "name": "example", "timeZone": "example", "coverage": [ { "startDay": "example", "startTime": "example", "endDay": "example", "endTime": "example" } ], "cadence": { "type": "example", "timeZone": "example", "startsAt": "example", "period": 1, "skipWeekends": true, "skipNationalHolidays": true, "countryCodes": [ "example" ], "daysOfWeek": [ "example" ], "dayOfWeek": "example", "weeksInMonth": [ 1 ], "times": [ "example" ] } } ], "cells": [ { "id": "example", "laneId": "example", "windowId": "example", "rosterId": "example" } ], "doubleCover": true }'Gives the rotation the lanes, coverage windows and cells you describe. A replacement, not a patch: the lanes you send are the lanes it will have, and one you leave out is deleted along with whoever was on duty in it. Answers with the whole rotation and a fresh ETag. Read the rotation first and send its lanes, windows and cells back with your change made. Leave windows out entirely to keep the columns it has, which is what an edit to the rows alone should do. To add a lane or a window, leave its id out, or give it a handle of your own for its cells to name. Places this leaves empty are dealt straight away rather than at the next hand-over, so a lane you add has somebody on it when the response comes back.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”Header Parameters
Section titled “Header Parameters”The ETag from your last read of this rotation, sent back exactly as you received it, quotes included. The write happens only if nothing changed in between: a stale validator is answered 412 and nothing is written. Send * to write against whatever is current on purpose. Omitting the header is 428, never an unconditional write. https://docs.roundrobinbot.eu/api/conventions/#conditional-writes
Request Bodyrequired
Section titled “Request Bodyrequired”The grid PUT /v1/rotations/{rotationId}/coverage gives a rotation: its lanes, its coverage windows, and which list each place draws on.
object
The rows, in the order they should be dealt: the first lane is the primary one.
One row of the proposed grid.
object
The lane’s id, or a handle of your own for a lane you are adding. Always required.
What to call this lane, such as Primary or Frontend. Left out on a rotation with one lane, which never shows a name.
The columns: when the rotation is covered, and how often duty changes hands there.
One column of the proposed grid.
object
The window’s id, or a handle of your own for a window you are adding. Always required.
What to call this window, such as EMEA.
The time zone the covered hours below are read in, as a city identifier (Europe/Rome) or UTC. Fixed offsets are refused rather than guessed at.
The repeating week this column is open for. Leave it empty for a column that is open all week, which is what a rotation with no restricted hours has.
One stretch of the coverage week, which may run past midnight into the next day.
object
A weekday name, monday through sunday, lower case.
A time of day, HH:mm.
How often duty changes hands in this column. Leave it out to keep the cadence this window already has: a caller changing the hours must not flatten the handover as a side effect.
object
One of dayOfWeek, daysOfWeekList, dayOfMonth, nthWeekdayOfMonth, daily or workday.
The time zone the schedule runs in, as a city identifier: Europe/Rome, or UTC. Fixed offsets and old spellings are refused rather than guessed at.
When the schedule starts, as an RFC 3339 timestamp. A value with no offset is read as UTC.
How many units of the schedule’s own kind sit between two hand-overs: 2 on a dayOfWeek schedule is fortnightly. Defaults to 1.
Whether hand-overs that land on a weekend move on. Defaults to false, and is always true for workday. Needs countryCodes: which days are the weekend is a fact about a country.
Whether hand-overs that land on a national holiday move on. Defaults to false, and is always true for workday. Needs countryCodes for the same reason.
The ISO 3166-1 alpha-2 countries whose weekends and holidays the skips are read from. At least one is required whenever either skip is on, and so on every workday schedule, which turns both on. Without one the skips would skip nothing while still reading as active.
For daysOfWeekList: the weekdays it hands over on, lower case (monday … sunday). At least one.
For nthWeekdayOfMonth: which weekday, lower case. Not used by dayOfWeek, which takes its day from startsAt.
For nthWeekdayOfMonth: which occurrences in the month, 1 through 5. At least one.
For daily: the times of day it hands over at, as HH:mm. At least one.
Every lane crossed with every window, one cell each.
One place in the proposed grid: a lane crossed with a window.
object
The cell’s id, or left out to create one.
The lane this cell sits in, naming one of the lanes in this body.
The window this cell sits in, naming one of the windows in play.
The list this place is dealt from, which is required on every cell.
Whether one person may hold two places at once when the list behind them is too short to fill both. Defaults to false, which leaves the places it cannot fill empty.
Examplegenerated
{ "lanes": [ { "id": "example", "name": "example" } ], "windows": [ { "id": "example", "name": "example", "timeZone": "example", "coverage": [ { "startDay": "example", "startTime": "example", "endDay": "example", "endTime": "example" } ], "cadence": { "type": "example", "timeZone": "example", "startsAt": "example", "period": 1, "skipWeekends": true, "skipNationalHolidays": true, "countryCodes": [ "example" ], "daysOfWeek": [ "example" ], "dayOfWeek": "example", "weeksInMonth": [ 1 ], "times": [ "example" ] } } ], "cells": [ { "id": "example", "laneId": "example", "windowId": "example", "rosterId": "example" } ], "doubleCover": true}The grid PUT /v1/rotations/{rotationId}/coverage gives a rotation: its lanes, its coverage windows, and which list each place draws on.
object
The rows, in the order they should be dealt: the first lane is the primary one.
One row of the proposed grid.
object
The lane’s id, or a handle of your own for a lane you are adding. Always required.
What to call this lane, such as Primary or Frontend. Left out on a rotation with one lane, which never shows a name.
The columns: when the rotation is covered, and how often duty changes hands there.
One column of the proposed grid.
object
The window’s id, or a handle of your own for a window you are adding. Always required.
What to call this window, such as EMEA.
The time zone the covered hours below are read in, as a city identifier (Europe/Rome) or UTC. Fixed offsets are refused rather than guessed at.
The repeating week this column is open for. Leave it empty for a column that is open all week, which is what a rotation with no restricted hours has.
One stretch of the coverage week, which may run past midnight into the next day.
object
A weekday name, monday through sunday, lower case.
A time of day, HH:mm.
How often duty changes hands in this column. Leave it out to keep the cadence this window already has: a caller changing the hours must not flatten the handover as a side effect.
object
One of dayOfWeek, daysOfWeekList, dayOfMonth, nthWeekdayOfMonth, daily or workday.
The time zone the schedule runs in, as a city identifier: Europe/Rome, or UTC. Fixed offsets and old spellings are refused rather than guessed at.
When the schedule starts, as an RFC 3339 timestamp. A value with no offset is read as UTC.
How many units of the schedule’s own kind sit between two hand-overs: 2 on a dayOfWeek schedule is fortnightly. Defaults to 1.
Whether hand-overs that land on a weekend move on. Defaults to false, and is always true for workday. Needs countryCodes: which days are the weekend is a fact about a country.
Whether hand-overs that land on a national holiday move on. Defaults to false, and is always true for workday. Needs countryCodes for the same reason.
The ISO 3166-1 alpha-2 countries whose weekends and holidays the skips are read from. At least one is required whenever either skip is on, and so on every workday schedule, which turns both on. Without one the skips would skip nothing while still reading as active.
For daysOfWeekList: the weekdays it hands over on, lower case (monday … sunday). At least one.
For nthWeekdayOfMonth: which weekday, lower case. Not used by dayOfWeek, which takes its day from startsAt.
For nthWeekdayOfMonth: which occurrences in the month, 1 through 5. At least one.
For daily: the times of day it hands over at, as HH:mm. At least one.
Every lane crossed with every window, one cell each.
One place in the proposed grid: a lane crossed with a window.
object
The cell’s id, or left out to create one.
The lane this cell sits in, naming one of the lanes in this body.
The window this cell sits in, naming one of the windows in play.
The list this place is dealt from, which is required on every cell.
Whether one person may hold two places at once when the list behind them is too short to fill both. Defaults to false, which leaves the places it cannot fill empty.
Examplegenerated
{ "lanes": [ { "id": "example", "name": "example" } ], "windows": [ { "id": "example", "name": "example", "timeZone": "example", "coverage": [ { "startDay": "example", "startTime": "example", "endDay": "example", "endTime": "example" } ], "cadence": { "type": "example", "timeZone": "example", "startsAt": "example", "period": 1, "skipWeekends": true, "skipNationalHolidays": true, "countryCodes": [ "example" ], "daysOfWeek": [ "example" ], "dayOfWeek": "example", "weeksInMonth": [ 1 ], "times": [ "example" ] } } ], "cells": [ { "id": "example", "laneId": "example", "windowId": "example", "rosterId": "example" } ], "doubleCover": true}The grid PUT /v1/rotations/{rotationId}/coverage gives a rotation: its lanes, its coverage windows, and which list each place draws on.
object
The rows, in the order they should be dealt: the first lane is the primary one.
One row of the proposed grid.
object
The lane’s id, or a handle of your own for a lane you are adding. Always required.
What to call this lane, such as Primary or Frontend. Left out on a rotation with one lane, which never shows a name.
The columns: when the rotation is covered, and how often duty changes hands there.
One column of the proposed grid.
object
The window’s id, or a handle of your own for a window you are adding. Always required.
What to call this window, such as EMEA.
The time zone the covered hours below are read in, as a city identifier (Europe/Rome) or UTC. Fixed offsets are refused rather than guessed at.
The repeating week this column is open for. Leave it empty for a column that is open all week, which is what a rotation with no restricted hours has.
One stretch of the coverage week, which may run past midnight into the next day.
object
A weekday name, monday through sunday, lower case.
A time of day, HH:mm.
How often duty changes hands in this column. Leave it out to keep the cadence this window already has: a caller changing the hours must not flatten the handover as a side effect.
object
One of dayOfWeek, daysOfWeekList, dayOfMonth, nthWeekdayOfMonth, daily or workday.
The time zone the schedule runs in, as a city identifier: Europe/Rome, or UTC. Fixed offsets and old spellings are refused rather than guessed at.
When the schedule starts, as an RFC 3339 timestamp. A value with no offset is read as UTC.
How many units of the schedule’s own kind sit between two hand-overs: 2 on a dayOfWeek schedule is fortnightly. Defaults to 1.
Whether hand-overs that land on a weekend move on. Defaults to false, and is always true for workday. Needs countryCodes: which days are the weekend is a fact about a country.
Whether hand-overs that land on a national holiday move on. Defaults to false, and is always true for workday. Needs countryCodes for the same reason.
The ISO 3166-1 alpha-2 countries whose weekends and holidays the skips are read from. At least one is required whenever either skip is on, and so on every workday schedule, which turns both on. Without one the skips would skip nothing while still reading as active.
For daysOfWeekList: the weekdays it hands over on, lower case (monday … sunday). At least one.
For nthWeekdayOfMonth: which weekday, lower case. Not used by dayOfWeek, which takes its day from startsAt.
For nthWeekdayOfMonth: which occurrences in the month, 1 through 5. At least one.
For daily: the times of day it hands over at, as HH:mm. At least one.
Every lane crossed with every window, one cell each.
One place in the proposed grid: a lane crossed with a window.
object
The cell’s id, or left out to create one.
The lane this cell sits in, naming one of the lanes in this body.
The window this cell sits in, naming one of the windows in play.
The list this place is dealt from, which is required on every cell.
Whether one person may hold two places at once when the list behind them is too short to fill both. Defaults to false, which leaves the places it cannot fill empty.
Examplegenerated
{ "lanes": [ { "id": "example", "name": "example" } ], "windows": [ { "id": "example", "name": "example", "timeZone": "example", "coverage": [ { "startDay": "example", "startTime": "example", "endDay": "example", "endTime": "example" } ], "cadence": { "type": "example", "timeZone": "example", "startsAt": "example", "period": 1, "skipWeekends": true, "skipNationalHolidays": true, "countryCodes": [ "example" ], "daysOfWeek": [ "example" ], "dayOfWeek": "example", "weeksInMonth": [ 1 ], "times": [ "example" ] } } ], "cells": [ { "id": "example", "laneId": "example", "windowId": "example", "rosterId": "example" } ], "doubleCover": true}The grid PUT /v1/rotations/{rotationId}/coverage gives a rotation: its lanes, its coverage windows, and which list each place draws on.
object
The rows, in the order they should be dealt: the first lane is the primary one.
One row of the proposed grid.
object
The lane’s id, or a handle of your own for a lane you are adding. Always required.
What to call this lane, such as Primary or Frontend. Left out on a rotation with one lane, which never shows a name.
The columns: when the rotation is covered, and how often duty changes hands there.
One column of the proposed grid.
object
The window’s id, or a handle of your own for a window you are adding. Always required.
What to call this window, such as EMEA.
The time zone the covered hours below are read in, as a city identifier (Europe/Rome) or UTC. Fixed offsets are refused rather than guessed at.
The repeating week this column is open for. Leave it empty for a column that is open all week, which is what a rotation with no restricted hours has.
One stretch of the coverage week, which may run past midnight into the next day.
object
A weekday name, monday through sunday, lower case.
A time of day, HH:mm.
How often duty changes hands in this column. Leave it out to keep the cadence this window already has: a caller changing the hours must not flatten the handover as a side effect.
object
One of dayOfWeek, daysOfWeekList, dayOfMonth, nthWeekdayOfMonth, daily or workday.
The time zone the schedule runs in, as a city identifier: Europe/Rome, or UTC. Fixed offsets and old spellings are refused rather than guessed at.
When the schedule starts, as an RFC 3339 timestamp. A value with no offset is read as UTC.
How many units of the schedule’s own kind sit between two hand-overs: 2 on a dayOfWeek schedule is fortnightly. Defaults to 1.
Whether hand-overs that land on a weekend move on. Defaults to false, and is always true for workday. Needs countryCodes: which days are the weekend is a fact about a country.
Whether hand-overs that land on a national holiday move on. Defaults to false, and is always true for workday. Needs countryCodes for the same reason.
The ISO 3166-1 alpha-2 countries whose weekends and holidays the skips are read from. At least one is required whenever either skip is on, and so on every workday schedule, which turns both on. Without one the skips would skip nothing while still reading as active.
For daysOfWeekList: the weekdays it hands over on, lower case (monday … sunday). At least one.
For nthWeekdayOfMonth: which weekday, lower case. Not used by dayOfWeek, which takes its day from startsAt.
For nthWeekdayOfMonth: which occurrences in the month, 1 through 5. At least one.
For daily: the times of day it hands over at, as HH:mm. At least one.
Every lane crossed with every window, one cell each.
One place in the proposed grid: a lane crossed with a window.
object
The cell’s id, or left out to create one.
The lane this cell sits in, naming one of the lanes in this body.
The window this cell sits in, naming one of the windows in play.
The list this place is dealt from, which is required on every cell.
Whether one person may hold two places at once when the list behind them is too short to fill both. Defaults to false, which leaves the places it cannot fill empty.
Examplegenerated
{ "lanes": [ { "id": "example", "name": "example" } ], "windows": [ { "id": "example", "name": "example", "timeZone": "example", "coverage": [ { "startDay": "example", "startTime": "example", "endDay": "example", "endTime": "example" } ], "cadence": { "type": "example", "timeZone": "example", "startsAt": "example", "period": 1, "skipWeekends": true, "skipNationalHolidays": true, "countryCodes": [ "example" ], "daysOfWeek": [ "example" ], "dayOfWeek": "example", "weeksInMonth": [ 1 ], "times": [ "example" ] } } ], "cells": [ { "id": "example", "laneId": "example", "windowId": "example", "rosterId": "example" } ], "doubleCover": true}Responses
Section titled “Responses”OK
A rotation: the grid of duties it runs, who is in it, and who holds each place right now.
object
The short code the rotation answers to in Slack.
Whether every member of the workspace can see the rotation.
manual, auto or external.
How many lanes are running, which is how many people hold the shift at once.
Whether this rotation has more than one place to be on duty at once.
Whether one person may hold two places at once when the list behind them is too short to fill both.
Whether days the cadence skips — weekends, national holidays — count as time the rotation is not covered. One switch for the whole rotation, read into every window’s own reading.
Everybody in the rotation: the union across every list it draws on.
object
Members added individually.
One member of a rotation.
object
Where the member sits in the order the lists are built from.
Members that came in through a Slack user group, listed under the group they came from. Add or remove somebody in Slack’s group and the rotation follows.
A Slack user group in the rotation, and the people currently in it.
object
One member of a rotation.
object
Where the member sits in the order the lists are built from.
The rows of the grid: the kinds of duty this rotation runs.
A row of the grid: a kind of duty, such as primary or backend.
object
What the customer calls this lane, and absent until they name it.
The columns of the grid: covered hours, a time zone, and a handover cadence.
A column of the grid: when the rotation is covered, and how often duty changes hands there.
object
The one zone this window’s covered hours are expressed in, as its own identifier (Europe/Rome). Never rewritten to the tzdb canonical name a linked city shares. Empty on a manual rotation, which has no cadence and so no zone to express one in.
The repeating week this window is open for, as stored. Empty means the whole week.
One stretch of the coverage week, which may run past midnight into the next day.
object
A weekday name, monday through sunday.
A time of day, HH:mm.
Whether the window restricts nothing: open the whole week, every week.
How often duty changes hands in this column.
object
One of dayOfWeek, daysOfWeekList, dayOfMonth, nthWeekdayOfMonth, daily, workday, manual or external. Fields that mean nothing for the type are absent rather than defaulted, so test for presence rather than for a zero.
The time zone the cadence was configured with, as its own identifier (Europe/Rome). Never rewritten to the tzdb canonical name a linked city shares.
When the cadence starts, in its own time zone.
How many units of the cadence’s own kind sit between two hand-overs.
The countries whose weekends and holidays the skips are read from.
The next hand-overs this window has already scheduled. For anything further out, ask for a window from GET /v1/rotations/{rotationId}/schedule.
Set for dayOfWeek and nthWeekdayOfMonth.
Set for daysOfWeekList.
Set for dayOfMonth.
Set for nthWeekdayOfMonth: which occurrences in the month, 1 through 5.
Set for daily: the times of day it hands over at.
Set for external: which partner drives the rotation. One of pagerDuty, opsGenie, jsm for Jira Service Management, or none when the rotation is external but no partner is linked yet.
Whether the window is open at the moment of the response.
Every lane crossed with every window, and whoever holds each one.
A lane crossed with a window: one place somebody can be on duty.
object
Which list this place is dealt from, matching an entry in the rotation’s rosters.
Whether this place is defined but not running, because the workspace is not on a paid plan.
Whoever holds this place, or nothing.
object
The Slack user holding the place, or null when a partner named somebody Slack cannot.
Their position in the list this place is dealt from, and absent for a person a partner named, who was never dealt from a list at all.
Whether they are waiting for the window to open rather than on duty right now.
Members the list would otherwise have named, who were passed over because they were absent. A skip, decided once before the shift starts, rather than a hand-over of part of one.
A member the rotation passed over because they were away.
object
The Slack user id of the member who was passed over.
Where the absence came from: googleCalendar or internalAvailability. Null on older records, which predate the field, so treat it as optional.
The lists this rotation deals from, each in the order this rotation deals it.
A list this rotation deals from, in the order this rotation deals it.
object
The list this order belongs to. Absent on a rotation whose people are not on a shared list yet.
The turn order: who is dealt, and in what order.
One position in a turn order.
object
Set when the member is in the order by way of a user group.
The turn the next handover deals from.
The Slack user group kept in sync with whoever is on call.
The on-call resource, embedded, so the common question needs no second call.
object
Empty when nobody holds the shift, and also when an external rotation’s on-duty person has no Slack identity: read unmappedExternalDuty before concluding “nobody”.
One person holding the shift, and when they hold it until.
object
The Slack user id of the person actually on duty.
Their position in the turn order of the list they were dealt from.
Which place in the grid they hold, and the lane and window that cross there.
Members the plan would otherwise have named, who were passed over because they were absent.
A member the rotation passed over because they were away.
object
The Slack user id of the member who was passed over.
Where the absence came from: googleCalendar or internalAvailability. Null on older records, which predate the field, so treat it as optional.
Set when an external schedule put somebody on duty who does not map to a Slack user. For those rotations this is the only answer there is, so a client that reads onCall alone reports “nobody” for every one of them.
object
Every Slack user this body names, resolved, when the caller asked for ?expand=users. Null otherwise, so a client can tell “not asked for” from “asked for and nobody matched”.
A Slack user, as Round Robin knows them.
object
The Slack user id.
The workspace that owns this person’s directory entry, which under Enterprise Grid can differ from the calling key’s workspace.
Null when the install was never granted users:read.email, not only when unknown.
A Slack Connect person: visible through a shared channel, never a member of the workspace.
Deactivated in Slack, or gone from the workspace. These people are still answered rather than hidden, so an id a rotation still names resolves to something you can render.
The person’s Slack avatar, at 192px.
The person’s Slack time zone, as an IANA identifier (Europe/Rome). Absent when Round Robin has not seen one for them.
Examplegenerated
{ "id": "example", "name": "example", "description": "example", "code": "example", "enabled": true, "public": true, "mode": "example", "runningLanes": 1, "isGrid": true, "doubleCover": true, "skipsAreOffTime": true, "owners": [ "example" ], "channels": [ "example" ], "members": { "users": [ { "userId": "example", "sequenceNumber": 1 } ], "userGroups": [ { "userGroupId": "example", "users": [ { "userId": "example", "sequenceNumber": 1 } ] } ] }, "lanes": [ { "id": "example", "name": "example" } ], "windows": [ { "id": "example", "name": "example", "timeZone": "example", "coverage": [ { "startDay": "example", "startTime": "example", "endDay": "example", "endTime": "example" } ], "alwaysOpen": true, "cadence": { "type": "example", "timeZone": "example", "startsAt": "2026-04-15T12:00:00Z", "period": 1, "skipWeekends": true, "skipNationalHolidays": true, "countryCodes": [ "example" ], "nextEvents": [ "2026-04-15T12:00:00Z" ], "dayOfWeek": "example", "daysOfWeek": [ "example" ], "dayOfMonth": 1, "weeksInMonth": [ 1 ], "times": [ "example" ], "partner": "example" }, "openNow": true, "currentCoverage": { "startUtc": "2026-04-15T12:00:00Z", "endUtc": "2026-04-15T12:00:00Z" }, "nextCoverage": { "startUtc": "2026-04-15T12:00:00Z", "endUtc": "2026-04-15T12:00:00Z" } } ], "cells": [ { "id": "example", "laneId": "example", "windowId": "example", "rosterId": "example", "stopped": true, "holder": { "userId": "example", "externalUser": { "email": "example", "name": "example" }, "turn": 1, "waiting": true, "since": "2026-04-15T12:00:00Z", "until": "2026-04-15T12:00:00Z", "skippedForAbsence": [ { "userId": "example", "from": "2026-04-15T12:00:00Z", "until": "2026-04-15T12:00:00Z", "source": "example" } ] } } ], "rosters": [ { "rosterId": "example", "order": [ { "userId": "example", "userGroupId": "example", "turn": 1 } ], "nextTurn": 1 } ], "onDutyUserGroupId": "example", "onCall": { "rotationId": "example", "onCall": [ { "userId": "example", "turn": 1, "cellId": "example", "laneId": "example", "laneName": "example", "windowId": "example", "windowName": "example", "since": "2026-04-15T12:00:00Z", "until": "2026-04-15T12:00:00Z", "skippedForAbsence": [ { "userId": "example", "from": "2026-04-15T12:00:00Z", "until": "2026-04-15T12:00:00Z", "source": "example" } ] } ], "unmappedExternalDuty": { "email": "example", "name": "example", "until": "2026-04-15T12:00:00Z" }, "users": [ { "id": "example", "teamId": "example", "displayName": "example", "realName": "example", "email": "example", "isGuest": true, "isExternal": true, "isDeleted": true, "avatarUrl": "example", "timeZone": "example" } ] }, "createdAt": "2026-04-15T12:00:00Z", "updatedAt": "2026-04-15T12:00:00Z"}Bad Request
object
Examplegenerated
{ "type": "example", "title": "example", "status": 1, "detail": "example", "instance": "example"}Unauthorized
object
Examplegenerated
{ "type": "example", "title": "example", "status": 1, "detail": "example", "instance": "example"}Payment Required
object
Examplegenerated
{ "type": "example", "title": "example", "status": 1, "detail": "example", "instance": "example"}Forbidden
object
Examplegenerated
{ "type": "example", "title": "example", "status": 1, "detail": "example", "instance": "example"}Not Found
object
Examplegenerated
{ "type": "example", "title": "example", "status": 1, "detail": "example", "instance": "example"}Conflict
object
Examplegenerated
{ "type": "example", "title": "example", "status": 1, "detail": "example", "instance": "example"}Precondition Failed
object
Examplegenerated
{ "type": "example", "title": "example", "status": 1, "detail": "example", "instance": "example"}Precondition Required
object
Examplegenerated
{ "type": "example", "title": "example", "status": 1, "detail": "example", "instance": "example"}