---
title: "Reopen a closed signup"
method: POST
path: "/signups/{id}/reopen"
tags: ["Signups"]
---

# Reopen a closed signup

`POST /signups/{id}/reopen`

## Request

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

Sets `signupCloseDate` to the date supplied and, if the signup is `closed`, makes it `published` again. Needed because PATCH /signups/{id} cannot change status. A date that is not in the future is refused with 400 and nothing is written. On a signup that is already `published` it only replaces `signupCloseDate` (it can move the date earlier or later) and a repeat call with the same date leaves the same end state; on a `draft` it sets the date and leaves the status `draft`. Does not touch registrations, slots or items. Also revives a signup that was cancelled (cancelling closes it), even if its participants were told it is cancelled. Notifies no participants and emits one `signup.updated` webhook, so a reopened signup is not announced to participants: message participants separately if they should know. The account that owns the credential must have a verified email address (returns 403 otherwise), as for publish.

## Path parameters

- `id` string, uuid, required

## Request body

- ReopenSignupRequest
  - `signupCloseDate` string, required: The new close date, a moment in the future (a past or present one is refused with 400 and nothing is written). ISO-8601, same rules as PATCH: UTC / offset-bearing, or a naive local string read in the signup's stored timezone. Always sets the signup's `signupCloseDate`, replacing the old one.

## Response `200`

The signup, reopened

- SignupDetail
  - `id` string, uuid, required
  - `organizationId` string, required
  - `slug` string, required
  - `title` string, required
  - `status` 'draft' | 'published' | 'closed', required
  - `eventDate` string, date-time, required: ISO-8601 UTC.
  - `signupCloseDate` string, date-time, nullable, required: ISO-8601 UTC. Null = signups never close until the event.
  - `location` string, nullable, required
  - `isPrivate` boolean, required
  - `createdAt` string, date-time, required
  - `updatedAt` string, date-time, required
  - `description` string, nullable, required
  - `maxParticipants` integer, nullable, required: Cap on total participants. Null only on a plan with no participant ceiling (uncapped); elsewhere the cap is stored as the plan ceiling.
  - `commitmentRequired` boolean, required: When true, a participant must claim a slot or an item to sign up — attending without committing to anything is not offered.
  - `requiresPhone` boolean, required
  - `timezone` string, required: IANA timezone the organizer attached to this signup. Display surfaces should prefer this over the viewer's local zone when rendering eventDate / slot times.
  - `eventWideCustomField` object, nullable, required: Optional one-off field shown on every signup form.
    - `name` string, required
    - `required` boolean, required
    - `type` 'short' | 'long', required
  - `days` Day[], required: Every day of the signup in date order, cancelled ones included. Same shape as `GET /signups/{id}/days`.
    - `id` string, uuid, required
    - `eventId` string, uuid, required
    - `date` string, required: The calendar date, `YYYY-MM-DD`, in the signup's timezone.
    - `seriesId` string, uuid, nullable, required: The Slot Series that generated this day, or null for a day added by hand or an ordinary signup's day.
    - `cancelledAt` string, date-time, nullable, required: When the day was called off, or null. A cancelled day keeps its slots, items and registrations. A repeating schedule's date is cancelled through its Shifts instead and keeps null here; read `noLiveTime`.
    - `noLiveTime` boolean, required: True when the day had times and none of them is live any more — participants are not offered it, exactly as a cancelled day.
    - `question` object, nullable, required: The Day Question asked once per day of whoever signs up for anything that day: the day's own, else the repeating schedule's default. Null when none.
      - `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: Whose `question` it is: the day's own, or the schedule's default it inherits. Null when there is no question.
    - `isPast` boolean, required: Whether the date is before today in the signup's timezone.

## 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
- `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)
