---
title: "Change an event status"
method: POST
path: "/events/{id}/status"
tags: ["Events"]
---

# Change an event status

`POST /events/{id}/status`

## Request

- Base URL: `https://joinways.app/api/v1`
- URL: `https://joinways.app/api/v1/events/{id}/status`
- Auth: one of:
  - HTTP bearer
  - OAuth 2 (authorization code, authorization URL `https://joinways.app/oauth/authorize`, token URL `https://joinways.app/api/oauth/token`, scopes: `mcp.write`)

Same service as the app's status menu: archived events refused, custom stage checked against the workspace's stages, loss and cancellation reasons stored (cleared by any other status), the other `option` events of a group lost when one is confirmed (with `sibling_loss_reason`), `event_confirmed` notification, Slack and calendar sync. Fires the `event.status_changed` / `event.stage_changed` webhooks. **Role permission:** `events.manage`.

## Headers

- `Idempotency-Key` string

## Request body

- object
  - `status` 'option' | 'confirmed' | 'lost' | 'cancelled', required: `option` = pending / tentative, `confirmed` = booked, `lost` = did not convert, `cancelled` = cancelled after booking.
  - `stage_id` string, uuid, nullable: Custom stage under `status` (workspace stages); `null` clears it.
  - `loss_reason` 'insufficient_budget' | 'competitor_selected' | 'no_availability' | 'postponed' | 'venue_unsuitable' | 'venue_not_selected' | 'duplicate_booking' | 'location_mismatch' | 'client_unresponsive'
  - `loss_reason_detail` string
  - `cancellation_reason` 'client_request' | 'force_majeure' | 'health_safety' | 'venue_unavailable' | 'insufficient_attendees' | 'budget_cut' | 'date_conflict' | 'duplicate_booking' | 'internal_decision' | 'other'
  - `cancellation_reason_detail` string
  - `sibling_loss_reason` 'insufficient_budget' | 'competitor_selected' | 'no_availability' | 'postponed' | 'venue_unsuitable' | 'venue_not_selected' | 'duplicate_booking' | 'location_mismatch' | 'client_unresponsive'
  - `sibling_loss_reason_detail` string: Confirming an event of a group marks its other `option` events `lost` with this reason. Omitted: they stay as they are.

## Response `200`

The new status.

- object
  - `id` string, uuid
  - `status` 'option' | 'confirmed' | 'lost' | 'cancelled': `option` = pending / tentative, `confirmed` = booked, `lost` = did not convert, `cancelled` = cancelled after booking.
  - `venue_id` string, uuid, nullable
  - `stage_id` string, uuid, nullable
  - `status_changed_at` string, date-time, nullable
  - `loss_reason` string, nullable
  - `loss_reason_detail` string, nullable
  - `cancellation_reason` string, nullable
  - `cancellation_reason_detail` string, nullable

## Other responses

- `400`: Validation failed (`invalid_request`). For a body that fails the schema, `details` holds `formErrors` and `fieldErrors`.
- `401`: Missing, invalid, expired or revoked bearer token (`unauthorized`).
- `403`: `forbidden`: the token lacks the scope, its owner's role lacks the permission named by the operation, or the workspace has neither the Pro plan nor a trial (`details.reason` `plan_not_eligible`).
- `404`: Not found in this workspace, or the id of the path is not a UUID (`not_found`).
- `409`: The state of the record refuses the operation (`conflict`). `details.reason` is a stable code.
- `429`: Too many requests (`rate_limited`). `details.reason`: `per-ip`, `per-account-minute`, `per-account-day`, or `email_rate_limited` (email budget). Always carries `Retry-After`: wait that many seconds.

---

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