---
title: "Bulk-create time slots for a signup"
method: POST
path: "/signups/{id}/slots"
tags: ["Slots"]
---

# Bulk-create time slots for a signup

`POST /signups/{id}/slots`

## Request

- Base URL: `https://thesignup.app/api/v1`
- URL: `https://thesignup.app/api/v1/signups/{id}/slots`
- Auth: HTTP bearer

Insert one or more time slots on an existing signup. Use right after `POST /signups` to lay out a multi-slot event. Timezone (THE-206): if you supply `timezone` (IANA) — or the parent signup already has one — `startTime` / `endTime` may be naive local strings (`2026-09-15T17:00`); they're parsed against that zone and stored as UTC instants. Otherwise the existing UTC-only contract applies.

## Path parameters

- `id` string, uuid, required

## Request body

- CreateSlotsRequest
  - `timezone` string: Optional IANA timezone override for this batch. When set, naive `startTime` / `endTime` strings parse as wall-clock time in that zone. Falls back to the parent signup's `timezone` when absent.
  - `slots` object[], required
    - `startTime` string, required: ISO-8601 datetime. UTC (`...Z`), offset-bearing, OR naive local — naive form requires a timezone (either on this request or on the parent signup).
    - `endTime` string, required
    - `maxParticipants` integer, required
    - `maxPerPerson` integer
    - `title` string
    - `description` string
    - `location` string
    - `customField` object
      - `name` string, required: The question text. Trimmed, then 1 to 200 characters, when sent to the slot update door.
      - `placeholder` string: Example answer, shown as a hint in the answer box.
      - `required` boolean, required
      - `type` 'short' | 'long', required

## Response `201`

Created time slots

- CreateSlotsResponse
  - `count` integer, required
  - `data` TimeSlot[], required
    - `id` string, uuid, required
    - `eventId` string, uuid, required
    - `startTime` string, date-time, required
    - `endTime` string, date-time, required
    - `maxParticipants` integer, required
    - `maxPerPerson` integer, required: The most spots one person may take on this slot. 1 (the default) is one spot per person; 0 is no per-person limit.
    - `title` string, nullable, required
    - `description` string, nullable, required
    - `location` string, nullable, required
    - `customField` object, nullable, required: The slot's own question, as stored. Read `question` for what the slot actually asks — a slot generated from a repeating shift may inherit the shift's question when this is null.
      - `name` string, required
      - `placeholder` string
      - `required` boolean, required
      - `type` 'short' | 'long', required
    - `question` object, nullable, required: The question participants are asked when taking this slot: the slot's own, else the repeating shift's. Null when nothing is asked.
      - `label` string, required
      - `placeholder` string: Example answer, shown as a hint in the answer box. Absent when none was given.
      - `required` boolean, required
    - `questionSource` 'own' | 'series' | 'null', nullable, required: "own" when `question` is the slot's own; "series" when inherited from its repeating shift; null when nothing is asked.
    - `createdAt` string, date-time, required

## Other responses

- `401`: Unauthenticated — credentials missing, malformed, invalid, or revoked
- `404`: Not found
- `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)
