Conventions
Every /v1 operation pages, dates and versions its answers the same way. Learn these rules once and they hold across the API.
You need: the credential required by the operation. See authentication.
Read every page
Section titled “Read every page”| Response shape | Continue with |
|---|---|
page, pageSize, totalPages |
The next page number, until totalPages |
Cover requests with nextCursor |
That value as cursor, with the same from and to |
Availability impact with nextAfterRotationId |
That value as afterRotationId |
Page numbers start at 1, and pageSize is at most 100. Each operation lists the fields it sorts on. An unknown sort field, or a page or size out of range, returns 400.
An empty page does not prove there is nothing more. Check the completion fields and the limitation codes below.
When a read is not complete
Section titled “When a read is not complete”Some reads can answer only part of what you asked: a calendar could not be read, or a rotation’s future depends on somebody acting. These reads carry complete or completion, and a limitationCodes list that says why.
| Read | Where the codes are |
|---|---|
| Availability impact preview | rotations[].limitationCodes |
| Swap candidates | limitationCodes |
| One person’s shifts | rotations[].limitationCodes |
Each entry has a code, and a source when the reason concerns one availability source: manualAvailability or googleCalendar.
{ "code": "googleCalendarUnavailable", "source": "googleCalendar" }code |
What it means |
|---|---|
recurrenceExpansionIncomplete |
A recurring availability setting could not be expanded across the whole range. |
manualAvailabilityUnavailable |
Manual availability could not be read. |
googleCalendarUnavailable |
Google Calendar could not be read. |
proposalRecurrenceIncomplete |
The proposed recurring availability could not be expanded across the whole range. |
calendarFreshnessUnknown |
Google Calendar was read, but how recent its events are is not known. |
externalRotation |
The rotation follows a PagerDuty or Jira Service Management schedule, so no availability impact is projected. |
rotationDisabled |
The rotation is switched off, so no availability impact is projected. |
projectionUnavailable |
The rotation could not be projected. |
candidateHorizon |
A swap candidate ending after horizonUtc is left out. |
randomFutureUnknown |
The rotation picks at random, so future duty is not known until it is drawn. |
manualFutureContingent |
The rotation hands over by hand, so future duty depends on somebody rotating it. |
A read that carries any code is not exhaustive, so do not treat what it leaves out as confirmed. Treat a code you do not recognise the same way.
Keep interval boundaries
Section titled “Keep interval boundaries”Every timestamp carries its UTC offset. Duty and impact operations that ask for UTC accept offset zero only, so convert local dates and times before you send them.
An interval includes its start and excludes its end. To select a whole duty interval, send back the boundaries the API returned. Check each operation’s range limit: swap candidates and the availability impact preview accept at most 31 days.
Conditional reads
Section titled “Conditional reads”When a read returns an ETag, keep it exactly as received, quotes included. Where the operation supports conditional reads, send it in If-None-Match. 304 means your copy is still current.
Not every operation supports conditional reads. An ETag can also be the version a later write needs, so its presence alone does not mean If-None-Match works there.
Conditional writes
Section titled “Conditional writes”Writes to an existing rotation generally require If-Match. Send the current ETag from the resource, or from the action’s preview.
| Result | What to do |
|---|---|
428 precondition_required |
Send the required header. |
412 precondition_failed |
Read or preview again, review the current terms, and retry with the new ETag. |
409 write_conflict |
Read again, then retry the same change. |
An ETag with a W/ prefix is accepted when its revision matches. Keep the value as you received it.
If-Match: * lets a write through against any current revision. Avoid it when retrying an action that could advance duty twice.
Writes that take no precondition
Section titled “Writes that take no precondition”Creating and deleting a rotation absence need neither If-Match nor Idempotency-Key. Creating the same absence again (same person, period and appliesTo) returns the existing one.
Previews change nothing, so they need no If-Match either.
Create things once
Section titled “Create things once”Creating a rotation takes Idempotency-Key instead of If-Match. Use a new key for each rotation you mean to create, and the same key to retry it. A retry within 24 hours returns the rotation already created. Reusing the key after that returns 409.
Duty arrangement, cover and swap actions carry an operationId in the body. After an uncertain result, retry with the same body and the same identifier. Changed terms need a new identifier. See participant duty operations.
Cache and poll
Section titled “Cache and poll”Keep authenticated responses private to the caller. Conditional reads count towards rate limits, 304 responses included.
Poll only as often as your integration needs, and wait for Retry-After when a response carries it.
Next steps
Section titled “Next steps”- Errors: what each refusal means and what to do.
- Participant duty operations: preview and acknowledge duty changes.
- Rate limits: how often you can call.
