Get a rotation's activity
using System.Net.Http.Headers;var client = new HttpClient();var request = new HttpRequestMessage{ Method = HttpMethod.Get, RequestUri = new Uri("https://api.roundrobinbot.eu/v1/rotations/example/activity?from=2026-04-15T12%3A00%3A00Z&to=2026-04-15T12%3A00%3A00Z"), Headers = { { "Authorization", "Bearer <token>" }, },};using (var response = await client.SendAsync(request)){ response.EnsureSuccessStatusCode(); var body = await response.Content.ReadAsStringAsync(); Console.WriteLine(body);}package main
import ( "fmt" "net/http" "io")
func main() {
url := "https://api.roundrobinbot.eu/v1/rotations/example/activity?from=2026-04-15T12%3A00%3A00Z&to=2026-04-15T12%3A00%3A00Z"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
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();
Request request = new Request.Builder() .url("https://api.roundrobinbot.eu/v1/rotations/example/activity?from=2026-04-15T12%3A00%3A00Z&to=2026-04-15T12%3A00%3A00Z") .get() .addHeader("Authorization", "Bearer <token>") .build();
Response response = client.newCall(request).execute();import axios from 'axios';
const options = { method: 'GET', url: 'https://api.roundrobinbot.eu/v1/rotations/example/activity', params: {from: '2026-04-15T12:00:00Z', to: '2026-04-15T12:00:00Z'}, headers: {Authorization: 'Bearer <token>'}};
try { const { data } = await axios.request(options); console.log(data);} catch (error) { console.error(error);}const url = 'https://api.roundrobinbot.eu/v1/rotations/example/activity?from=2026-04-15T12%3A00%3A00Z&to=2026-04-15T12%3A00%3A00Z';const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request GET \ --url 'https://api.roundrobinbot.eu/v1/rotations/example/activity?from=2026-04-15T12%3A00%3A00Z&to=2026-04-15T12%3A00%3A00Z' \ --header 'Authorization: Bearer <token>'What was changed on this rotation inside a window you name, and who changed it: a person by their Slack user id, an API key by its key id, or the product itself when the cadence came round and nobody asked for anything. Each entry names the change as a code (coverage-changed, rotated-manually, owners-changed) and, for the settings that are audited as one entry, which parts of them moved. It does not carry before-and-after values: what a rotation records for those is a rendered string in a format meant for a screen. Read the rotation to see where it stands now. Refused calls are not here. A refusal is evidence about a credential rather than a change to your workspace, and nothing in this feed says what anybody authenticated with. from and to are both required, inclusive at both ends, and no more than 90 days apart. No ETag, as on every collection here.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”Query Parameters
Section titled “Query Parameters”Responses
Section titled “Responses”OK
The envelope every /v1 collection comes back in.
object
A recorded change to a rotation, including its time and actor.
object
The stable entry identifier. Use it to deduplicate polling results.
Recorded duty-change details, or null when this entry has no such snapshot. Do not infer missing details from the current schedule.
object
The identifier of the operation that recorded this change.
assignment, cover, swap or reset.
The recorded action code. Preserve unrecognized values when displaying or storing entries.
The assignment or request state recorded by this operation, not its current state.
The cover or swap request identifier, or null for a direct assignment or lane reset.
The requesting member’s Slack user identifier, when the change concerns a request.
The requested recipients’ Slack user identifiers. Empty when the change has no recipients.
Recorded affected intervals. Check each side’s resolved flag before interpreting its user identifiers.
An affected duty interval and its recorded assignees before and after the operation.
object
The identifier of the affected lane in a window.
The inclusive UTC start of the affected interval.
The exclusive UTC end, or null when no end is recorded.
Recorded assignees before the operation. Interpret an empty array only together with BeforeResolved.
Recorded assignees after the operation. Interpret an empty array only together with AfterResolved.
True when the preceding assignment is known. An empty user list then means no assignee; false means unknown.
True when the resulting assignment is known. An empty user list then means no assignee; false means unknown.
The lane name recorded for this change, when available.
The coverage-window name recorded for this change, when available.
The accepting cover recipient’s Slack user identifier recorded by this operation, or null when absent. This does not establish the interval’s resolved assignment.
The recorded time of the operation or change, in UTC.
The action code, such as created, coverage-changed or duty-change. Treat unrecognized values as opaque.
Codes identifying changed parts of a composite setting, such as timezone or week. Empty when no parts are recorded.
The rotation name recorded at the time of the change, when available.
The person, application or system responsible for the change.
object
The actor type: user, bot, mcpClient, apiKey or system.
The actor’s Slack user identifier, when available. Resolve it through GET /v1/users/{userId}.
The API key identifier when Type is apiKey. This is not the key secret.
Examplegenerated
{ "data": [ { "id": "example", "dutyChange": { "operationId": "example", "kind": "example", "action": "example", "state": "example", "requestId": "example", "requesterUserId": "example", "recipientUserIds": [ "example" ], "intervals": [ { "cellId": "example", "from": "2026-04-15T12:00:00Z", "to": "2026-04-15T12:00:00Z", "beforeUserIds": [ "example" ], "afterUserIds": [ "example" ], "beforeResolved": true, "afterResolved": true, "laneName": "example", "windowName": "example" } ], "acceptedUserId": "example" }, "at": "2026-04-15T12:00:00Z", "verb": "example", "parts": [ "example" ], "rotationName": "example", "actor": { "type": "example", "userId": "example", "keyId": "example" } } ], "page": 1, "pageSize": 1, "totalItems": 1, "totalPages": 1}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"}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"}