> For the complete documentation index, see [llms.txt](https://movemint.gitbook.io/movemint-developer-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://movemint.gitbook.io/movemint-developer-docs/open-api-specification/core-resources/waves.md).

# Waves

Manage waves (start corrals / heats), assign and unassign participants, run bulk auto-assignment, and configure wave-number settings. A wave with no linked sub-events applies to every sub-event ("shared"); linking sub-events restricts it to those. Waves can be capped, gender-restricted, and time-gated by a time-based custom question.

## GET /api/v1/events/{handle}/waves

> List waves

````json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"tags":[{"name":"Waves","description":"Manage waves (start corrals / heats), assign and unassign participants,\nrun bulk auto-assignment, and configure wave-number settings. A wave with\nno linked sub-events applies to every sub-event (\"shared\"); linking\nsub-events restricts it to those. Waves can be capped, gender-restricted,\nand time-gated by a time-based custom question.\n"}],"servers":[{"url":"https://www.movemint.cc","description":"Production"}],"security":[{"bearerAuth":[]},{"oauth2":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Pass the access token in the `Authorization` header:\n```\nAuthorization: Bearer YOUR_ACCESS_TOKEN\n```\n"},"oauth2":{"type":"oauth2","description":"OAuth 2.0 authentication using the Authorization Code or Client\nCredentials grant flow.\n","flows":{"authorizationCode":{"authorizationUrl":"https://www.movemint.cc/oauth/authorize","tokenUrl":"https://www.movemint.cc/oauth/token","refreshUrl":"https://www.movemint.cc/oauth/token","scopes":{}},"clientCredentials":{"tokenUrl":"https://www.movemint.cc/oauth/token","scopes":{}}}}},"parameters":{"EventHandle":{"name":"handle","in":"path","required":true,"description":"The unique handle (slug) of the event","schema":{"type":"string"}}},"schemas":{"Wave":{"type":"object","required":["id","name","position","public","start_time","max_participants","gender_identity","gender_name","assigned_count","remaining_capacity","event_variant_ids","transactable_custom_question_id","min_time_seconds","max_time_seconds","created_at","updated_at"],"properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"position":{"type":"integer"},"public":{"type":"boolean","description":"Public waves are the ones bulk/auto-assignment fills."},"start_time":{"type":"string","format":"date-time","nullable":true},"max_participants":{"type":"integer","nullable":true,"description":"Capacity cap; null means unlimited."},"gender_identity":{"type":"integer","nullable":true,"description":"Gender restriction (0=Male, 1=Female, 2=Nonbinary, 3=Prefer Not to Say). Null = no restriction."},"gender_name":{"type":"string","nullable":true},"assigned_count":{"type":"integer"},"remaining_capacity":{"type":"integer","nullable":true},"event_variant_ids":{"type":"array","description":"Linked sub-event ids. Empty means the wave applies to every sub-event (shared).","items":{"type":"integer","format":"int64"}},"transactable_custom_question_id":{"type":"integer","format":"int64","nullable":true,"description":"Time-based custom question that gates eligibility, when set."},"min_time_seconds":{"type":"integer","nullable":true},"max_time_seconds":{"type":"integer","nullable":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"OAuthError":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Machine-readable error code"},"error_description":{"type":"string","description":"Human-readable description of the error"}}},"Error":{"type":"object","description":"A generic error response","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message"}}}},"responses":{"Unauthorized":{"description":"Unauthorized - invalid or missing token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"Forbidden":{"description":"Forbidden - user is not an admin of this event","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"EventNotFound":{"description":"Event not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/api/v1/events/{handle}/waves":{"get":{"tags":["Waves"],"summary":"List waves","operationId":"listWaves","parameters":[{"$ref":"#/components/parameters/EventHandle"}],"responses":{"200":{"description":"Waves ordered by position","content":{"application/json":{"schema":{"type":"object","required":["waves"],"properties":{"waves":{"type":"array","items":{"$ref":"#/components/schemas/Wave"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/EventNotFound"}}}}}}
````

## POST /api/v1/events/{handle}/waves

> Create a wave

````json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"tags":[{"name":"Waves","description":"Manage waves (start corrals / heats), assign and unassign participants,\nrun bulk auto-assignment, and configure wave-number settings. A wave with\nno linked sub-events applies to every sub-event (\"shared\"); linking\nsub-events restricts it to those. Waves can be capped, gender-restricted,\nand time-gated by a time-based custom question.\n"}],"servers":[{"url":"https://www.movemint.cc","description":"Production"}],"security":[{"bearerAuth":[]},{"oauth2":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Pass the access token in the `Authorization` header:\n```\nAuthorization: Bearer YOUR_ACCESS_TOKEN\n```\n"},"oauth2":{"type":"oauth2","description":"OAuth 2.0 authentication using the Authorization Code or Client\nCredentials grant flow.\n","flows":{"authorizationCode":{"authorizationUrl":"https://www.movemint.cc/oauth/authorize","tokenUrl":"https://www.movemint.cc/oauth/token","refreshUrl":"https://www.movemint.cc/oauth/token","scopes":{}},"clientCredentials":{"tokenUrl":"https://www.movemint.cc/oauth/token","scopes":{}}}}},"parameters":{"EventHandle":{"name":"handle","in":"path","required":true,"description":"The unique handle (slug) of the event","schema":{"type":"string"}}},"schemas":{"CreateWaveRequest":{"allOf":[{"$ref":"#/components/schemas/WaveWritableFields"},{"type":"object","required":["name"],"properties":{"name":{"type":"string"}}}]},"WaveWritableFields":{"type":"object","properties":{"public":{"type":"boolean"},"start_time":{"type":"string","format":"date-time"},"max_participants":{"type":"integer","minimum":1},"gender_identity":{"type":"integer","enum":[0,1,2,3],"description":"0=Male, 1=Female, 2=Nonbinary, 3=Prefer Not to Say."},"position":{"type":"integer"},"transactable_custom_question_id":{"type":"integer","format":"int64","description":"Required if you set min/max time bounds. Clearing it clears the bounds."},"min_time_seconds":{"type":"integer","minimum":0},"max_time_seconds":{"type":"integer","minimum":0},"event_variant_ids":{"type":"array","description":"Sub-event ids to link. Replace-not-merge. Pass [] for a shared wave.","items":{"type":"integer","format":"int64"}}}},"Wave":{"type":"object","required":["id","name","position","public","start_time","max_participants","gender_identity","gender_name","assigned_count","remaining_capacity","event_variant_ids","transactable_custom_question_id","min_time_seconds","max_time_seconds","created_at","updated_at"],"properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"position":{"type":"integer"},"public":{"type":"boolean","description":"Public waves are the ones bulk/auto-assignment fills."},"start_time":{"type":"string","format":"date-time","nullable":true},"max_participants":{"type":"integer","nullable":true,"description":"Capacity cap; null means unlimited."},"gender_identity":{"type":"integer","nullable":true,"description":"Gender restriction (0=Male, 1=Female, 2=Nonbinary, 3=Prefer Not to Say). Null = no restriction."},"gender_name":{"type":"string","nullable":true},"assigned_count":{"type":"integer"},"remaining_capacity":{"type":"integer","nullable":true},"event_variant_ids":{"type":"array","description":"Linked sub-event ids. Empty means the wave applies to every sub-event (shared).","items":{"type":"integer","format":"int64"}},"transactable_custom_question_id":{"type":"integer","format":"int64","nullable":true,"description":"Time-based custom question that gates eligibility, when set."},"min_time_seconds":{"type":"integer","nullable":true},"max_time_seconds":{"type":"integer","nullable":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"OAuthError":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Machine-readable error code"},"error_description":{"type":"string","description":"Human-readable description of the error"}}},"Error":{"type":"object","description":"A generic error response","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message"}}},"ValidationError":{"type":"object","description":"A validation error response with a list of error messages","required":["errors"],"properties":{"errors":{"type":"array","items":{"type":"string"},"description":"List of validation error messages"}}}},"responses":{"Unauthorized":{"description":"Unauthorized - invalid or missing token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"Forbidden":{"description":"Forbidden - user is not an admin of this event","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"EventNotFound":{"description":"Event not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/api/v1/events/{handle}/waves":{"post":{"tags":["Waves"],"summary":"Create a wave","operationId":"createWave","parameters":[{"$ref":"#/components/parameters/EventHandle"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWaveRequest"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","required":["wave"],"properties":{"wave":{"$ref":"#/components/schemas/Wave"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/EventNotFound"},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}}}}}}}
````

## GET /api/v1/events/{handle}/waves/{id}

> Get a wave

````json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"tags":[{"name":"Waves","description":"Manage waves (start corrals / heats), assign and unassign participants,\nrun bulk auto-assignment, and configure wave-number settings. A wave with\nno linked sub-events applies to every sub-event (\"shared\"); linking\nsub-events restricts it to those. Waves can be capped, gender-restricted,\nand time-gated by a time-based custom question.\n"}],"servers":[{"url":"https://www.movemint.cc","description":"Production"}],"security":[{"bearerAuth":[]},{"oauth2":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Pass the access token in the `Authorization` header:\n```\nAuthorization: Bearer YOUR_ACCESS_TOKEN\n```\n"},"oauth2":{"type":"oauth2","description":"OAuth 2.0 authentication using the Authorization Code or Client\nCredentials grant flow.\n","flows":{"authorizationCode":{"authorizationUrl":"https://www.movemint.cc/oauth/authorize","tokenUrl":"https://www.movemint.cc/oauth/token","refreshUrl":"https://www.movemint.cc/oauth/token","scopes":{}},"clientCredentials":{"tokenUrl":"https://www.movemint.cc/oauth/token","scopes":{}}}}},"parameters":{"EventHandle":{"name":"handle","in":"path","required":true,"description":"The unique handle (slug) of the event","schema":{"type":"string"}},"ResourceId":{"name":"id","in":"path","required":true,"description":"The ID of the resource","schema":{"type":"integer","format":"int64"}}},"schemas":{"Wave":{"type":"object","required":["id","name","position","public","start_time","max_participants","gender_identity","gender_name","assigned_count","remaining_capacity","event_variant_ids","transactable_custom_question_id","min_time_seconds","max_time_seconds","created_at","updated_at"],"properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"position":{"type":"integer"},"public":{"type":"boolean","description":"Public waves are the ones bulk/auto-assignment fills."},"start_time":{"type":"string","format":"date-time","nullable":true},"max_participants":{"type":"integer","nullable":true,"description":"Capacity cap; null means unlimited."},"gender_identity":{"type":"integer","nullable":true,"description":"Gender restriction (0=Male, 1=Female, 2=Nonbinary, 3=Prefer Not to Say). Null = no restriction."},"gender_name":{"type":"string","nullable":true},"assigned_count":{"type":"integer"},"remaining_capacity":{"type":"integer","nullable":true},"event_variant_ids":{"type":"array","description":"Linked sub-event ids. Empty means the wave applies to every sub-event (shared).","items":{"type":"integer","format":"int64"}},"transactable_custom_question_id":{"type":"integer","format":"int64","nullable":true,"description":"Time-based custom question that gates eligibility, when set."},"min_time_seconds":{"type":"integer","nullable":true},"max_time_seconds":{"type":"integer","nullable":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"OAuthError":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Machine-readable error code"},"error_description":{"type":"string","description":"Human-readable description of the error"}}},"Error":{"type":"object","description":"A generic error response","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message"}}}},"responses":{"Unauthorized":{"description":"Unauthorized - invalid or missing token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"Forbidden":{"description":"Forbidden - user is not an admin of this event","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"EventNotFound":{"description":"Event not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/api/v1/events/{handle}/waves/{id}":{"get":{"tags":["Waves"],"summary":"Get a wave","operationId":"getWave","parameters":[{"$ref":"#/components/parameters/EventHandle"},{"$ref":"#/components/parameters/ResourceId"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["wave"],"properties":{"wave":{"$ref":"#/components/schemas/Wave"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/EventNotFound"}}}}}}
````

## DELETE /api/v1/events/{handle}/waves/{id}

> Delete a wave

````json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"tags":[{"name":"Waves","description":"Manage waves (start corrals / heats), assign and unassign participants,\nrun bulk auto-assignment, and configure wave-number settings. A wave with\nno linked sub-events applies to every sub-event (\"shared\"); linking\nsub-events restricts it to those. Waves can be capped, gender-restricted,\nand time-gated by a time-based custom question.\n"}],"servers":[{"url":"https://www.movemint.cc","description":"Production"}],"security":[{"bearerAuth":[]},{"oauth2":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Pass the access token in the `Authorization` header:\n```\nAuthorization: Bearer YOUR_ACCESS_TOKEN\n```\n"},"oauth2":{"type":"oauth2","description":"OAuth 2.0 authentication using the Authorization Code or Client\nCredentials grant flow.\n","flows":{"authorizationCode":{"authorizationUrl":"https://www.movemint.cc/oauth/authorize","tokenUrl":"https://www.movemint.cc/oauth/token","refreshUrl":"https://www.movemint.cc/oauth/token","scopes":{}},"clientCredentials":{"tokenUrl":"https://www.movemint.cc/oauth/token","scopes":{}}}}},"parameters":{"EventHandle":{"name":"handle","in":"path","required":true,"description":"The unique handle (slug) of the event","schema":{"type":"string"}},"ResourceId":{"name":"id","in":"path","required":true,"description":"The ID of the resource","schema":{"type":"integer","format":"int64"}}},"responses":{"Unauthorized":{"description":"Unauthorized - invalid or missing token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"Forbidden":{"description":"Forbidden - user is not an admin of this event","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"EventNotFound":{"description":"Event not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"OAuthError":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Machine-readable error code"},"error_description":{"type":"string","description":"Human-readable description of the error"}}},"Error":{"type":"object","description":"A generic error response","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message"}}}}},"paths":{"/api/v1/events/{handle}/waves/{id}":{"delete":{"tags":["Waves"],"summary":"Delete a wave","operationId":"deleteWave","parameters":[{"$ref":"#/components/parameters/EventHandle"},{"$ref":"#/components/parameters/ResourceId"}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","enum":[true]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/EventNotFound"}}}}}}
````

## Update a wave

> Only the fields you send are changed. Sending \`event\_variant\_ids\`\
> REPLACES the full set of linked sub-events (pass \`\[]\` to make the wave\
> shared). Clearing \`transactable\_custom\_question\_id\` also clears the time\
> bounds.<br>

````json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"tags":[{"name":"Waves","description":"Manage waves (start corrals / heats), assign and unassign participants,\nrun bulk auto-assignment, and configure wave-number settings. A wave with\nno linked sub-events applies to every sub-event (\"shared\"); linking\nsub-events restricts it to those. Waves can be capped, gender-restricted,\nand time-gated by a time-based custom question.\n"}],"servers":[{"url":"https://www.movemint.cc","description":"Production"}],"security":[{"bearerAuth":[]},{"oauth2":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Pass the access token in the `Authorization` header:\n```\nAuthorization: Bearer YOUR_ACCESS_TOKEN\n```\n"},"oauth2":{"type":"oauth2","description":"OAuth 2.0 authentication using the Authorization Code or Client\nCredentials grant flow.\n","flows":{"authorizationCode":{"authorizationUrl":"https://www.movemint.cc/oauth/authorize","tokenUrl":"https://www.movemint.cc/oauth/token","refreshUrl":"https://www.movemint.cc/oauth/token","scopes":{}},"clientCredentials":{"tokenUrl":"https://www.movemint.cc/oauth/token","scopes":{}}}}},"parameters":{"EventHandle":{"name":"handle","in":"path","required":true,"description":"The unique handle (slug) of the event","schema":{"type":"string"}},"ResourceId":{"name":"id","in":"path","required":true,"description":"The ID of the resource","schema":{"type":"integer","format":"int64"}}},"schemas":{"UpdateWaveRequest":{"allOf":[{"$ref":"#/components/schemas/WaveWritableFields"},{"type":"object","properties":{"name":{"type":"string"}}}]},"WaveWritableFields":{"type":"object","properties":{"public":{"type":"boolean"},"start_time":{"type":"string","format":"date-time"},"max_participants":{"type":"integer","minimum":1},"gender_identity":{"type":"integer","enum":[0,1,2,3],"description":"0=Male, 1=Female, 2=Nonbinary, 3=Prefer Not to Say."},"position":{"type":"integer"},"transactable_custom_question_id":{"type":"integer","format":"int64","description":"Required if you set min/max time bounds. Clearing it clears the bounds."},"min_time_seconds":{"type":"integer","minimum":0},"max_time_seconds":{"type":"integer","minimum":0},"event_variant_ids":{"type":"array","description":"Sub-event ids to link. Replace-not-merge. Pass [] for a shared wave.","items":{"type":"integer","format":"int64"}}}},"Wave":{"type":"object","required":["id","name","position","public","start_time","max_participants","gender_identity","gender_name","assigned_count","remaining_capacity","event_variant_ids","transactable_custom_question_id","min_time_seconds","max_time_seconds","created_at","updated_at"],"properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"position":{"type":"integer"},"public":{"type":"boolean","description":"Public waves are the ones bulk/auto-assignment fills."},"start_time":{"type":"string","format":"date-time","nullable":true},"max_participants":{"type":"integer","nullable":true,"description":"Capacity cap; null means unlimited."},"gender_identity":{"type":"integer","nullable":true,"description":"Gender restriction (0=Male, 1=Female, 2=Nonbinary, 3=Prefer Not to Say). Null = no restriction."},"gender_name":{"type":"string","nullable":true},"assigned_count":{"type":"integer"},"remaining_capacity":{"type":"integer","nullable":true},"event_variant_ids":{"type":"array","description":"Linked sub-event ids. Empty means the wave applies to every sub-event (shared).","items":{"type":"integer","format":"int64"}},"transactable_custom_question_id":{"type":"integer","format":"int64","nullable":true,"description":"Time-based custom question that gates eligibility, when set."},"min_time_seconds":{"type":"integer","nullable":true},"max_time_seconds":{"type":"integer","nullable":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"OAuthError":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Machine-readable error code"},"error_description":{"type":"string","description":"Human-readable description of the error"}}},"Error":{"type":"object","description":"A generic error response","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message"}}},"ValidationError":{"type":"object","description":"A validation error response with a list of error messages","required":["errors"],"properties":{"errors":{"type":"array","items":{"type":"string"},"description":"List of validation error messages"}}}},"responses":{"Unauthorized":{"description":"Unauthorized - invalid or missing token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"Forbidden":{"description":"Forbidden - user is not an admin of this event","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"EventNotFound":{"description":"Event not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/api/v1/events/{handle}/waves/{id}":{"patch":{"tags":["Waves"],"summary":"Update a wave","operationId":"updateWave","description":"Only the fields you send are changed. Sending `event_variant_ids`\nREPLACES the full set of linked sub-events (pass `[]` to make the wave\nshared). Clearing `transactable_custom_question_id` also clears the time\nbounds.\n","parameters":[{"$ref":"#/components/parameters/EventHandle"},{"$ref":"#/components/parameters/ResourceId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateWaveRequest"}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object","required":["wave"],"properties":{"wave":{"$ref":"#/components/schemas/Wave"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/EventNotFound"},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}}}}}}}
````

## Reorder waves

> Sets wave positions from the order of the given ids. Foreign ids are ignored.

````json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"tags":[{"name":"Waves","description":"Manage waves (start corrals / heats), assign and unassign participants,\nrun bulk auto-assignment, and configure wave-number settings. A wave with\nno linked sub-events applies to every sub-event (\"shared\"); linking\nsub-events restricts it to those. Waves can be capped, gender-restricted,\nand time-gated by a time-based custom question.\n"}],"servers":[{"url":"https://www.movemint.cc","description":"Production"}],"security":[{"bearerAuth":[]},{"oauth2":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Pass the access token in the `Authorization` header:\n```\nAuthorization: Bearer YOUR_ACCESS_TOKEN\n```\n"},"oauth2":{"type":"oauth2","description":"OAuth 2.0 authentication using the Authorization Code or Client\nCredentials grant flow.\n","flows":{"authorizationCode":{"authorizationUrl":"https://www.movemint.cc/oauth/authorize","tokenUrl":"https://www.movemint.cc/oauth/token","refreshUrl":"https://www.movemint.cc/oauth/token","scopes":{}},"clientCredentials":{"tokenUrl":"https://www.movemint.cc/oauth/token","scopes":{}}}}},"parameters":{"EventHandle":{"name":"handle","in":"path","required":true,"description":"The unique handle (slug) of the event","schema":{"type":"string"}}},"schemas":{"Wave":{"type":"object","required":["id","name","position","public","start_time","max_participants","gender_identity","gender_name","assigned_count","remaining_capacity","event_variant_ids","transactable_custom_question_id","min_time_seconds","max_time_seconds","created_at","updated_at"],"properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"position":{"type":"integer"},"public":{"type":"boolean","description":"Public waves are the ones bulk/auto-assignment fills."},"start_time":{"type":"string","format":"date-time","nullable":true},"max_participants":{"type":"integer","nullable":true,"description":"Capacity cap; null means unlimited."},"gender_identity":{"type":"integer","nullable":true,"description":"Gender restriction (0=Male, 1=Female, 2=Nonbinary, 3=Prefer Not to Say). Null = no restriction."},"gender_name":{"type":"string","nullable":true},"assigned_count":{"type":"integer"},"remaining_capacity":{"type":"integer","nullable":true},"event_variant_ids":{"type":"array","description":"Linked sub-event ids. Empty means the wave applies to every sub-event (shared).","items":{"type":"integer","format":"int64"}},"transactable_custom_question_id":{"type":"integer","format":"int64","nullable":true,"description":"Time-based custom question that gates eligibility, when set."},"min_time_seconds":{"type":"integer","nullable":true},"max_time_seconds":{"type":"integer","nullable":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"OAuthError":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Machine-readable error code"},"error_description":{"type":"string","description":"Human-readable description of the error"}}},"Error":{"type":"object","description":"A generic error response","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message"}}}},"responses":{"Unauthorized":{"description":"Unauthorized - invalid or missing token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"Forbidden":{"description":"Forbidden - user is not an admin of this event","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"EventNotFound":{"description":"Event not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/api/v1/events/{handle}/waves/reorder":{"patch":{"tags":["Waves"],"summary":"Reorder waves","operationId":"reorderWaves","description":"Sets wave positions from the order of the given ids. Foreign ids are ignored.","parameters":[{"$ref":"#/components/parameters/EventHandle"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["wave_ids"],"properties":{"wave_ids":{"type":"array","items":{"type":"integer","format":"int64"}}}}}}},"responses":{"200":{"description":"Reordered","content":{"application/json":{"schema":{"type":"object","required":["waves"],"properties":{"waves":{"type":"array","items":{"$ref":"#/components/schemas/Wave"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/EventNotFound"},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}
````

## GET /api/v1/events/{handle}/waves/participants

> List participants with wave-assignment status

````json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"tags":[{"name":"Waves","description":"Manage waves (start corrals / heats), assign and unassign participants,\nrun bulk auto-assignment, and configure wave-number settings. A wave with\nno linked sub-events applies to every sub-event (\"shared\"); linking\nsub-events restricts it to those. Waves can be capped, gender-restricted,\nand time-gated by a time-based custom question.\n"}],"servers":[{"url":"https://www.movemint.cc","description":"Production"}],"security":[{"bearerAuth":[]},{"oauth2":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Pass the access token in the `Authorization` header:\n```\nAuthorization: Bearer YOUR_ACCESS_TOKEN\n```\n"},"oauth2":{"type":"oauth2","description":"OAuth 2.0 authentication using the Authorization Code or Client\nCredentials grant flow.\n","flows":{"authorizationCode":{"authorizationUrl":"https://www.movemint.cc/oauth/authorize","tokenUrl":"https://www.movemint.cc/oauth/token","refreshUrl":"https://www.movemint.cc/oauth/token","scopes":{}},"clientCredentials":{"tokenUrl":"https://www.movemint.cc/oauth/token","scopes":{}}}}},"parameters":{"EventHandle":{"name":"handle","in":"path","required":true,"description":"The unique handle (slug) of the event","schema":{"type":"string"}}},"schemas":{"WaveParticipantList":{"type":"object","required":["participants","total_count","page","per_page","total_pages"],"properties":{"participants":{"type":"array","items":{"type":"object","required":["id","first_name","last_name","email","confirmation_number","event_variant_id","wave_assignment"],"properties":{"id":{"type":"integer","format":"int64"},"first_name":{"type":"string","nullable":true},"last_name":{"type":"string","nullable":true},"email":{"type":"string","nullable":true},"confirmation_number":{"type":"string","nullable":true},"event_variant_id":{"type":"integer","format":"int64"},"wave_assignment":{"type":"object","nullable":true,"required":["wave_id","wave_name","wave_number"],"properties":{"wave_id":{"type":"integer","format":"int64"},"wave_name":{"type":"string","nullable":true},"wave_number":{"type":"string","nullable":true}}}}}},"total_count":{"type":"integer"},"page":{"type":"integer"},"per_page":{"type":"integer"},"total_pages":{"type":"integer"}}},"OAuthError":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Machine-readable error code"},"error_description":{"type":"string","description":"Human-readable description of the error"}}},"Error":{"type":"object","description":"A generic error response","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message"}}}},"responses":{"Unauthorized":{"description":"Unauthorized - invalid or missing token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"Forbidden":{"description":"Forbidden - user is not an admin of this event","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"EventNotFound":{"description":"Event not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/api/v1/events/{handle}/waves/participants":{"get":{"tags":["Waves"],"summary":"List participants with wave-assignment status","operationId":"listWaveParticipants","parameters":[{"$ref":"#/components/parameters/EventHandle"},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["assigned","unassigned"]}},{"name":"wave_id","in":"query","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"event_variant_id","in":"query","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"search","in":"query","required":false,"schema":{"type":"string"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1}},{"name":"sort","in":"query","required":false,"description":"Sort order: `wave` (by assigned wave) or `time:<question_id>` (by a time-based question's answer). Defaults to name.","schema":{"type":"string"}},{"name":"direction","in":"query","required":false,"schema":{"type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"Paginated participants","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WaveParticipantList"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/EventNotFound"}}}}}}
````

## Assign a participant to a wave

> Replaces any existing wave assignment for the participant.

````json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"tags":[{"name":"Waves","description":"Manage waves (start corrals / heats), assign and unassign participants,\nrun bulk auto-assignment, and configure wave-number settings. A wave with\nno linked sub-events applies to every sub-event (\"shared\"); linking\nsub-events restricts it to those. Waves can be capped, gender-restricted,\nand time-gated by a time-based custom question.\n"}],"servers":[{"url":"https://www.movemint.cc","description":"Production"}],"security":[{"bearerAuth":[]},{"oauth2":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Pass the access token in the `Authorization` header:\n```\nAuthorization: Bearer YOUR_ACCESS_TOKEN\n```\n"},"oauth2":{"type":"oauth2","description":"OAuth 2.0 authentication using the Authorization Code or Client\nCredentials grant flow.\n","flows":{"authorizationCode":{"authorizationUrl":"https://www.movemint.cc/oauth/authorize","tokenUrl":"https://www.movemint.cc/oauth/token","refreshUrl":"https://www.movemint.cc/oauth/token","scopes":{}},"clientCredentials":{"tokenUrl":"https://www.movemint.cc/oauth/token","scopes":{}}}}},"parameters":{"EventHandle":{"name":"handle","in":"path","required":true,"description":"The unique handle (slug) of the event","schema":{"type":"string"}}},"schemas":{"AssignParticipantRequest":{"type":"object","required":["participant_id","wave_id"],"properties":{"participant_id":{"type":"integer","format":"int64"},"wave_id":{"type":"integer","format":"int64"},"wave_number":{"type":"string","description":"Optional number within the wave. Auto-assigned when the event uses auto wave numbers and none is given."}}},"WaveAssignment":{"type":"object","required":["participant_id","wave_id","wave_number"],"properties":{"participant_id":{"type":"integer","format":"int64"},"wave_id":{"type":"integer","format":"int64"},"wave_number":{"type":"string","nullable":true}}},"OAuthError":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Machine-readable error code"},"error_description":{"type":"string","description":"Human-readable description of the error"}}},"Error":{"type":"object","description":"A generic error response","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message"}}},"ValidationError":{"type":"object","description":"A validation error response with a list of error messages","required":["errors"],"properties":{"errors":{"type":"array","items":{"type":"string"},"description":"List of validation error messages"}}}},"responses":{"Unauthorized":{"description":"Unauthorized - invalid or missing token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"Forbidden":{"description":"Forbidden - user is not an admin of this event","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"EventNotFound":{"description":"Event not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/api/v1/events/{handle}/wave_assignments":{"post":{"tags":["Waves"],"summary":"Assign a participant to a wave","operationId":"assignParticipantToWave","description":"Replaces any existing wave assignment for the participant.","parameters":[{"$ref":"#/components/parameters/EventHandle"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssignParticipantRequest"}}}},"responses":{"201":{"description":"Assigned","content":{"application/json":{"schema":{"type":"object","required":["wave_assignment"],"properties":{"wave_assignment":{"$ref":"#/components/schemas/WaveAssignment"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/EventNotFound"},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}}}}}}}
````

## DELETE /api/v1/events/{handle}/wave\_assignments

> Unassign every participant

````json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"tags":[{"name":"Waves","description":"Manage waves (start corrals / heats), assign and unassign participants,\nrun bulk auto-assignment, and configure wave-number settings. A wave with\nno linked sub-events applies to every sub-event (\"shared\"); linking\nsub-events restricts it to those. Waves can be capped, gender-restricted,\nand time-gated by a time-based custom question.\n"}],"servers":[{"url":"https://www.movemint.cc","description":"Production"}],"security":[{"bearerAuth":[]},{"oauth2":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Pass the access token in the `Authorization` header:\n```\nAuthorization: Bearer YOUR_ACCESS_TOKEN\n```\n"},"oauth2":{"type":"oauth2","description":"OAuth 2.0 authentication using the Authorization Code or Client\nCredentials grant flow.\n","flows":{"authorizationCode":{"authorizationUrl":"https://www.movemint.cc/oauth/authorize","tokenUrl":"https://www.movemint.cc/oauth/token","refreshUrl":"https://www.movemint.cc/oauth/token","scopes":{}},"clientCredentials":{"tokenUrl":"https://www.movemint.cc/oauth/token","scopes":{}}}}},"parameters":{"EventHandle":{"name":"handle","in":"path","required":true,"description":"The unique handle (slug) of the event","schema":{"type":"string"}}},"responses":{"Unauthorized":{"description":"Unauthorized - invalid or missing token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"Forbidden":{"description":"Forbidden - user is not an admin of this event","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"EventNotFound":{"description":"Event not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"OAuthError":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Machine-readable error code"},"error_description":{"type":"string","description":"Human-readable description of the error"}}},"Error":{"type":"object","description":"A generic error response","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message"}}}}},"paths":{"/api/v1/events/{handle}/wave_assignments":{"delete":{"tags":["Waves"],"summary":"Unassign every participant","operationId":"unassignAllFromWaves","parameters":[{"$ref":"#/components/parameters/EventHandle"}],"responses":{"200":{"description":"All assignments removed","content":{"application/json":{"schema":{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","enum":[true]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/EventNotFound"}}}}}}
````

## DELETE /api/v1/events/{handle}/wave\_assignments/{participant\_id}

> Unassign a participant from their wave

````json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"tags":[{"name":"Waves","description":"Manage waves (start corrals / heats), assign and unassign participants,\nrun bulk auto-assignment, and configure wave-number settings. A wave with\nno linked sub-events applies to every sub-event (\"shared\"); linking\nsub-events restricts it to those. Waves can be capped, gender-restricted,\nand time-gated by a time-based custom question.\n"}],"servers":[{"url":"https://www.movemint.cc","description":"Production"}],"security":[{"bearerAuth":[]},{"oauth2":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Pass the access token in the `Authorization` header:\n```\nAuthorization: Bearer YOUR_ACCESS_TOKEN\n```\n"},"oauth2":{"type":"oauth2","description":"OAuth 2.0 authentication using the Authorization Code or Client\nCredentials grant flow.\n","flows":{"authorizationCode":{"authorizationUrl":"https://www.movemint.cc/oauth/authorize","tokenUrl":"https://www.movemint.cc/oauth/token","refreshUrl":"https://www.movemint.cc/oauth/token","scopes":{}},"clientCredentials":{"tokenUrl":"https://www.movemint.cc/oauth/token","scopes":{}}}}},"parameters":{"EventHandle":{"name":"handle","in":"path","required":true,"description":"The unique handle (slug) of the event","schema":{"type":"string"}}},"responses":{"Unauthorized":{"description":"Unauthorized - invalid or missing token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"Forbidden":{"description":"Forbidden - user is not an admin of this event","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"EventNotFound":{"description":"Event not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"OAuthError":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Machine-readable error code"},"error_description":{"type":"string","description":"Human-readable description of the error"}}},"Error":{"type":"object","description":"A generic error response","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message"}}}}},"paths":{"/api/v1/events/{handle}/wave_assignments/{participant_id}":{"delete":{"tags":["Waves"],"summary":"Unassign a participant from their wave","operationId":"unassignParticipantFromWave","parameters":[{"$ref":"#/components/parameters/EventHandle"},{"name":"participant_id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Unassigned","content":{"application/json":{"schema":{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","enum":[true]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/EventNotFound"}}}}}}
````

## Bulk-assign participants by list

> Assigns many participants in one transaction (any error rolls back the\
> whole batch). Each entry identifies a participant by \`participant\_id\` or\
> \`confirmation\_number\`, and a wave by \`wave\_id\` or \`wave\_name\` (names are\
> created on the fly if they don't exist).<br>

````json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"tags":[{"name":"Waves","description":"Manage waves (start corrals / heats), assign and unassign participants,\nrun bulk auto-assignment, and configure wave-number settings. A wave with\nno linked sub-events applies to every sub-event (\"shared\"); linking\nsub-events restricts it to those. Waves can be capped, gender-restricted,\nand time-gated by a time-based custom question.\n"}],"servers":[{"url":"https://www.movemint.cc","description":"Production"}],"security":[{"bearerAuth":[]},{"oauth2":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Pass the access token in the `Authorization` header:\n```\nAuthorization: Bearer YOUR_ACCESS_TOKEN\n```\n"},"oauth2":{"type":"oauth2","description":"OAuth 2.0 authentication using the Authorization Code or Client\nCredentials grant flow.\n","flows":{"authorizationCode":{"authorizationUrl":"https://www.movemint.cc/oauth/authorize","tokenUrl":"https://www.movemint.cc/oauth/token","refreshUrl":"https://www.movemint.cc/oauth/token","scopes":{}},"clientCredentials":{"tokenUrl":"https://www.movemint.cc/oauth/token","scopes":{}}}}},"parameters":{"EventHandle":{"name":"handle","in":"path","required":true,"description":"The unique handle (slug) of the event","schema":{"type":"string"}}},"schemas":{"BulkWaveAssignmentRequest":{"type":"object","required":["assignments"],"properties":{"assignments":{"type":"array","minItems":1,"items":{"type":"object","description":"Identify the participant by id OR confirmation_number, and the wave by id OR name.","properties":{"participant_id":{"type":"integer","format":"int64"},"confirmation_number":{"type":"string"},"wave_id":{"type":"integer","format":"int64"},"wave_name":{"type":"string"},"wave_number":{"type":"string"}}}}}},"OAuthError":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Machine-readable error code"},"error_description":{"type":"string","description":"Human-readable description of the error"}}},"Error":{"type":"object","description":"A generic error response","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message"}}}},"responses":{"Unauthorized":{"description":"Unauthorized - invalid or missing token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"Forbidden":{"description":"Forbidden - user is not an admin of this event","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"EventNotFound":{"description":"Event not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/api/v1/events/{handle}/wave_assignments/bulk":{"post":{"tags":["Waves"],"summary":"Bulk-assign participants by list","operationId":"bulkAssignWaveParticipants","description":"Assigns many participants in one transaction (any error rolls back the\nwhole batch). Each entry identifies a participant by `participant_id` or\n`confirmation_number`, and a wave by `wave_id` or `wave_name` (names are\ncreated on the fly if they don't exist).\n","parameters":[{"$ref":"#/components/parameters/EventHandle"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkWaveAssignmentRequest"}}}},"responses":{"200":{"description":"Import summary","content":{"application/json":{"schema":{"type":"object","required":["created","moved","created_waves"],"properties":{"created":{"type":"integer"},"moved":{"type":"integer"},"created_waves":{"type":"integer"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/EventNotFound"},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}
````

## Bulk auto-assign participants into waves

> Orders candidate participants and drops each into the first eligible\
> public wave (walked top-to-bottom by position), honoring each wave's\
> sub-event links, gender restriction, time gate, and capacity. Use\
> \`dry\_run\` to preview without persisting.<br>

````json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"tags":[{"name":"Waves","description":"Manage waves (start corrals / heats), assign and unassign participants,\nrun bulk auto-assignment, and configure wave-number settings. A wave with\nno linked sub-events applies to every sub-event (\"shared\"); linking\nsub-events restricts it to those. Waves can be capped, gender-restricted,\nand time-gated by a time-based custom question.\n"}],"servers":[{"url":"https://www.movemint.cc","description":"Production"}],"security":[{"bearerAuth":[]},{"oauth2":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Pass the access token in the `Authorization` header:\n```\nAuthorization: Bearer YOUR_ACCESS_TOKEN\n```\n"},"oauth2":{"type":"oauth2","description":"OAuth 2.0 authentication using the Authorization Code or Client\nCredentials grant flow.\n","flows":{"authorizationCode":{"authorizationUrl":"https://www.movemint.cc/oauth/authorize","tokenUrl":"https://www.movemint.cc/oauth/token","refreshUrl":"https://www.movemint.cc/oauth/token","scopes":{}},"clientCredentials":{"tokenUrl":"https://www.movemint.cc/oauth/token","scopes":{}}}}},"parameters":{"EventHandle":{"name":"handle","in":"path","required":true,"description":"The unique handle (slug) of the event","schema":{"type":"string"}}},"schemas":{"WaveGenerationRequest":{"type":"object","properties":{"ordering":{"type":"string","enum":["registration_date","custom_question","name","age","random"],"description":"How candidates are ordered before filling waves. Defaults to registration_date."},"direction":{"type":"string","enum":["asc","desc"],"description":"asc fills front waves with earliest/fastest first. Defaults to asc."},"gender_mode":{"type":"string","enum":["none","separate_waves","order_within"]},"transactable_custom_question_id":{"type":"integer","format":"int64","description":"Required when ordering=custom_question. Orders by the answer to this time-based question."},"assign_wave_numbers":{"type":"boolean","description":"Defaults to the event's auto_assign_wave_numbers setting."},"overwrite":{"type":"boolean","description":"Re-assign everyone (clears existing public-wave assignments first). Defaults to false (fill unassigned only)."},"dry_run":{"type":"boolean","description":"Preview the result without persisting."}}},"WaveGenerationResult":{"type":"object","required":["assigned_count","overflow_count","dry_run","wave_summaries"],"properties":{"assigned_count":{"type":"integer"},"overflow_count":{"type":"integer"},"dry_run":{"type":"boolean"},"wave_summaries":{"type":"array","items":{"type":"object","required":["id","name","newly_assigned","existing_assigned","capacity"],"properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"newly_assigned":{"type":"integer"},"existing_assigned":{"type":"integer"},"capacity":{"type":"integer","nullable":true}}}}}},"OAuthError":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Machine-readable error code"},"error_description":{"type":"string","description":"Human-readable description of the error"}}},"Error":{"type":"object","description":"A generic error response","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message"}}}},"responses":{"Unauthorized":{"description":"Unauthorized - invalid or missing token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"Forbidden":{"description":"Forbidden - user is not an admin of this event","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"EventNotFound":{"description":"Event not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/api/v1/events/{handle}/wave_generation":{"post":{"tags":["Waves"],"summary":"Bulk auto-assign participants into waves","operationId":"generateWaveAssignments","description":"Orders candidate participants and drops each into the first eligible\npublic wave (walked top-to-bottom by position), honoring each wave's\nsub-event links, gender restriction, time gate, and capacity. Use\n`dry_run` to preview without persisting.\n","parameters":[{"$ref":"#/components/parameters/EventHandle"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WaveGenerationRequest"}}}},"responses":{"200":{"description":"Assignment result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WaveGenerationResult"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/EventNotFound"},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}
````

## GET /api/v1/events/{handle}/wave\_settings

> Get wave settings

````json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"tags":[{"name":"Waves","description":"Manage waves (start corrals / heats), assign and unassign participants,\nrun bulk auto-assignment, and configure wave-number settings. A wave with\nno linked sub-events applies to every sub-event (\"shared\"); linking\nsub-events restricts it to those. Waves can be capped, gender-restricted,\nand time-gated by a time-based custom question.\n"}],"servers":[{"url":"https://www.movemint.cc","description":"Production"}],"security":[{"bearerAuth":[]},{"oauth2":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Pass the access token in the `Authorization` header:\n```\nAuthorization: Bearer YOUR_ACCESS_TOKEN\n```\n"},"oauth2":{"type":"oauth2","description":"OAuth 2.0 authentication using the Authorization Code or Client\nCredentials grant flow.\n","flows":{"authorizationCode":{"authorizationUrl":"https://www.movemint.cc/oauth/authorize","tokenUrl":"https://www.movemint.cc/oauth/token","refreshUrl":"https://www.movemint.cc/oauth/token","scopes":{}},"clientCredentials":{"tokenUrl":"https://www.movemint.cc/oauth/token","scopes":{}}}}},"parameters":{"EventHandle":{"name":"handle","in":"path","required":true,"description":"The unique handle (slug) of the event","schema":{"type":"string"}}},"schemas":{"WaveSettings":{"type":"object","required":["uses_wave_numbers","auto_assign_wave_numbers","sub_events"],"properties":{"uses_wave_numbers":{"type":"boolean"},"auto_assign_wave_numbers":{"type":"boolean"},"sub_events":{"type":"array","items":{"type":"object","required":["id","name","auto_assign_waves"],"properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"auto_assign_waves":{"type":"boolean"}}}}}},"OAuthError":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Machine-readable error code"},"error_description":{"type":"string","description":"Human-readable description of the error"}}},"Error":{"type":"object","description":"A generic error response","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message"}}}},"responses":{"Unauthorized":{"description":"Unauthorized - invalid or missing token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"Forbidden":{"description":"Forbidden - user is not an admin of this event","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"EventNotFound":{"description":"Event not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/api/v1/events/{handle}/wave_settings":{"get":{"tags":["Waves"],"summary":"Get wave settings","operationId":"getWaveSettings","parameters":[{"$ref":"#/components/parameters/EventHandle"}],"responses":{"200":{"description":"Settings","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WaveSettings"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/EventNotFound"}}}}}}
````

## PATCH /api/v1/events/{handle}/wave\_settings

> Update wave settings

````json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"tags":[{"name":"Waves","description":"Manage waves (start corrals / heats), assign and unassign participants,\nrun bulk auto-assignment, and configure wave-number settings. A wave with\nno linked sub-events applies to every sub-event (\"shared\"); linking\nsub-events restricts it to those. Waves can be capped, gender-restricted,\nand time-gated by a time-based custom question.\n"}],"servers":[{"url":"https://www.movemint.cc","description":"Production"}],"security":[{"bearerAuth":[]},{"oauth2":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Pass the access token in the `Authorization` header:\n```\nAuthorization: Bearer YOUR_ACCESS_TOKEN\n```\n"},"oauth2":{"type":"oauth2","description":"OAuth 2.0 authentication using the Authorization Code or Client\nCredentials grant flow.\n","flows":{"authorizationCode":{"authorizationUrl":"https://www.movemint.cc/oauth/authorize","tokenUrl":"https://www.movemint.cc/oauth/token","refreshUrl":"https://www.movemint.cc/oauth/token","scopes":{}},"clientCredentials":{"tokenUrl":"https://www.movemint.cc/oauth/token","scopes":{}}}}},"parameters":{"EventHandle":{"name":"handle","in":"path","required":true,"description":"The unique handle (slug) of the event","schema":{"type":"string"}}},"schemas":{"WaveSettingsUpdateRequest":{"type":"object","properties":{"uses_wave_numbers":{"type":"boolean"},"auto_assign_wave_numbers":{"type":"boolean"},"variant_settings":{"type":"object","description":"Map of sub-event id (string) to a boolean auto_assign_waves flag.","additionalProperties":{"type":"boolean"}}}},"WaveSettings":{"type":"object","required":["uses_wave_numbers","auto_assign_wave_numbers","sub_events"],"properties":{"uses_wave_numbers":{"type":"boolean"},"auto_assign_wave_numbers":{"type":"boolean"},"sub_events":{"type":"array","items":{"type":"object","required":["id","name","auto_assign_waves"],"properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"auto_assign_waves":{"type":"boolean"}}}}}},"OAuthError":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Machine-readable error code"},"error_description":{"type":"string","description":"Human-readable description of the error"}}},"Error":{"type":"object","description":"A generic error response","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message"}}},"ValidationError":{"type":"object","description":"A validation error response with a list of error messages","required":["errors"],"properties":{"errors":{"type":"array","items":{"type":"string"},"description":"List of validation error messages"}}}},"responses":{"Unauthorized":{"description":"Unauthorized - invalid or missing token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"Forbidden":{"description":"Forbidden - user is not an admin of this event","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"EventNotFound":{"description":"Event not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/api/v1/events/{handle}/wave_settings":{"patch":{"tags":["Waves"],"summary":"Update wave settings","operationId":"updateWaveSettings","parameters":[{"$ref":"#/components/parameters/EventHandle"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WaveSettingsUpdateRequest"}}}},"responses":{"200":{"description":"Updated settings","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WaveSettings"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/EventNotFound"},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}}}}}}}
````


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://movemint.gitbook.io/movemint-developer-docs/open-api-specification/core-resources/waves.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
