---
title: "Delete one Shift of a repeating schedule"
method: DELETE
path: "/signups/{id}/slot_series/{seriesId}/shifts/{shiftIndex}"
tags: ["Slots"]
---

# Delete one Shift of a repeating schedule

`DELETE /signups/{id}/slot_series/{seriesId}/shifts/{shiftIndex}`

## Request

- Base URL: `https://thesignup.app/api/v1`
- URL: `https://thesignup.app/api/v1/signups/{id}/slot_series/{seriesId}/shifts/{shiftIndex}`
- Auth: HTTP bearer

Remove one Shift from the Series' plan and cancel its live Occurrences, executed immediately: there is no dry run, and no confirmation step. Name the Shift with `shiftIndex` (path) and, on a weekly rule, `weekday` (query; `0`-`6`, `0` = Sunday). Higher Shifts are renumbered down by one. ALWAYS send `expectStart` and `expectEnd` (query, `HH:MM` from get_slot_coverage): higher Shifts renumber down after a delete, so the same `shiftIndex` then names a different Shift, and a retried or replayed DELETE (clients and proxies retry DELETE as idempotent) would cancel it and email its participants. With the precondition a replay is `409 conflict` and nothing is written; never retry without re-reading. The Occurrences are cancelled, not deleted: each keeps its `seriesId`, gets `cancelledAt` set and becomes detached, and its registrations stay on it. Every participant registered on a cancelled Occurrence is told by email, and by text when they gave a phone number and SMS consent; the optional JSON body's `message` is added to that notification and `note` is a private organizer note. A client or proxy that strips DELETE bodies sends the notification without `message`. The response reports the blast radius: `dates` cancelled, `affectedParticipants` and `notified`. A `shiftIndex` the Series does not have (or a weekly rule with no `weekday`) is `400 bad_request`, and so is removing the schedule's last Shift — delete the Series instead (`DELETE /signups/{id}/slot_series/{seriesId}`). Nothing is written in either case. The account behind the credential must have a verified email, or the call is `403 forbidden`.

## Path parameters

- `id` string, uuid, required
- `seriesId` string, uuid, required
- `shiftIndex` string, required: The Shift's position in the Series' shift plan (from `shiftIndex` on its Occurrences), counting from 0.

## Query parameters

- `expectStart` string: Precondition, sent together with `expectEnd`: the `HH:MM` start the Shift at this index has right now, in the signup's timezone (read it from get_slot_coverage). If the Shift there has other times — e.g. because a delete already renumbered the Shifts — the call is `409 conflict` and nothing is written. Always send it.
- `expectEnd` string: Precondition, sent together with `expectStart`: the `HH:MM` end the Shift at this index has right now, in the signup's timezone. Both or neither.
- `weekday` string: Weekly schedules only: the weekday the Shift runs on, `0`-`6` with `0` = Sunday. Ignored on daily and monthly schedules. The Series' `rule.activeDays` is keyed by the same numbers; get_slot_coverage groups a Shift without a weekday, so derive it from an Occurrence's `startTime` in the signup's timezone.

## Request body

- DeleteShiftRequest
  - `note` string, nullable: A private note for organizers, kept on the Occurrence and never shown to participants.
  - `message` string, nullable: Added to the email and text participants receive about this change.

## Response `200`

What the delete cancelled and who was told

- DeleteShiftResponse
  - `confirmed` boolean, required: Always `true` from this route: the call executed.
  - `dates` integer, required: Live Occurrences of the Shift (on that weekday, for a weekly rule) that were cancelled. Already-cancelled ones are not counted.
  - `affectedParticipants` integer, required: Registrations sitting on the cancelled Occurrences. They are kept, on cancelled dates.
  - `notified` object, required: Who the delete told: distinct participants, emails sent, texts sent.
    - `recipients` integer, required
    - `emails` integer, required
    - `sms` integer, required

## Other responses

- `400`: Bad request — body or path could not be parsed
- `401`: Unauthenticated — credentials missing, malformed, invalid, or revoked
- `403`: Forbidden — credentials valid but lack the required scope
- `404`: Not found
- `409`: The Shift at `shiftIndex` does not have the `expectStart` / `expectEnd` sent; nothing was written
- `422`: Validation failed — request body / query / path is structurally wrong
- `429`: Rate limited or daily ceiling exceeded
- `500`: Internal server error

---

[API](https://skmtc.dev/thesignup/apis/thesignup-api.md) · [All operations](https://skmtc.dev/thesignup/apis/thesignup-api/llms.txt) · [OpenAPI document](https://skmtc.dev/thesignup/apis/thesignup-api/revisions/c6da7cf92172?raw)
