> 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/models.md).

# Models

## The AuthorizationCodeGrantRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"AuthorizationCodeGrantRequest":{"type":"object","required":["grant_type","code","client_id","client_secret","redirect_uri"],"properties":{"grant_type":{"type":"string","enum":["authorization_code"]},"code":{"type":"string","description":"The authorization code received from the authorization endpoint"},"client_id":{"type":"string","description":"Your application's Client ID"},"client_secret":{"type":"string","description":"Your application's Client Secret"},"redirect_uri":{"type":"string","format":"uri","description":"The same redirect URI used in the authorization request"}}}}}}
```

## The RefreshTokenGrantRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"RefreshTokenGrantRequest":{"type":"object","required":["grant_type","refresh_token","client_id","client_secret"],"properties":{"grant_type":{"type":"string","enum":["refresh_token"]},"refresh_token":{"type":"string","description":"The refresh token issued alongside the access token"},"client_id":{"type":"string","description":"Your application's Client ID"},"client_secret":{"type":"string","description":"Your application's Client Secret"}}}}}}
```

## The ClientCredentialsGrantRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"ClientCredentialsGrantRequest":{"type":"object","required":["grant_type","client_id","client_secret"],"properties":{"grant_type":{"type":"string","enum":["client_credentials"]},"client_id":{"type":"string","description":"Your application's Client ID"},"client_secret":{"type":"string","description":"Your application's Client Secret"}}}}}}
```

## The TokenResponse object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"TokenResponse":{"type":"object","required":["access_token","token_type","expires_in","created_at"],"properties":{"access_token":{"type":"string","description":"The access token to use in API requests"},"token_type":{"type":"string","enum":["Bearer"],"description":"Always \"Bearer\""},"expires_in":{"type":"integer","description":"Token lifetime in seconds (default 7200 = 2 hours)"},"refresh_token":{"type":"string","description":"Token used to obtain a new access token when the current one expires. Not present for client_credentials grants."},"created_at":{"type":"integer","description":"Unix timestamp of when the token was created"}}}}}}
```

## The TokenInfo object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"TokenInfo":{"type":"object","required":["scopes","expires_in_seconds","application","created_at"],"properties":{"resource_owner_id":{"type":"integer","format":"int64","description":"The ID of the athlete who authorized the token"},"scopes":{"type":"array","items":{"type":"string"},"description":"List of scopes granted to this token"},"expires_in_seconds":{"type":"integer","description":"Seconds until the token expires"},"application":{"type":"object","properties":{"uid":{"type":"string","description":"The OAuth application's Client ID"}}},"created_at":{"type":"integer","description":"Unix timestamp of when the token was created"}}}}}}
```

## The OAuthError object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"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"}}}}}}
```

## The Athlete object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"Athlete":{"type":"object","description":"A Movemint user account","required":["id","first_name","last_name","email","handle","profile_picture","bio","dob","phone_number","gender_identity","city","state","country","zip_code","street_address","street_address_secondary","emergency_contact_name","emergency_contact_phone_number","event_director","created_at","updated_at"],"properties":{"id":{"type":"integer","format":"int64","description":"Unique identifier"},"first_name":{"type":"string","description":"First name"},"last_name":{"type":"string","description":"Last name"},"email":{"type":"string","format":"email","description":"Email address"},"handle":{"type":"string","description":"Unique handle (username)"},"profile_picture":{"type":"string","format":"uri","description":"URL of the user's profile picture"},"bio":{"type":"string","description":"User biography"},"dob":{"type":"string","format":"date","nullable":true,"description":"Date of birth (YYYY-MM-DD)"},"phone_number":{"type":"string","description":"Phone number"},"gender_identity":{"type":"integer","nullable":true,"description":"Gender identity enum value"},"city":{"type":"string","description":"City"},"state":{"type":"integer","nullable":true,"description":"State enum value"},"country":{"type":"integer","nullable":true,"description":"Country enum value"},"zip_code":{"type":"string","description":"ZIP or postal code"},"street_address":{"type":"string","description":"Street address (line 1)"},"street_address_secondary":{"type":"string","description":"Street address (line 2)"},"emergency_contact_name":{"type":"string","description":"Emergency contact name"},"emergency_contact_phone_number":{"type":"string","description":"Emergency contact phone number"},"event_director":{"type":"boolean","description":"Whether the user is an event director"},"created_at":{"type":"string","format":"date-time","description":"Account creation timestamp"},"updated_at":{"type":"string","format":"date-time","description":"Last update timestamp"}}}}}}
```

## The EventSummary object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"EventSummary":{"type":"object","description":"Compact list-view representation of an event, returned by\n`GET /api/v1/events`. All properties are always present; nullable\nproperties may have a null value.\n","required":["id","handle","name","status","start_date","end_date","city","state"],"properties":{"id":{"type":"integer","description":"Unique event identifier"},"handle":{"type":"string","description":"URL-safe unique identifier used to address the event on other endpoints"},"name":{"type":"string","nullable":true,"description":"Event name"},"status":{"type":"string","description":"Event lifecycle status"},"start_date":{"type":"string","format":"date","nullable":true,"description":"Event start date (YYYY-MM-DD)"},"end_date":{"type":"string","format":"date","nullable":true,"description":"Event end date (YYYY-MM-DD)"},"city":{"type":"string","nullable":true,"description":"Event city"},"state":{"type":"string","nullable":true,"description":"Event state or region"}}}}}}
```

## The Event object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"Event":{"type":"object","description":"An event on the Movemint platform. All properties are always present in the response; nullable properties may have a null value.","required":["id","name","latitude","longitude","start_date","end_date","sport_type","registration_open_date","registration_close_date","phone_number","email","website","description","max_participants","address","city","state","zip","presented_by","handle","created_at","updated_at","blurb","custom_waiver","status","collect_gender_identity","option_nonbinary","option_prefer_not_to_say","instagram_url","strava_club_url","x_url","facebook_url","donation_goal_cents","registration_included_in_donation_goal","currency","volunteer_message","allow_participant_transfer","participant_transfer_close_date","country","tax_address","collect_phone_number","collect_dob","collect_address","collect_emergency_contact","peer_to_peer_fundraiser","merchandise_tax_rate","service_fee_tax_rate","registration_tax_rate","stripe_account_id","onboarding_step","new_participant_owner_email_setting","show_signup_count","protecht_enabled","send_participant_confirmation_emails","teams_enabled","show_teams_on_start_list","show_teams_on_results","show_relay_teams_on_start_list","timezone","email_owner_on_merchandise_order","email_check_in_confirmation","team_password_setting","sms_enabled","is_free","show_start_list","event_cancellation_insurance_enabled","last_transaction_date","allow_event_variant_transfers","partner_program_eligible","show_event_variant_price_schedule","require_one_sub_event","frictionless_protecht","buy_now_pay_later","show_location","merchandise_store_close_date_time_utc","presale_registration_open_date","presale_registration_code","write_to_strava_activity_on_finish","tax_exempt","name_with_start_date","formatted_start_date","name_with_year"],"properties":{"id":{"type":"integer","format":"int64","description":"Unique identifier"},"name":{"type":"string","description":"Event name"},"latitude":{"type":"string","description":"Venue latitude (decimal as string for precision)"},"longitude":{"type":"string","description":"Venue longitude (decimal as string for precision)"},"start_date":{"type":"string","format":"date-time","description":"Event start date and time (UTC)"},"end_date":{"type":"string","format":"date-time","nullable":true,"description":"Event end date and time (UTC), if applicable"},"sport_type":{"type":"string","description":"Type of sport"},"registration_open_date":{"type":"string","format":"date-time","description":"When registration opens (UTC)"},"registration_close_date":{"type":"string","format":"date-time","nullable":true,"description":"When registration closes (UTC)"},"phone_number":{"type":"string","nullable":true,"description":"Contact phone number"},"email":{"type":"string","format":"email","description":"Contact email for the event"},"website":{"type":"string","format":"uri","description":"Event website URL"},"description":{"type":"string","description":"Full event description (may contain HTML)"},"max_participants":{"type":"integer","nullable":true,"description":"Maximum number of participants allowed; null if unlimited"},"address":{"type":"string","description":"Venue address or venue name"},"city":{"type":"string","description":"City"},"state":{"type":"integer","description":"State enum value (e.g. 21 for Massachusetts)"},"zip":{"type":"string","description":"ZIP or postal code"},"presented_by":{"type":"string","nullable":true,"description":"Presenting sponsor or organization name"},"handle":{"type":"string","description":"Unique URL-safe handle used in paths"},"created_at":{"type":"string","format":"date-time","description":"Record creation timestamp (UTC)"},"updated_at":{"type":"string","format":"date-time","description":"Last update timestamp (UTC)"},"blurb":{"type":"string","description":"Short event summary"},"custom_waiver":{"type":"string","nullable":true,"description":"Custom waiver text shown during registration"},"status":{"type":"string","enum":["draft","live","unlisted","landing_page","past_event"],"description":"Event visibility/status"},"collect_gender_identity":{"type":"boolean","description":"Whether gender identity is collected during registration"},"option_nonbinary":{"type":"boolean","description":"Whether non-binary is offered as a gender identity option"},"option_prefer_not_to_say":{"type":"boolean","description":"Whether \"prefer not to say\" is offered for gender identity"},"instagram_url":{"type":"string","format":"uri","nullable":true,"description":"Instagram profile URL"},"strava_club_url":{"type":"string","format":"uri","nullable":true,"description":"Strava club URL"},"x_url":{"type":"string","format":"uri","nullable":true,"description":"X (Twitter) profile URL"},"facebook_url":{"type":"string","format":"uri","nullable":true,"description":"Facebook page URL"},"donation_goal_cents":{"type":"integer","format":"int64","nullable":true,"description":"Donation goal in cents, if fundraising is enabled"},"registration_included_in_donation_goal":{"type":"boolean","description":"Whether registration revenue counts toward donation goal"},"currency":{"type":"string","description":"ISO 4217 currency code"},"volunteer_message":{"type":"string","nullable":true,"description":"Message or instructions for volunteers"},"allow_participant_transfer":{"type":"boolean","description":"Whether participant transfers are allowed"},"participant_transfer_close_date":{"type":"string","format":"date-time","nullable":true,"description":"Deadline for participant transfers (UTC)"},"country":{"type":"integer","description":"Country enum value (e.g. 187 for United States)"},"tax_address":{"type":"string","nullable":true,"description":"Address used for tax purposes"},"collect_phone_number":{"type":"boolean","description":"Whether phone number is collected during registration"},"collect_dob":{"type":"boolean","description":"Whether date of birth is collected during registration"},"collect_address":{"type":"boolean","description":"Whether address is collected during registration"},"collect_emergency_contact":{"type":"boolean","description":"Whether emergency contact is collected during registration"},"peer_to_peer_fundraiser":{"type":"boolean","description":"Whether peer-to-peer fundraising is enabled"},"merchandise_tax_rate":{"type":"string","nullable":true,"description":"Tax rate for merchandise (decimal as string, e.g. 0.0)"},"service_fee_tax_rate":{"type":"string","nullable":true,"description":"Tax rate for service fees (decimal as string, e.g. 0.0625)"},"registration_tax_rate":{"type":"string","nullable":true,"description":"Tax rate for registration (decimal as string)"},"stripe_account_id":{"type":"integer","format":"int64","nullable":true,"description":"Stripe Connect account ID when connected"},"onboarding_step":{"type":"integer","nullable":true,"description":"Current step in event onboarding flow"},"new_participant_owner_email_setting":{"type":"string","enum":["never_email_owner","email_owner_every_participant"],"description":"When the event owner is emailed about new participants"},"show_signup_count":{"type":"boolean","description":"Whether the signup count is publicly visible"},"protecht_enabled":{"type":"boolean","description":"Whether event cancellation insurance (Protecht) is offered"},"send_participant_confirmation_emails":{"type":"boolean","description":"Whether confirmation emails are sent to participants"},"teams_enabled":{"type":"boolean","description":"Whether team registration is enabled"},"show_teams_on_start_list":{"type":"boolean","description":"Whether teams are shown on the start list"},"show_teams_on_results":{"type":"boolean","description":"Whether teams are shown on results"},"show_relay_teams_on_start_list":{"type":"boolean","description":"Whether relay teams are shown on the start list"},"timezone":{"type":"string","description":"IANA timezone string"},"email_owner_on_merchandise_order":{"type":"boolean","description":"Whether the owner is emailed on merchandise orders"},"email_check_in_confirmation":{"type":"boolean","description":"Whether check-in confirmation emails are sent"},"team_password_setting":{"type":"string","enum":["no_password","optional","required"],"description":"Whether team join requires a password"},"sms_enabled":{"type":"boolean","description":"Whether SMS notifications are enabled"},"is_free":{"type":"boolean","description":"Whether the event is free to register"},"show_start_list":{"type":"boolean","description":"Whether the start list is publicly visible"},"event_cancellation_insurance_enabled":{"type":"boolean","description":"Whether event cancellation insurance is enabled"},"last_transaction_date":{"type":"string","format":"date-time","nullable":true,"description":"Timestamp of last transaction (UTC)"},"allow_event_variant_transfers":{"type":"boolean","description":"Whether transfers between event variants are allowed"},"partner_program_eligible":{"type":"boolean","description":"Whether the event is eligible for partner program"},"show_event_variant_price_schedule":{"type":"boolean","description":"Whether event variant price schedule is shown"},"require_one_sub_event":{"type":"boolean","description":"Whether participant must choose at least one sub-event"},"frictionless_protecht":{"type":"boolean","description":"Whether frictionless Protecht signup is enabled"},"buy_now_pay_later":{"type":"boolean","description":"Whether buy-now-pay-later is offered"},"show_location":{"type":"boolean","description":"Whether the event location is shown publicly"},"merchandise_store_close_date_time_utc":{"type":"string","format":"date-time","nullable":true,"description":"When the merchandise store closes (UTC)"},"presale_registration_open_date":{"type":"string","format":"date-time","nullable":true,"description":"When presale registration opens (UTC)"},"presale_registration_code":{"type":"string","nullable":true,"description":"Code required for presale registration"},"write_to_strava_activity_on_finish":{"type":"boolean","description":"Whether finishing writes to Strava activity"},"tax_exempt":{"type":"boolean","description":"Whether the event is tax exempt"},"name_with_start_date":{"type":"string","description":"Event name combined with formatted start date"},"formatted_start_date":{"type":"string","description":"Human-readable formatted start date"},"name_with_year":{"type":"string","description":"Event name with year"}}}}}}
```

## The EventParticipant object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"EventParticipant":{"type":"object","description":"A registered participant for an event. Includes nested event details,\nevent variant, merchandise orders, and custom question answers.\n","required":["id","athlete_id","event_variant_id","confirmation_number","first_name","last_name","email","phone_number","dob","gender_identity","gender_name","phone_number_with_country_code","street_address","street_address_secondary","city","state","country","zip_code","country_code","emergency_contact_name","emergency_contact_phone_number","emergency_contact_phone_country_code","amount_paid_cents","stripe_checkout_id","stripe_receipt_url","stripe_receipt_number","bib_number","checked_in","registration_source","sms_opt_in","signed_waiver_at","confirmation_page","created_at","updated_at","event","event_variant","merchandise_orders","custom_question_text_answers"],"properties":{"id":{"type":"integer","format":"int64","description":"Unique identifier"},"athlete_id":{"type":"integer","format":"int64","nullable":true,"description":"ID of the associated athlete account (if linked)"},"event_variant_id":{"type":"integer","format":"int64","description":"ID of the event variant (ticket type) the participant registered for"},"confirmation_number":{"type":"string","description":"Unique registration confirmation number (always present for saved records)"},"first_name":{"type":"string","description":"Participant's first name"},"last_name":{"type":"string","description":"Participant's last name"},"email":{"type":"string","format":"email","description":"Participant's email address"},"phone_number":{"type":"string","description":"Participant's phone number"},"dob":{"type":"string","format":"date","nullable":true,"description":"Date of birth (YYYY-MM-DD)"},"gender_identity":{"type":"integer","nullable":true,"description":"Gender identity enum value"},"gender_name":{"type":"string","description":"Human-readable gender name"},"phone_number_with_country_code":{"type":"string","description":"Full phone number including country code"},"street_address":{"type":"string","description":"Street address (line 1)"},"street_address_secondary":{"type":"string","description":"Street address (line 2)"},"city":{"type":"string","description":"City"},"state":{"type":"integer","nullable":true,"description":"State enum value"},"country":{"type":"integer","nullable":true,"description":"Country enum value"},"zip_code":{"type":"string","description":"ZIP or postal code"},"country_code":{"type":"integer","nullable":true,"description":"Phone country code"},"emergency_contact_name":{"type":"string","description":"Emergency contact full name"},"emergency_contact_phone_number":{"type":"string","description":"Emergency contact phone number"},"emergency_contact_phone_country_code":{"type":"integer","nullable":true,"description":"Emergency contact phone country code"},"amount_paid_cents":{"type":"integer","nullable":true,"description":"Total amount paid in cents"},"stripe_checkout_id":{"type":"string","description":"Stripe Checkout session ID"},"stripe_receipt_url":{"type":"string","format":"uri","description":"URL to the Stripe payment receipt"},"stripe_receipt_number":{"type":"string","description":"Stripe receipt number"},"bib_number":{"type":"integer","nullable":true,"description":"Assigned bib number (if applicable)"},"checked_in":{"type":"boolean","description":"Whether the participant has been checked in at the event"},"registration_source":{"type":"integer","description":"How the participant was registered (enum value)"},"sms_opt_in":{"type":"boolean","description":"Whether the participant opted in to SMS notifications"},"signed_waiver_at":{"type":"string","format":"date-time","nullable":true,"description":"When the participant signed the waiver"},"confirmation_page":{"type":"string","format":"uri","description":"URL to the participant's confirmation page"},"created_at":{"type":"string","format":"date-time","description":"Registration timestamp"},"updated_at":{"type":"string","format":"date-time","description":"Last update timestamp"},"event":{"type":"object","description":"Summary of the parent event","required":["handle","name","start_date","event_page_url"],"properties":{"handle":{"type":"string","description":"Event handle"},"name":{"type":"string","description":"Event name"},"start_date":{"type":"string","format":"date-time","nullable":true,"description":"Event start date"},"event_page_url":{"type":"string","format":"uri","description":"Public URL of the event page"}}},"event_variant":{"type":"object","description":"The ticket type / variant the participant registered for","required":["id","name"],"properties":{"id":{"type":"integer","format":"int64","description":"Event variant ID"},"name":{"type":"string","description":"Event variant name"}}},"merchandise_orders":{"type":"array","description":"Merchandise orders placed during registration","items":{"$ref":"#/components/schemas/MerchandiseOrder"}},"custom_question_text_answers":{"type":"array","description":"Answers to custom registration questions","items":{"$ref":"#/components/schemas/CustomQuestionAnswer"}},"financials":{"description":"Per-registration money breakdown, in integer cents. Only present\nwhen the authenticated user is a full admin or owner of the event;\nomitted entirely for other admin roles.\n","$ref":"#/components/schemas/ParticipantFinancials"}}},"MerchandiseOrder":{"type":"object","description":"A merchandise order placed during event registration","required":["id","merchandise_id","merchandise_option_id","athlete_id","confirmation_number","stripe_checkout_id","stripe_receipt_url","stripe_receipt_number","amount_paid_cents","first_name","last_name","email","created_at","updated_at","merchandise","merchandise_option"],"properties":{"id":{"type":"integer","format":"int64","description":"Unique identifier"},"merchandise_id":{"type":"integer","format":"int64","description":"ID of the merchandise item"},"merchandise_option_id":{"type":"integer","format":"int64","nullable":true,"description":"ID of the selected merchandise option (e.g., size)"},"athlete_id":{"type":"integer","format":"int64","nullable":true,"description":"ID of the athlete who placed the order"},"confirmation_number":{"type":"string","description":"Order confirmation number"},"stripe_checkout_id":{"type":"string","description":"Stripe Checkout session ID"},"stripe_receipt_url":{"type":"string","format":"uri","description":"URL to the Stripe payment receipt"},"stripe_receipt_number":{"type":"string","description":"Stripe receipt number"},"amount_paid_cents":{"type":"integer","nullable":true,"description":"Amount paid in cents"},"first_name":{"type":"string","description":"Buyer's first name"},"last_name":{"type":"string","description":"Buyer's last name"},"email":{"type":"string","format":"email","description":"Buyer's email address"},"created_at":{"type":"string","format":"date-time","description":"Order creation timestamp"},"updated_at":{"type":"string","format":"date-time","description":"Last update timestamp"},"merchandise":{"type":"object","description":"The merchandise item","required":["id","name"],"properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"}}},"merchandise_option":{"type":"object","description":"The selected option (e.g., size, color)","required":["id","name"],"properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"}}}}},"CustomQuestionAnswer":{"type":"object","description":"A participant's answer to a custom registration question. In addition\nto the standard fields, the response includes a dynamic key derived\nfrom the question title (camelCase) mapped to the answer value.\n","required":["id","question","answer","question_answer","created_at","updated_at"],"properties":{"id":{"type":"integer","format":"int64","description":"Answer record ID"},"question":{"type":"string","description":"The question text"},"answer":{"type":"string","description":"The participant's answer"},"question_answer":{"type":"object","description":"A single-entry object mapping the question text to the answer","additionalProperties":{"type":"string"}},"created_at":{"type":"string","format":"date-time","description":"Record creation timestamp"},"updated_at":{"type":"string","format":"date-time","description":"Last update timestamp"}}},"ParticipantFinancials":{"type":"object","description":"Per-registration money breakdown, all in integer cents. Each value is\n0 when the corresponding adjustment does not apply to the registration.\n\nThe deductions (`discount_cents`, `credit_cents`, `gift_card_cents`,\n`referral_credit_cents`) are disjoint — a given amount is reported under\nexactly one of them, so they can be summed.\n","required":["discount_cents","credit_cents","gift_card_cents","referral_credit_cents","tax_cents","service_fee_cents"],"properties":{"discount_cents":{"type":"integer","description":"Amount discounted via a redeemed discount code. A discount that came from a\nreferral link is reported under `referral_credit_cents` instead.\n"},"credit_cents":{"type":"integer","description":"Account credit applied to the registration."},"gift_card_cents":{"type":"integer","description":"Gift card value applied to the registration."},"referral_credit_cents":{"type":"integer","description":"Amount discounted because the registrant used a referral link. 0 if they\nreplaced the referral with their own discount code, which is reported\nunder `discount_cents`.\n"},"tax_cents":{"type":"integer","description":"Sales tax charged on the registration."},"service_fee_cents":{"type":"integer","description":"Platform / service fee for the registration (flat plus percentage)."}}}}}}
```

## The ParticipantFinancials object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"ParticipantFinancials":{"type":"object","description":"Per-registration money breakdown, all in integer cents. Each value is\n0 when the corresponding adjustment does not apply to the registration.\n\nThe deductions (`discount_cents`, `credit_cents`, `gift_card_cents`,\n`referral_credit_cents`) are disjoint — a given amount is reported under\nexactly one of them, so they can be summed.\n","required":["discount_cents","credit_cents","gift_card_cents","referral_credit_cents","tax_cents","service_fee_cents"],"properties":{"discount_cents":{"type":"integer","description":"Amount discounted via a redeemed discount code. A discount that came from a\nreferral link is reported under `referral_credit_cents` instead.\n"},"credit_cents":{"type":"integer","description":"Account credit applied to the registration."},"gift_card_cents":{"type":"integer","description":"Gift card value applied to the registration."},"referral_credit_cents":{"type":"integer","description":"Amount discounted because the registrant used a referral link. 0 if they\nreplaced the referral with their own discount code, which is reported\nunder `discount_cents`.\n"},"tax_cents":{"type":"integer","description":"Sales tax charged on the registration."},"service_fee_cents":{"type":"integer","description":"Platform / service fee for the registration (flat plus percentage)."}}}}}}
```

## The MerchandiseOrder object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"MerchandiseOrder":{"type":"object","description":"A merchandise order placed during event registration","required":["id","merchandise_id","merchandise_option_id","athlete_id","confirmation_number","stripe_checkout_id","stripe_receipt_url","stripe_receipt_number","amount_paid_cents","first_name","last_name","email","created_at","updated_at","merchandise","merchandise_option"],"properties":{"id":{"type":"integer","format":"int64","description":"Unique identifier"},"merchandise_id":{"type":"integer","format":"int64","description":"ID of the merchandise item"},"merchandise_option_id":{"type":"integer","format":"int64","nullable":true,"description":"ID of the selected merchandise option (e.g., size)"},"athlete_id":{"type":"integer","format":"int64","nullable":true,"description":"ID of the athlete who placed the order"},"confirmation_number":{"type":"string","description":"Order confirmation number"},"stripe_checkout_id":{"type":"string","description":"Stripe Checkout session ID"},"stripe_receipt_url":{"type":"string","format":"uri","description":"URL to the Stripe payment receipt"},"stripe_receipt_number":{"type":"string","description":"Stripe receipt number"},"amount_paid_cents":{"type":"integer","nullable":true,"description":"Amount paid in cents"},"first_name":{"type":"string","description":"Buyer's first name"},"last_name":{"type":"string","description":"Buyer's last name"},"email":{"type":"string","format":"email","description":"Buyer's email address"},"created_at":{"type":"string","format":"date-time","description":"Order creation timestamp"},"updated_at":{"type":"string","format":"date-time","description":"Last update timestamp"},"merchandise":{"type":"object","description":"The merchandise item","required":["id","name"],"properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"}}},"merchandise_option":{"type":"object","description":"The selected option (e.g., size, color)","required":["id","name"],"properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"}}}}}}}}
```

## The CustomQuestionAnswer object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"CustomQuestionAnswer":{"type":"object","description":"A participant's answer to a custom registration question. In addition\nto the standard fields, the response includes a dynamic key derived\nfrom the question title (camelCase) mapped to the answer value.\n","required":["id","question","answer","question_answer","created_at","updated_at"],"properties":{"id":{"type":"integer","format":"int64","description":"Answer record ID"},"question":{"type":"string","description":"The question text"},"answer":{"type":"string","description":"The participant's answer"},"question_answer":{"type":"object","description":"A single-entry object mapping the question text to the answer","additionalProperties":{"type":"string"}},"created_at":{"type":"string","format":"date-time","description":"Record creation timestamp"},"updated_at":{"type":"string","format":"date-time","description":"Last update timestamp"}}}}}}
```

## The WebhookSubscription object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"WebhookSubscription":{"type":"object","description":"A webhook subscription that receives event notifications via HTTP POST.\n","required":["id","url","oauth_application_uid","athlete_id","created_at","updated_at"],"properties":{"id":{"type":"integer","format":"int64","description":"Unique identifier"},"url":{"type":"string","format":"uri","description":"The URL that receives webhook POST requests"},"secret":{"type":"string","description":"HMAC-SHA256 signing secret. Use this to verify the `X-Signature`\nheader on incoming webhook deliveries. **This value is only\nreturned when the subscription is first created.** Always present in create response.\n"},"oauth_application_uid":{"type":"string","description":"The UID of the OAuth application this subscription belongs to"},"athlete_id":{"type":"integer","format":"int64","nullable":true,"description":"ID of the athlete who created the subscription"},"created_at":{"type":"string","format":"date-time","description":"Creation timestamp"},"updated_at":{"type":"string","format":"date-time","description":"Last update timestamp"}}}}}}
```

## The WebhookEvent object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"WebhookEvent":{"type":"object","description":"The payload delivered to webhook subscription URLs. Currently the only\nsupported event type is `event.participant.created`.\n","required":["type","data"],"properties":{"type":{"type":"string","description":"The event type identifier","enum":["event.participant.created"]},"data":{"type":"object","required":["object"],"properties":{"object":{"$ref":"#/components/schemas/EventParticipant"}}}}},"EventParticipant":{"type":"object","description":"A registered participant for an event. Includes nested event details,\nevent variant, merchandise orders, and custom question answers.\n","required":["id","athlete_id","event_variant_id","confirmation_number","first_name","last_name","email","phone_number","dob","gender_identity","gender_name","phone_number_with_country_code","street_address","street_address_secondary","city","state","country","zip_code","country_code","emergency_contact_name","emergency_contact_phone_number","emergency_contact_phone_country_code","amount_paid_cents","stripe_checkout_id","stripe_receipt_url","stripe_receipt_number","bib_number","checked_in","registration_source","sms_opt_in","signed_waiver_at","confirmation_page","created_at","updated_at","event","event_variant","merchandise_orders","custom_question_text_answers"],"properties":{"id":{"type":"integer","format":"int64","description":"Unique identifier"},"athlete_id":{"type":"integer","format":"int64","nullable":true,"description":"ID of the associated athlete account (if linked)"},"event_variant_id":{"type":"integer","format":"int64","description":"ID of the event variant (ticket type) the participant registered for"},"confirmation_number":{"type":"string","description":"Unique registration confirmation number (always present for saved records)"},"first_name":{"type":"string","description":"Participant's first name"},"last_name":{"type":"string","description":"Participant's last name"},"email":{"type":"string","format":"email","description":"Participant's email address"},"phone_number":{"type":"string","description":"Participant's phone number"},"dob":{"type":"string","format":"date","nullable":true,"description":"Date of birth (YYYY-MM-DD)"},"gender_identity":{"type":"integer","nullable":true,"description":"Gender identity enum value"},"gender_name":{"type":"string","description":"Human-readable gender name"},"phone_number_with_country_code":{"type":"string","description":"Full phone number including country code"},"street_address":{"type":"string","description":"Street address (line 1)"},"street_address_secondary":{"type":"string","description":"Street address (line 2)"},"city":{"type":"string","description":"City"},"state":{"type":"integer","nullable":true,"description":"State enum value"},"country":{"type":"integer","nullable":true,"description":"Country enum value"},"zip_code":{"type":"string","description":"ZIP or postal code"},"country_code":{"type":"integer","nullable":true,"description":"Phone country code"},"emergency_contact_name":{"type":"string","description":"Emergency contact full name"},"emergency_contact_phone_number":{"type":"string","description":"Emergency contact phone number"},"emergency_contact_phone_country_code":{"type":"integer","nullable":true,"description":"Emergency contact phone country code"},"amount_paid_cents":{"type":"integer","nullable":true,"description":"Total amount paid in cents"},"stripe_checkout_id":{"type":"string","description":"Stripe Checkout session ID"},"stripe_receipt_url":{"type":"string","format":"uri","description":"URL to the Stripe payment receipt"},"stripe_receipt_number":{"type":"string","description":"Stripe receipt number"},"bib_number":{"type":"integer","nullable":true,"description":"Assigned bib number (if applicable)"},"checked_in":{"type":"boolean","description":"Whether the participant has been checked in at the event"},"registration_source":{"type":"integer","description":"How the participant was registered (enum value)"},"sms_opt_in":{"type":"boolean","description":"Whether the participant opted in to SMS notifications"},"signed_waiver_at":{"type":"string","format":"date-time","nullable":true,"description":"When the participant signed the waiver"},"confirmation_page":{"type":"string","format":"uri","description":"URL to the participant's confirmation page"},"created_at":{"type":"string","format":"date-time","description":"Registration timestamp"},"updated_at":{"type":"string","format":"date-time","description":"Last update timestamp"},"event":{"type":"object","description":"Summary of the parent event","required":["handle","name","start_date","event_page_url"],"properties":{"handle":{"type":"string","description":"Event handle"},"name":{"type":"string","description":"Event name"},"start_date":{"type":"string","format":"date-time","nullable":true,"description":"Event start date"},"event_page_url":{"type":"string","format":"uri","description":"Public URL of the event page"}}},"event_variant":{"type":"object","description":"The ticket type / variant the participant registered for","required":["id","name"],"properties":{"id":{"type":"integer","format":"int64","description":"Event variant ID"},"name":{"type":"string","description":"Event variant name"}}},"merchandise_orders":{"type":"array","description":"Merchandise orders placed during registration","items":{"$ref":"#/components/schemas/MerchandiseOrder"}},"custom_question_text_answers":{"type":"array","description":"Answers to custom registration questions","items":{"$ref":"#/components/schemas/CustomQuestionAnswer"}},"financials":{"description":"Per-registration money breakdown, in integer cents. Only present\nwhen the authenticated user is a full admin or owner of the event;\nomitted entirely for other admin roles.\n","$ref":"#/components/schemas/ParticipantFinancials"}}},"MerchandiseOrder":{"type":"object","description":"A merchandise order placed during event registration","required":["id","merchandise_id","merchandise_option_id","athlete_id","confirmation_number","stripe_checkout_id","stripe_receipt_url","stripe_receipt_number","amount_paid_cents","first_name","last_name","email","created_at","updated_at","merchandise","merchandise_option"],"properties":{"id":{"type":"integer","format":"int64","description":"Unique identifier"},"merchandise_id":{"type":"integer","format":"int64","description":"ID of the merchandise item"},"merchandise_option_id":{"type":"integer","format":"int64","nullable":true,"description":"ID of the selected merchandise option (e.g., size)"},"athlete_id":{"type":"integer","format":"int64","nullable":true,"description":"ID of the athlete who placed the order"},"confirmation_number":{"type":"string","description":"Order confirmation number"},"stripe_checkout_id":{"type":"string","description":"Stripe Checkout session ID"},"stripe_receipt_url":{"type":"string","format":"uri","description":"URL to the Stripe payment receipt"},"stripe_receipt_number":{"type":"string","description":"Stripe receipt number"},"amount_paid_cents":{"type":"integer","nullable":true,"description":"Amount paid in cents"},"first_name":{"type":"string","description":"Buyer's first name"},"last_name":{"type":"string","description":"Buyer's last name"},"email":{"type":"string","format":"email","description":"Buyer's email address"},"created_at":{"type":"string","format":"date-time","description":"Order creation timestamp"},"updated_at":{"type":"string","format":"date-time","description":"Last update timestamp"},"merchandise":{"type":"object","description":"The merchandise item","required":["id","name"],"properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"}}},"merchandise_option":{"type":"object","description":"The selected option (e.g., size, color)","required":["id","name"],"properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"}}}}},"CustomQuestionAnswer":{"type":"object","description":"A participant's answer to a custom registration question. In addition\nto the standard fields, the response includes a dynamic key derived\nfrom the question title (camelCase) mapped to the answer value.\n","required":["id","question","answer","question_answer","created_at","updated_at"],"properties":{"id":{"type":"integer","format":"int64","description":"Answer record ID"},"question":{"type":"string","description":"The question text"},"answer":{"type":"string","description":"The participant's answer"},"question_answer":{"type":"object","description":"A single-entry object mapping the question text to the answer","additionalProperties":{"type":"string"}},"created_at":{"type":"string","format":"date-time","description":"Record creation timestamp"},"updated_at":{"type":"string","format":"date-time","description":"Last update timestamp"}}},"ParticipantFinancials":{"type":"object","description":"Per-registration money breakdown, all in integer cents. Each value is\n0 when the corresponding adjustment does not apply to the registration.\n\nThe deductions (`discount_cents`, `credit_cents`, `gift_card_cents`,\n`referral_credit_cents`) are disjoint — a given amount is reported under\nexactly one of them, so they can be summed.\n","required":["discount_cents","credit_cents","gift_card_cents","referral_credit_cents","tax_cents","service_fee_cents"],"properties":{"discount_cents":{"type":"integer","description":"Amount discounted via a redeemed discount code. A discount that came from a\nreferral link is reported under `referral_credit_cents` instead.\n"},"credit_cents":{"type":"integer","description":"Account credit applied to the registration."},"gift_card_cents":{"type":"integer","description":"Gift card value applied to the registration."},"referral_credit_cents":{"type":"integer","description":"Amount discounted because the registrant used a referral link. 0 if they\nreplaced the referral with their own discount code, which is reported\nunder `discount_cents`.\n"},"tax_cents":{"type":"integer","description":"Sales tax charged on the registration."},"service_fee_cents":{"type":"integer","description":"Platform / service fee for the registration (flat plus percentage)."}}}}}}
```

## The EventResult object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"EventResult":{"type":"object","description":"A result container for a race within an event (e.g., \"5K\", \"10K\").\nEach event can have multiple event results.\n","required":["id","event_id","event_variant_id","name","result_type","time_precision","distance","distance_unit","pace_type","pace_unit","effective_pace_unit","split_time_basis","show_pace","last_place_celebration","finisher_count","created_at","updated_at"],"properties":{"id":{"type":"integer","format":"int64","description":"Unique identifier"},"event_id":{"type":"integer","format":"int64","description":"ID of the parent event"},"event_variant_id":{"type":"integer","format":"int64","nullable":true,"description":"ID of the associated event variant (optional)"},"name":{"type":"string","description":"Name of the result (e.g., \"5K\", \"Half Marathon\")"},"result_type":{"type":"string","description":"Determines division behavior:\n- `irl` — Standard divisions (gender + age groups) auto-created\n- `irl_custom_divisions` — Only gender divisions auto-created; timer provides custom divisions per finisher\n","enum":["irl","irl_custom_divisions"]},"time_precision":{"type":"string","description":"How precisely result times are displayed across the platform.\nUnderlying sub-second data is always preserved regardless of this\nsetting; it only controls display rounding.\n- `full_second` — rounded to the nearest second (default)\n- `tenth_of_second` — rounded to the nearest tenth\n- `hundredth_of_second` — rounded to the nearest hundredth\n","enum":["full_second","tenth_of_second","hundredth_of_second"]},"distance":{"type":"number","nullable":true,"description":"Race distance, expressed in `distance_unit`."},"distance_unit":{"type":"string","nullable":true,"description":"Unit `distance` is expressed in.","enum":["miles","kilometers","meters","yards",null]},"pace_type":{"type":"string","nullable":true,"description":"Whether rates read as time-per-distance or distance-per-time.\nSuperseded by `pace_unit` when that is set.\n","enum":["pace","speed",null]},"pace_unit":{"type":"string","nullable":true,"description":"The rate results display in, naming the denominator outright — a\npool swim is min_per_100_meters and rowing is min_per_500_meters,\nneither of which follows from the distance unit. Null derives one\nfrom pace_type + distance_unit; see `effective_pace_unit`.\n","enum":["min_per_mile","min_per_kilometer","min_per_100_meters","min_per_100_yards","min_per_500_meters","miles_per_hour","kilometers_per_hour","meters_per_second",null]},"effective_pace_unit":{"type":"string","description":"The rate unit actually rendered, after the derivation above.","enum":["min_per_mile","min_per_kilometer","min_per_100_meters","min_per_100_yards","min_per_500_meters","miles_per_hour","kilometers_per_hour","meters_per_second"]},"split_time_basis":{"type":"string","description":"How the source reports intermediate splits — both their times and\ntheir distances: `cumulative` (measured from the start) or `per_leg`\n(each value covers that leg alone, common for multisport). `per_leg`\ntimes are converted to elapsed-from-start when the source is parsed,\nnever stored raw; `per_leg` distances are stored as entered.\n","enum":["cumulative","per_leg"]},"show_pace":{"type":"boolean","description":"Whether a pace/speed is displayed for the overall result. Defaults\nto true. Set false where a combined rate is meaningless (a\nmultisport result whose legs don't average into one number); each\nsplit keeps its own `show_pace`.\n"},"last_place_celebration":{"type":"string","nullable":true,"description":"Last-place celebration label, if any.","enum":["lanterne_rouge","dfl",null]},"finisher_count":{"type":"integer","description":"Number of finishers in this result"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}}}}
```

## The EventResultDetail object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"EventResultDetail":{"allOf":[{"$ref":"#/components/schemas/EventResult"},{"type":"object","required":["splits","divisions"],"properties":{"splits":{"type":"array","description":"Split points for this result, ordered by position","items":{"$ref":"#/components/schemas/EventResultSplit"}},"divisions":{"type":"array","description":"Divisions for this result","items":{"$ref":"#/components/schemas/EventResultDivision"}}}}]},"EventResult":{"type":"object","description":"A result container for a race within an event (e.g., \"5K\", \"10K\").\nEach event can have multiple event results.\n","required":["id","event_id","event_variant_id","name","result_type","time_precision","distance","distance_unit","pace_type","pace_unit","effective_pace_unit","split_time_basis","show_pace","last_place_celebration","finisher_count","created_at","updated_at"],"properties":{"id":{"type":"integer","format":"int64","description":"Unique identifier"},"event_id":{"type":"integer","format":"int64","description":"ID of the parent event"},"event_variant_id":{"type":"integer","format":"int64","nullable":true,"description":"ID of the associated event variant (optional)"},"name":{"type":"string","description":"Name of the result (e.g., \"5K\", \"Half Marathon\")"},"result_type":{"type":"string","description":"Determines division behavior:\n- `irl` — Standard divisions (gender + age groups) auto-created\n- `irl_custom_divisions` — Only gender divisions auto-created; timer provides custom divisions per finisher\n","enum":["irl","irl_custom_divisions"]},"time_precision":{"type":"string","description":"How precisely result times are displayed across the platform.\nUnderlying sub-second data is always preserved regardless of this\nsetting; it only controls display rounding.\n- `full_second` — rounded to the nearest second (default)\n- `tenth_of_second` — rounded to the nearest tenth\n- `hundredth_of_second` — rounded to the nearest hundredth\n","enum":["full_second","tenth_of_second","hundredth_of_second"]},"distance":{"type":"number","nullable":true,"description":"Race distance, expressed in `distance_unit`."},"distance_unit":{"type":"string","nullable":true,"description":"Unit `distance` is expressed in.","enum":["miles","kilometers","meters","yards",null]},"pace_type":{"type":"string","nullable":true,"description":"Whether rates read as time-per-distance or distance-per-time.\nSuperseded by `pace_unit` when that is set.\n","enum":["pace","speed",null]},"pace_unit":{"type":"string","nullable":true,"description":"The rate results display in, naming the denominator outright — a\npool swim is min_per_100_meters and rowing is min_per_500_meters,\nneither of which follows from the distance unit. Null derives one\nfrom pace_type + distance_unit; see `effective_pace_unit`.\n","enum":["min_per_mile","min_per_kilometer","min_per_100_meters","min_per_100_yards","min_per_500_meters","miles_per_hour","kilometers_per_hour","meters_per_second",null]},"effective_pace_unit":{"type":"string","description":"The rate unit actually rendered, after the derivation above.","enum":["min_per_mile","min_per_kilometer","min_per_100_meters","min_per_100_yards","min_per_500_meters","miles_per_hour","kilometers_per_hour","meters_per_second"]},"split_time_basis":{"type":"string","description":"How the source reports intermediate splits — both their times and\ntheir distances: `cumulative` (measured from the start) or `per_leg`\n(each value covers that leg alone, common for multisport). `per_leg`\ntimes are converted to elapsed-from-start when the source is parsed,\nnever stored raw; `per_leg` distances are stored as entered.\n","enum":["cumulative","per_leg"]},"show_pace":{"type":"boolean","description":"Whether a pace/speed is displayed for the overall result. Defaults\nto true. Set false where a combined rate is meaningless (a\nmultisport result whose legs don't average into one number); each\nsplit keeps its own `show_pace`.\n"},"last_place_celebration":{"type":"string","nullable":true,"description":"Last-place celebration label, if any.","enum":["lanterne_rouge","dfl",null]},"finisher_count":{"type":"integer","description":"Number of finishers in this result"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"EventResultSplit":{"type":"object","description":"A split point within an event result. Each result must have at\nleast one split marked as the finish.\n","required":["id","event_result_id","name","position","is_finish","distance","pace_unit","distance_unit","effective_pace_unit","effective_distance_unit","show_pace","created_at","updated_at"],"properties":{"id":{"type":"integer","format":"int64","description":"Unique identifier"},"event_result_id":{"type":"integer","format":"int64","description":"ID of the parent event result"},"name":{"type":"string","nullable":true,"description":"Name of the split (e.g., \"Mile 1\", \"Finish\")"},"position":{"type":"integer","description":"Order position (0-indexed)"},"is_finish":{"type":"boolean","description":"Whether this split represents the finish line"},"distance":{"type":"number","nullable":true,"description":"This split's distance, in `effective_distance_unit`. Measured from\nthe start under a `cumulative` split_time_basis, or covering this\nleg alone under `per_leg`.\n"},"pace_unit":{"type":"string","nullable":true,"description":"Rate unit for this split only, overriding the result's. Null\ninherits. Lets a bike leg read in miles_per_hour while the swim leg\nstays min_per_100_meters.\n","enum":["min_per_mile","min_per_kilometer","min_per_100_meters","min_per_100_yards","min_per_500_meters","miles_per_hour","kilometers_per_hour","meters_per_second",null]},"distance_unit":{"type":"string","nullable":true,"description":"Unit this split's `distance` is expressed in, overriding the\nresult's. Null inherits.\n","enum":["miles","kilometers","meters","yards",null]},"effective_pace_unit":{"type":"string","description":"The rate unit this split actually displays in, after inheritance.","enum":["min_per_mile","min_per_kilometer","min_per_100_meters","min_per_100_yards","min_per_500_meters","miles_per_hour","kilometers_per_hour","meters_per_second"]},"effective_distance_unit":{"type":"string","nullable":true,"description":"The unit `distance` is actually in, after inheritance.","enum":["miles","kilometers","meters","yards",null]},"show_pace":{"type":"boolean","description":"Whether a pace/speed is displayed for this split. Defaults to true.\nUnlike the unit overrides above this does not inherit — set it false\nto hide the rate on a transition or an untimed leg.\n"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"EventResultDivision":{"type":"object","description":"A division within an event result (e.g., \"Male\", \"Female 25 - 29\",\nor a custom division like \"Masters\").\n","required":["id","name","division_type","created_at","updated_at"],"properties":{"id":{"type":"integer","format":"int64","description":"Unique identifier"},"name":{"type":"string","description":"Display name of the division"},"division_type":{"type":"string","description":"Machine-readable division type"},"created_at":{"type":"string","format":"date-time","description":"Record creation timestamp"},"updated_at":{"type":"string","format":"date-time","description":"Last update timestamp"}}}}}}
```

## The RaceResultContest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"RaceResultContest":{"type":"object","description":"A contest on the connected Race Result timing event.","required":["contest_id","contest_name"],"properties":{"contest_id":{"type":"integer","description":"Race Result contest id."},"contest_name":{"type":"string"}}}}}}
```

## The RaceResultList object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"RaceResultList":{"type":"object","description":"A Race Result result-list.","required":["name"],"properties":{"name":{"type":"string"}}}}}}
```

## The RaceResultColumn object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"RaceResultColumn":{"type":"object","description":"A column on a Race Result list.","required":["heading","expression"],"properties":{"heading":{"type":"string","description":"Display heading of the column."},"expression":{"type":"string","description":"Race Result expression used to read the value at sync time."}}}}}}
```

## The RaceResultDivisionColumnCandidate object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"RaceResultDivisionColumnCandidate":{"type":"object","description":"A column that can produce divisions, with a distinct-value probe.","required":["expression","label","distinct_values","sample"],"properties":{"expression":{"type":"string"},"label":{"type":"string"},"distinct_values":{"type":"integer","description":"Number of distinct non-empty values found in the list data."},"sample":{"type":"array","items":{"type":"string"}}}}}}}
```

## The RaceResultColumns object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"RaceResultColumns":{"type":"object","required":["columns"],"properties":{"columns":{"type":"array","description":"Every column on the list (options for place + split time columns).","items":{"$ref":"#/components/schemas/RaceResultColumn"}}}},"RaceResultColumn":{"type":"object","description":"A column on a Race Result list.","required":["heading","expression"],"properties":{"heading":{"type":"string","description":"Display heading of the column."},"expression":{"type":"string","description":"Race Result expression used to read the value at sync time."}}}}}}
```

## The RaceResultDivisionOptions object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"RaceResultDivisionOptions":{"type":"object","required":["division_column_candidates"],"properties":{"division_column_candidates":{"type":"array","description":"Columns that would produce divisions, best candidates first. Empty\nwhen the probe could not be evaluated (see\ndivision_column_candidates_error).\n","items":{"$ref":"#/components/schemas/RaceResultDivisionColumnCandidate"}},"division_column_candidates_error":{"type":"string","description":"Present only when the division candidate probe failed or timed out.\nCreate the mapping without a division_column to use Movemint's\ndefault divisions.\n"}}},"RaceResultDivisionColumnCandidate":{"type":"object","description":"A column that can produce divisions, with a distinct-value probe.","required":["expression","label","distinct_values","sample"],"properties":{"expression":{"type":"string"},"label":{"type":"string"},"distinct_values":{"type":"integer","description":"Number of distinct non-empty values found in the list data."},"sample":{"type":"array","items":{"type":"string"}}}}}}}
```

## The RaceResultCategoryMapping object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"RaceResultCategoryMapping":{"type":"object","description":"The saved contest/list/column mapping for a race result.","required":["rr_list_name","rr_column_name","split_by_gender","rr_place_column_name"],"properties":{"rr_list_name":{"type":"string","description":"Race Result list name backing this result."},"rr_column_name":{"type":"string","nullable":true,"description":"Division column expression. Null = Movemint default divisions."},"split_by_gender":{"type":"boolean","description":"Whether each division is also split by gender."},"rr_place_column_name":{"type":"string","nullable":true,"description":"Column expression to rank by. Null = Race Result overall finish."}}}}}}
```

## The RaceResultSplitInput object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"RaceResultSplitInput":{"type":"object","description":"A lap/split time column to bring back as a split.","required":["rr_list_column_heading","rr_list_column_expression","name","position"],"properties":{"rr_list_column_heading":{"type":"string","description":"RR list column heading carrying this split's time."},"rr_list_column_expression":{"type":"string","description":"RR column expression read at sync time."},"name":{"type":"string","description":"Display name for the split (e.g. \"Mile 1\", \"Finish\")."},"distance":{"type":"number","nullable":true,"description":"This split's distance, in its own `distance_unit` (the result's,\nunless overridden below). How it is measured depends on the\nresult's `split_time_basis`: distance from the start under\n`cumulative`, this leg alone under `per_leg`.\n"},"position":{"type":"integer","description":"1-based ordering of the split."},"pace_unit":{"type":"string","nullable":true,"description":"Rate unit for this split only, overriding the result's. Null (or\nomitted) inherits. A multisport result needs this per split — the\nbike leg reads in miles_per_hour while the swim leg reads in\nmin_per_100_meters.\n","enum":["min_per_mile","min_per_kilometer","min_per_100_meters","min_per_100_yards","min_per_500_meters","miles_per_hour","kilometers_per_hour","meters_per_second",null]},"distance_unit":{"type":"string","nullable":true,"description":"Unit this split's `distance` is expressed in, overriding the\nresult's. Null (or omitted) inherits.\n","enum":["miles","kilometers","meters","yards",null]},"show_pace":{"type":"boolean","description":"Whether to display a pace/speed for this split. Defaults to true;\nset false for a transition or an untimed leg. Unlike the unit\noverrides above this does not inherit.\n"}}}}}}
```

## The RaceResultCustomFieldInput object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"RaceResultCustomFieldInput":{"type":"object","description":"A Race Result list column to import as custom data on the result. Each\nbecomes a result-scoped custom question, answered per finisher at sync\ntime.\n","required":["rr_list_column_heading","rr_list_column_expression"],"properties":{"rr_list_column_heading":{"type":"string","description":"RR list column heading to import. This is the stable key — renaming\nthe display name never orphans the answers already recorded.\n"},"rr_list_column_expression":{"type":"string","description":"RR column expression read at sync time."},"column_display_name":{"type":"string","description":"Label shown on the result. Defaults to the column heading."}}}}}}
```

## The RaceResultMappingSplit object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"RaceResultMappingSplit":{"type":"object","description":"A split on a race result mapping, with its unit overrides resolved.","required":["id","name","position","distance","is_finish","pace_unit","distance_unit","effective_pace_unit","effective_distance_unit","show_pace"],"properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string","nullable":true},"position":{"type":"integer"},"distance":{"type":"number","nullable":true,"description":"This split's distance, in `effective_distance_unit`. Measured from\nthe start under a `cumulative` split_time_basis, or covering this\nleg alone under `per_leg`.\n"},"is_finish":{"type":"boolean"},"pace_unit":{"type":"string","nullable":true,"description":"This split's own override. Null = inherits the result's.","enum":["min_per_mile","min_per_kilometer","min_per_100_meters","min_per_100_yards","min_per_500_meters","miles_per_hour","kilometers_per_hour","meters_per_second",null]},"distance_unit":{"type":"string","nullable":true,"description":"This split's own override. Null = inherits the result's.","enum":["miles","kilometers","meters","yards",null]},"effective_pace_unit":{"type":"string","description":"The rate unit this split actually displays in, after inheritance.","enum":["min_per_mile","min_per_kilometer","min_per_100_meters","min_per_100_yards","min_per_500_meters","miles_per_hour","kilometers_per_hour","meters_per_second"]},"effective_distance_unit":{"type":"string","nullable":true,"description":"The unit `distance` is actually in, after inheritance.","enum":["miles","kilometers","meters","yards",null]},"show_pace":{"type":"boolean","description":"Whether a pace/speed is displayed for this split."}}}}}}
```

## The RaceResultMapping object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"RaceResultMapping":{"type":"object","description":"An existing Race Result mapping — one result row on the admin Results\npage (a race_result_result EventResult plus its category mapping).\n","required":["id","name","result_type","race_result_contest_id","finisher_count","distance","distance_unit","pace_type","pace_unit","effective_pace_unit","time_precision","split_time_basis","show_pace","last_place_celebration","divisions_label","mapping","splits","custom_fields","created_at","updated_at"],"properties":{"id":{"type":"integer","format":"int64","description":"The event result id. Use it to update or delete the mapping."},"name":{"type":"string"},"result_type":{"type":"string"},"race_result_contest_id":{"type":"integer","nullable":true},"finisher_count":{"type":"integer"},"distance":{"type":"number","nullable":true},"distance_unit":{"type":"string","nullable":true,"enum":["miles","kilometers","meters","yards",null]},"pace_type":{"type":"string","nullable":true,"enum":["pace","speed",null]},"pace_unit":{"type":"string","nullable":true,"description":"The rate results display in. Null derives one from pace_type +\ndistance_unit — see effective_pace_unit for what that resolves to.\n","enum":["min_per_mile","min_per_kilometer","min_per_100_meters","min_per_100_yards","min_per_500_meters","miles_per_hour","kilometers_per_hour","meters_per_second",null]},"effective_pace_unit":{"type":"string","description":"The rate unit actually rendered, after the derivation above.","enum":["min_per_mile","min_per_kilometer","min_per_100_meters","min_per_100_yards","min_per_500_meters","miles_per_hour","kilometers_per_hour","meters_per_second"]},"time_precision":{"type":"string","nullable":true,"enum":["full_second","tenth_of_second","hundredth_of_second",null]},"split_time_basis":{"type":"string","description":"How the Race Result list reports intermediate splits — both their\ntimes and their distances: `cumulative` (measured from the start) or\n`per_leg` (each value covers that leg alone). `per_leg` times are\nconverted to elapsed-from-start when the contest is read, never\nstored raw; `per_leg` distances are stored as entered.\n","enum":["cumulative","per_leg"]},"show_pace":{"type":"boolean","description":"Whether a pace/speed is displayed for the overall result. Defaults\nto true. Set false where a combined rate is meaningless (a\nmultisport result whose legs don't average into one number); each\nsplit keeps its own `show_pace`.\n"},"last_place_celebration":{"type":"string","nullable":true,"enum":["lanterne_rouge","dfl",null]},"divisions_label":{"type":"string","description":"Human description of the divisions (e.g. \"Online • Lap Detail • Gender\")."},"mapping":{"nullable":true,"allOf":[{"$ref":"#/components/schemas/RaceResultCategoryMapping"}]},"splits":{"type":"array","items":{"$ref":"#/components/schemas/RaceResultMappingSplit"}},"custom_fields":{"type":"array","description":"Race Result list columns imported as custom data on this result.","items":{"$ref":"#/components/schemas/RaceResultCustomFieldInput"}},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"RaceResultCategoryMapping":{"type":"object","description":"The saved contest/list/column mapping for a race result.","required":["rr_list_name","rr_column_name","split_by_gender","rr_place_column_name"],"properties":{"rr_list_name":{"type":"string","description":"Race Result list name backing this result."},"rr_column_name":{"type":"string","nullable":true,"description":"Division column expression. Null = Movemint default divisions."},"split_by_gender":{"type":"boolean","description":"Whether each division is also split by gender."},"rr_place_column_name":{"type":"string","nullable":true,"description":"Column expression to rank by. Null = Race Result overall finish."}}},"RaceResultMappingSplit":{"type":"object","description":"A split on a race result mapping, with its unit overrides resolved.","required":["id","name","position","distance","is_finish","pace_unit","distance_unit","effective_pace_unit","effective_distance_unit","show_pace"],"properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string","nullable":true},"position":{"type":"integer"},"distance":{"type":"number","nullable":true,"description":"This split's distance, in `effective_distance_unit`. Measured from\nthe start under a `cumulative` split_time_basis, or covering this\nleg alone under `per_leg`.\n"},"is_finish":{"type":"boolean"},"pace_unit":{"type":"string","nullable":true,"description":"This split's own override. Null = inherits the result's.","enum":["min_per_mile","min_per_kilometer","min_per_100_meters","min_per_100_yards","min_per_500_meters","miles_per_hour","kilometers_per_hour","meters_per_second",null]},"distance_unit":{"type":"string","nullable":true,"description":"This split's own override. Null = inherits the result's.","enum":["miles","kilometers","meters","yards",null]},"effective_pace_unit":{"type":"string","description":"The rate unit this split actually displays in, after inheritance.","enum":["min_per_mile","min_per_kilometer","min_per_100_meters","min_per_100_yards","min_per_500_meters","miles_per_hour","kilometers_per_hour","meters_per_second"]},"effective_distance_unit":{"type":"string","nullable":true,"description":"The unit `distance` is actually in, after inheritance.","enum":["miles","kilometers","meters","yards",null]},"show_pace":{"type":"boolean","description":"Whether a pace/speed is displayed for this split."}}},"RaceResultCustomFieldInput":{"type":"object","description":"A Race Result list column to import as custom data on the result. Each\nbecomes a result-scoped custom question, answered per finisher at sync\ntime.\n","required":["rr_list_column_heading","rr_list_column_expression"],"properties":{"rr_list_column_heading":{"type":"string","description":"RR list column heading to import. This is the stable key — renaming\nthe display name never orphans the answers already recorded.\n"},"rr_list_column_expression":{"type":"string","description":"RR column expression read at sync time."},"column_display_name":{"type":"string","description":"Label shown on the result. Defaults to the column heading."}}}}}}
```

## The RaceResultMappingWritableFields object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"RaceResultMappingWritableFields":{"type":"object","description":"Fields shared by the create and update mapping requests.","properties":{"list_name":{"type":"string","description":"Race Result list name (from the lists endpoint)."},"division_column":{"type":"string","description":"Column expression for divisions (from division_column_candidates).\nEmpty string = Movemint default age/gender divisions.\n"},"split_by_gender":{"type":"boolean","description":"Also split each division by gender (only applies with a division_column)."},"place_column":{"type":"string","description":"Column expression to rank finishers by. Empty string = Race Result\noverall finish.\n"},"name":{"type":"string"},"distance":{"type":"number"},"distance_unit":{"type":"string","enum":["miles","kilometers","meters","yards"]},"pace_type":{"type":"string","description":"Superseded by pace_unit when that is set.","enum":["pace","speed"]},"pace_unit":{"type":"string","description":"The rate results display in. Pace units read time-per-distance\n(min_per_100_meters for pool swims, min_per_500_meters for rowing);\nspeed units read distance-per-time. Omit to derive one from\npace_type + distance_unit. An unrecognized value is treated as\nomitted rather than rejected.\n","enum":["min_per_mile","min_per_kilometer","min_per_100_meters","min_per_100_yards","min_per_500_meters","miles_per_hour","kilometers_per_hour","meters_per_second"]},"time_precision":{"type":"string","enum":["full_second","tenth_of_second","hundredth_of_second"]},"split_time_basis":{"type":"string","description":"How the Race Result list reports intermediate splits, times and\ndistances alike. Changing it re-reads the contest from Race Result\nso the stored split times are re-normalized — finisher times take a\nmoment to catch up.\n","enum":["cumulative","per_leg"]},"show_pace":{"type":"boolean","description":"Whether a pace/speed is displayed for the overall result. Defaults\nto true. Set false where a combined rate is meaningless (a\nmultisport result whose legs don't average into one number); each\nsplit keeps its own `show_pace`.\n"},"last_place_celebration":{"type":"string","enum":["lanterne_rouge","dfl"]},"splits":{"type":"array","description":"Replaces the result's split columns.","items":{"$ref":"#/components/schemas/RaceResultSplitInput"}},"custom_fields":{"type":"array","description":"Replaces the set of Race Result list columns imported as custom\ndata on the result. Send an empty array to import none.\n","items":{"$ref":"#/components/schemas/RaceResultCustomFieldInput"}}}},"RaceResultSplitInput":{"type":"object","description":"A lap/split time column to bring back as a split.","required":["rr_list_column_heading","rr_list_column_expression","name","position"],"properties":{"rr_list_column_heading":{"type":"string","description":"RR list column heading carrying this split's time."},"rr_list_column_expression":{"type":"string","description":"RR column expression read at sync time."},"name":{"type":"string","description":"Display name for the split (e.g. \"Mile 1\", \"Finish\")."},"distance":{"type":"number","nullable":true,"description":"This split's distance, in its own `distance_unit` (the result's,\nunless overridden below). How it is measured depends on the\nresult's `split_time_basis`: distance from the start under\n`cumulative`, this leg alone under `per_leg`.\n"},"position":{"type":"integer","description":"1-based ordering of the split."},"pace_unit":{"type":"string","nullable":true,"description":"Rate unit for this split only, overriding the result's. Null (or\nomitted) inherits. A multisport result needs this per split — the\nbike leg reads in miles_per_hour while the swim leg reads in\nmin_per_100_meters.\n","enum":["min_per_mile","min_per_kilometer","min_per_100_meters","min_per_100_yards","min_per_500_meters","miles_per_hour","kilometers_per_hour","meters_per_second",null]},"distance_unit":{"type":"string","nullable":true,"description":"Unit this split's `distance` is expressed in, overriding the\nresult's. Null (or omitted) inherits.\n","enum":["miles","kilometers","meters","yards",null]},"show_pace":{"type":"boolean","description":"Whether to display a pace/speed for this split. Defaults to true;\nset false for a transition or an untimed leg. Unlike the unit\noverrides above this does not inherit.\n"}}},"RaceResultCustomFieldInput":{"type":"object","description":"A Race Result list column to import as custom data on the result. Each\nbecomes a result-scoped custom question, answered per finisher at sync\ntime.\n","required":["rr_list_column_heading","rr_list_column_expression"],"properties":{"rr_list_column_heading":{"type":"string","description":"RR list column heading to import. This is the stable key — renaming\nthe display name never orphans the answers already recorded.\n"},"rr_list_column_expression":{"type":"string","description":"RR column expression read at sync time."},"column_display_name":{"type":"string","description":"Label shown on the result. Defaults to the column heading."}}}}}}
```

## The CreateRaceResultMappingRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"CreateRaceResultMappingRequest":{"allOf":[{"type":"object","required":["contest_id","list_name"],"properties":{"contest_id":{"type":"integer","description":"Race Result contest id (from the contests endpoint)."}}},{"$ref":"#/components/schemas/RaceResultMappingWritableFields"}]},"RaceResultMappingWritableFields":{"type":"object","description":"Fields shared by the create and update mapping requests.","properties":{"list_name":{"type":"string","description":"Race Result list name (from the lists endpoint)."},"division_column":{"type":"string","description":"Column expression for divisions (from division_column_candidates).\nEmpty string = Movemint default age/gender divisions.\n"},"split_by_gender":{"type":"boolean","description":"Also split each division by gender (only applies with a division_column)."},"place_column":{"type":"string","description":"Column expression to rank finishers by. Empty string = Race Result\noverall finish.\n"},"name":{"type":"string"},"distance":{"type":"number"},"distance_unit":{"type":"string","enum":["miles","kilometers","meters","yards"]},"pace_type":{"type":"string","description":"Superseded by pace_unit when that is set.","enum":["pace","speed"]},"pace_unit":{"type":"string","description":"The rate results display in. Pace units read time-per-distance\n(min_per_100_meters for pool swims, min_per_500_meters for rowing);\nspeed units read distance-per-time. Omit to derive one from\npace_type + distance_unit. An unrecognized value is treated as\nomitted rather than rejected.\n","enum":["min_per_mile","min_per_kilometer","min_per_100_meters","min_per_100_yards","min_per_500_meters","miles_per_hour","kilometers_per_hour","meters_per_second"]},"time_precision":{"type":"string","enum":["full_second","tenth_of_second","hundredth_of_second"]},"split_time_basis":{"type":"string","description":"How the Race Result list reports intermediate splits, times and\ndistances alike. Changing it re-reads the contest from Race Result\nso the stored split times are re-normalized — finisher times take a\nmoment to catch up.\n","enum":["cumulative","per_leg"]},"show_pace":{"type":"boolean","description":"Whether a pace/speed is displayed for the overall result. Defaults\nto true. Set false where a combined rate is meaningless (a\nmultisport result whose legs don't average into one number); each\nsplit keeps its own `show_pace`.\n"},"last_place_celebration":{"type":"string","enum":["lanterne_rouge","dfl"]},"splits":{"type":"array","description":"Replaces the result's split columns.","items":{"$ref":"#/components/schemas/RaceResultSplitInput"}},"custom_fields":{"type":"array","description":"Replaces the set of Race Result list columns imported as custom\ndata on the result. Send an empty array to import none.\n","items":{"$ref":"#/components/schemas/RaceResultCustomFieldInput"}}}},"RaceResultSplitInput":{"type":"object","description":"A lap/split time column to bring back as a split.","required":["rr_list_column_heading","rr_list_column_expression","name","position"],"properties":{"rr_list_column_heading":{"type":"string","description":"RR list column heading carrying this split's time."},"rr_list_column_expression":{"type":"string","description":"RR column expression read at sync time."},"name":{"type":"string","description":"Display name for the split (e.g. \"Mile 1\", \"Finish\")."},"distance":{"type":"number","nullable":true,"description":"This split's distance, in its own `distance_unit` (the result's,\nunless overridden below). How it is measured depends on the\nresult's `split_time_basis`: distance from the start under\n`cumulative`, this leg alone under `per_leg`.\n"},"position":{"type":"integer","description":"1-based ordering of the split."},"pace_unit":{"type":"string","nullable":true,"description":"Rate unit for this split only, overriding the result's. Null (or\nomitted) inherits. A multisport result needs this per split — the\nbike leg reads in miles_per_hour while the swim leg reads in\nmin_per_100_meters.\n","enum":["min_per_mile","min_per_kilometer","min_per_100_meters","min_per_100_yards","min_per_500_meters","miles_per_hour","kilometers_per_hour","meters_per_second",null]},"distance_unit":{"type":"string","nullable":true,"description":"Unit this split's `distance` is expressed in, overriding the\nresult's. Null (or omitted) inherits.\n","enum":["miles","kilometers","meters","yards",null]},"show_pace":{"type":"boolean","description":"Whether to display a pace/speed for this split. Defaults to true;\nset false for a transition or an untimed leg. Unlike the unit\noverrides above this does not inherit.\n"}}},"RaceResultCustomFieldInput":{"type":"object","description":"A Race Result list column to import as custom data on the result. Each\nbecomes a result-scoped custom question, answered per finisher at sync\ntime.\n","required":["rr_list_column_heading","rr_list_column_expression"],"properties":{"rr_list_column_heading":{"type":"string","description":"RR list column heading to import. This is the stable key — renaming\nthe display name never orphans the answers already recorded.\n"},"rr_list_column_expression":{"type":"string","description":"RR column expression read at sync time."},"column_display_name":{"type":"string","description":"Label shown on the result. Defaults to the column heading."}}}}}}
```

## The UpdateRaceResultMappingRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"UpdateRaceResultMappingRequest":{"allOf":[{"$ref":"#/components/schemas/RaceResultMappingWritableFields"}]},"RaceResultMappingWritableFields":{"type":"object","description":"Fields shared by the create and update mapping requests.","properties":{"list_name":{"type":"string","description":"Race Result list name (from the lists endpoint)."},"division_column":{"type":"string","description":"Column expression for divisions (from division_column_candidates).\nEmpty string = Movemint default age/gender divisions.\n"},"split_by_gender":{"type":"boolean","description":"Also split each division by gender (only applies with a division_column)."},"place_column":{"type":"string","description":"Column expression to rank finishers by. Empty string = Race Result\noverall finish.\n"},"name":{"type":"string"},"distance":{"type":"number"},"distance_unit":{"type":"string","enum":["miles","kilometers","meters","yards"]},"pace_type":{"type":"string","description":"Superseded by pace_unit when that is set.","enum":["pace","speed"]},"pace_unit":{"type":"string","description":"The rate results display in. Pace units read time-per-distance\n(min_per_100_meters for pool swims, min_per_500_meters for rowing);\nspeed units read distance-per-time. Omit to derive one from\npace_type + distance_unit. An unrecognized value is treated as\nomitted rather than rejected.\n","enum":["min_per_mile","min_per_kilometer","min_per_100_meters","min_per_100_yards","min_per_500_meters","miles_per_hour","kilometers_per_hour","meters_per_second"]},"time_precision":{"type":"string","enum":["full_second","tenth_of_second","hundredth_of_second"]},"split_time_basis":{"type":"string","description":"How the Race Result list reports intermediate splits, times and\ndistances alike. Changing it re-reads the contest from Race Result\nso the stored split times are re-normalized — finisher times take a\nmoment to catch up.\n","enum":["cumulative","per_leg"]},"show_pace":{"type":"boolean","description":"Whether a pace/speed is displayed for the overall result. Defaults\nto true. Set false where a combined rate is meaningless (a\nmultisport result whose legs don't average into one number); each\nsplit keeps its own `show_pace`.\n"},"last_place_celebration":{"type":"string","enum":["lanterne_rouge","dfl"]},"splits":{"type":"array","description":"Replaces the result's split columns.","items":{"$ref":"#/components/schemas/RaceResultSplitInput"}},"custom_fields":{"type":"array","description":"Replaces the set of Race Result list columns imported as custom\ndata on the result. Send an empty array to import none.\n","items":{"$ref":"#/components/schemas/RaceResultCustomFieldInput"}}}},"RaceResultSplitInput":{"type":"object","description":"A lap/split time column to bring back as a split.","required":["rr_list_column_heading","rr_list_column_expression","name","position"],"properties":{"rr_list_column_heading":{"type":"string","description":"RR list column heading carrying this split's time."},"rr_list_column_expression":{"type":"string","description":"RR column expression read at sync time."},"name":{"type":"string","description":"Display name for the split (e.g. \"Mile 1\", \"Finish\")."},"distance":{"type":"number","nullable":true,"description":"This split's distance, in its own `distance_unit` (the result's,\nunless overridden below). How it is measured depends on the\nresult's `split_time_basis`: distance from the start under\n`cumulative`, this leg alone under `per_leg`.\n"},"position":{"type":"integer","description":"1-based ordering of the split."},"pace_unit":{"type":"string","nullable":true,"description":"Rate unit for this split only, overriding the result's. Null (or\nomitted) inherits. A multisport result needs this per split — the\nbike leg reads in miles_per_hour while the swim leg reads in\nmin_per_100_meters.\n","enum":["min_per_mile","min_per_kilometer","min_per_100_meters","min_per_100_yards","min_per_500_meters","miles_per_hour","kilometers_per_hour","meters_per_second",null]},"distance_unit":{"type":"string","nullable":true,"description":"Unit this split's `distance` is expressed in, overriding the\nresult's. Null (or omitted) inherits.\n","enum":["miles","kilometers","meters","yards",null]},"show_pace":{"type":"boolean","description":"Whether to display a pace/speed for this split. Defaults to true;\nset false for a transition or an untimed leg. Unlike the unit\noverrides above this does not inherit.\n"}}},"RaceResultCustomFieldInput":{"type":"object","description":"A Race Result list column to import as custom data on the result. Each\nbecomes a result-scoped custom question, answered per finisher at sync\ntime.\n","required":["rr_list_column_heading","rr_list_column_expression"],"properties":{"rr_list_column_heading":{"type":"string","description":"RR list column heading to import. This is the stable key — renaming\nthe display name never orphans the answers already recorded.\n"},"rr_list_column_expression":{"type":"string","description":"RR column expression read at sync time."},"column_display_name":{"type":"string","description":"Label shown on the result. Defaults to the column heading."}}}}}}
```

## The EventResultSplit object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"EventResultSplit":{"type":"object","description":"A split point within an event result. Each result must have at\nleast one split marked as the finish.\n","required":["id","event_result_id","name","position","is_finish","distance","pace_unit","distance_unit","effective_pace_unit","effective_distance_unit","show_pace","created_at","updated_at"],"properties":{"id":{"type":"integer","format":"int64","description":"Unique identifier"},"event_result_id":{"type":"integer","format":"int64","description":"ID of the parent event result"},"name":{"type":"string","nullable":true,"description":"Name of the split (e.g., \"Mile 1\", \"Finish\")"},"position":{"type":"integer","description":"Order position (0-indexed)"},"is_finish":{"type":"boolean","description":"Whether this split represents the finish line"},"distance":{"type":"number","nullable":true,"description":"This split's distance, in `effective_distance_unit`. Measured from\nthe start under a `cumulative` split_time_basis, or covering this\nleg alone under `per_leg`.\n"},"pace_unit":{"type":"string","nullable":true,"description":"Rate unit for this split only, overriding the result's. Null\ninherits. Lets a bike leg read in miles_per_hour while the swim leg\nstays min_per_100_meters.\n","enum":["min_per_mile","min_per_kilometer","min_per_100_meters","min_per_100_yards","min_per_500_meters","miles_per_hour","kilometers_per_hour","meters_per_second",null]},"distance_unit":{"type":"string","nullable":true,"description":"Unit this split's `distance` is expressed in, overriding the\nresult's. Null inherits.\n","enum":["miles","kilometers","meters","yards",null]},"effective_pace_unit":{"type":"string","description":"The rate unit this split actually displays in, after inheritance.","enum":["min_per_mile","min_per_kilometer","min_per_100_meters","min_per_100_yards","min_per_500_meters","miles_per_hour","kilometers_per_hour","meters_per_second"]},"effective_distance_unit":{"type":"string","nullable":true,"description":"The unit `distance` is actually in, after inheritance.","enum":["miles","kilometers","meters","yards",null]},"show_pace":{"type":"boolean","description":"Whether a pace/speed is displayed for this split. Defaults to true.\nUnlike the unit overrides above this does not inherit — set it false\nto hide the rate on a transition or an untimed leg.\n"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}}}}
```

## The EventResultDivision object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"EventResultDivision":{"type":"object","description":"A division within an event result (e.g., \"Male\", \"Female 25 - 29\",\nor a custom division like \"Masters\").\n","required":["id","name","division_type","created_at","updated_at"],"properties":{"id":{"type":"integer","format":"int64","description":"Unique identifier"},"name":{"type":"string","description":"Display name of the division"},"division_type":{"type":"string","description":"Machine-readable division type"},"created_at":{"type":"string","format":"date-time","description":"Record creation timestamp"},"updated_at":{"type":"string","format":"date-time","description":"Last update timestamp"}}}}}}
```

## The Finisher object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"Finisher":{"type":"object","description":"An individual finisher in an event result, along with their split\neffort times.\n","required":["id","event_result_id","event_participant_id","first_name","last_name","gender_identity","gender_name","dob","age","bib","city","state","country","zip_code","created_at","updated_at","split_efforts"],"properties":{"id":{"type":"integer","format":"int64","description":"Unique identifier"},"event_result_id":{"type":"integer","format":"int64","description":"ID of the parent event result"},"event_participant_id":{"type":"integer","format":"int64","nullable":true,"description":"ID of the linked event participant (if any)"},"first_name":{"type":"string","description":"First name"},"last_name":{"type":"string","description":"Last name"},"gender_identity":{"type":"integer","nullable":true,"description":"Gender identity enum value (0=Male, 1=Female, 2=Nonbinary, 3=Prefer Not to Say, 4=Unknown)"},"gender_name":{"type":"string","nullable":true,"description":"Human-readable gender name"},"dob":{"type":"string","format":"date","nullable":true,"description":"Date of birth (YYYY-MM-DD)"},"age":{"type":"integer","nullable":true,"description":"Age at event start (computed from DOB)"},"bib":{"type":"string","nullable":true,"description":"Bib number"},"city":{"type":"string","nullable":true},"state":{"type":"integer","nullable":true,"description":"State enum value"},"country":{"type":"integer","nullable":true,"description":"Country enum value"},"zip_code":{"type":"string","nullable":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"split_efforts":{"type":"array","description":"Split effort times for this finisher","items":{"$ref":"#/components/schemas/SplitEffort"}}}},"SplitEffort":{"type":"object","description":"A finisher's time at a specific split point","required":["id","event_result_split_id","split_name","is_finish","place","chip_time","clock_time","formatted_time","created_at","updated_at"],"properties":{"id":{"type":"integer","format":"int64","description":"Unique identifier"},"event_result_split_id":{"type":"integer","format":"int64","description":"ID of the split this effort is for"},"split_name":{"type":"string","nullable":true,"description":"Name of the split"},"is_finish":{"type":"boolean","nullable":true,"description":"Whether this is the finish split"},"place":{"type":"integer","nullable":true,"description":"Place/position at this split"},"chip_time":{"type":"number","format":"double","nullable":true,"description":"Chip time in seconds (e.g., 1234.567)"},"clock_time":{"type":"number","format":"double","nullable":true,"description":"Clock/gun time in seconds (e.g., 1236.000)"},"formatted_time":{"type":"string","nullable":true,"description":"Human-readable formatted time (e.g., \"20:34.57\")"},"created_at":{"type":"string","format":"date-time","description":"Record creation timestamp"},"updated_at":{"type":"string","format":"date-time","description":"Last update timestamp"}}}}}}
```

## The SplitEffort object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"SplitEffort":{"type":"object","description":"A finisher's time at a specific split point","required":["id","event_result_split_id","split_name","is_finish","place","chip_time","clock_time","formatted_time","created_at","updated_at"],"properties":{"id":{"type":"integer","format":"int64","description":"Unique identifier"},"event_result_split_id":{"type":"integer","format":"int64","description":"ID of the split this effort is for"},"split_name":{"type":"string","nullable":true,"description":"Name of the split"},"is_finish":{"type":"boolean","nullable":true,"description":"Whether this is the finish split"},"place":{"type":"integer","nullable":true,"description":"Place/position at this split"},"chip_time":{"type":"number","format":"double","nullable":true,"description":"Chip time in seconds (e.g., 1234.567)"},"clock_time":{"type":"number","format":"double","nullable":true,"description":"Clock/gun time in seconds (e.g., 1236.000)"},"formatted_time":{"type":"string","nullable":true,"description":"Human-readable formatted time (e.g., \"20:34.57\")"},"created_at":{"type":"string","format":"date-time","description":"Record creation timestamp"},"updated_at":{"type":"string","format":"date-time","description":"Last update timestamp"}}}}}}
```

## The EventWritableFields object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"EventWritableFields":{"type":"object","description":"Subset of `Event` fields that can be set or modified through\n`POST /api/v1/events` and `PATCH /api/v1/events/{handle}`. Other\nfields (status, pricing model, sub-events, etc.) have dedicated\nendpoints. All fields are optional on update; on create, you almost\nalways want to send `name`, `start_date`, `end_date`, and a\nlocation.\n","properties":{"name":{"type":"string"},"handle":{"type":"string","description":"URL slug. Auto-generated on create if omitted."},"start_date":{"type":"string","format":"date"},"end_date":{"type":"string","format":"date"},"registration_open_date":{"type":"string","format":"date-time"},"registration_close_date":{"type":"string","format":"date-time"},"description":{"type":"string"},"email":{"type":"string","format":"email"},"phone_number":{"type":"string"},"website":{"type":"string","format":"uri"},"address":{"type":"string"},"city":{"type":"string"},"state":{"type":"string"},"zip":{"type":"string"},"country":{"type":"string"},"latitude":{"type":"number","format":"double"},"longitude":{"type":"number","format":"double"},"timezone":{"type":"string","description":"IANA timezone identifier (e.g., \"America/New_York\")."},"currency":{"type":"string","description":"ISO 4217 code (e.g., \"USD\")."},"sport_type":{"type":"string"},"max_participants":{"type":"integer"},"single_participant_only":{"type":"boolean"}}}}}}
```

## The EditionGroup object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"EditionGroup":{"type":"object","required":["group_name","current_edition_handle","editions"],"properties":{"group_name":{"type":"string","nullable":true,"description":"Null when the event belongs to no group yet."},"current_edition_handle":{"type":"string","nullable":true,"description":"The edition the admin surfaces as \"Current\"; null with no group."},"editions":{"type":"array","items":{"type":"object","required":["handle","name","status","start_date","end_date"],"properties":{"handle":{"type":"string"},"name":{"type":"string"},"status":{"type":"string","enum":["draft","live","unlisted","landing_page","past_event"]},"start_date":{"type":"string","format":"date","nullable":true},"end_date":{"type":"string","format":"date","nullable":true}}}}}}}}}
```

## The CreateEventRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"CreateEventRequest":{"type":"object","required":["event"],"properties":{"status":{"type":"string","enum":["draft","past_event"],"default":"draft","description":"The status the event is created in. Only these two are accepted —\nthey publish nothing. `past_event` additionally requires `name`\nand `start_date`. Every other status goes through the\nreadiness-gated status endpoint.\n"},"edition_of":{"type":"string","description":"Handle of an existing event this new event is another edition of.\nThe new event is linked into that event's edition group in the same\nrequest, so creating and linking cannot come apart. The caller must\nadminister the named event: an unknown handle returns `404` and one\nthe caller cannot administer returns `403` — in both cases no event\nis created.\n"},"copy_marketing_photos":{"type":"boolean","default":true,"description":"Whether the `edition_of` event's marketing photos are copied onto\nthe new event as independent photos, so deleting one from either\nevent leaves the other's gallery alone. Ignored when `edition_of`\nis absent. The response's `marketing_photos_copied` reports how\nmany were copied; a photo whose stored image cannot be read is\nskipped rather than failing the request, so the count can be lower\nthan the source gallery.\n"},"event":{"$ref":"#/components/schemas/EventWritableFields"}}},"EventWritableFields":{"type":"object","description":"Subset of `Event` fields that can be set or modified through\n`POST /api/v1/events` and `PATCH /api/v1/events/{handle}`. Other\nfields (status, pricing model, sub-events, etc.) have dedicated\nendpoints. All fields are optional on update; on create, you almost\nalways want to send `name`, `start_date`, `end_date`, and a\nlocation.\n","properties":{"name":{"type":"string"},"handle":{"type":"string","description":"URL slug. Auto-generated on create if omitted."},"start_date":{"type":"string","format":"date"},"end_date":{"type":"string","format":"date"},"registration_open_date":{"type":"string","format":"date-time"},"registration_close_date":{"type":"string","format":"date-time"},"description":{"type":"string"},"email":{"type":"string","format":"email"},"phone_number":{"type":"string"},"website":{"type":"string","format":"uri"},"address":{"type":"string"},"city":{"type":"string"},"state":{"type":"string"},"zip":{"type":"string"},"country":{"type":"string"},"latitude":{"type":"number","format":"double"},"longitude":{"type":"number","format":"double"},"timezone":{"type":"string","description":"IANA timezone identifier (e.g., \"America/New_York\")."},"currency":{"type":"string","description":"ISO 4217 code (e.g., \"USD\")."},"sport_type":{"type":"string"},"max_participants":{"type":"integer"},"single_participant_only":{"type":"boolean"}}}}}}
```

## The CreateEventResponse object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"CreateEventResponse":{"allOf":[{"$ref":"#/components/schemas/Event"},{"type":"object","properties":{"edition_group_name":{"type":"string","nullable":true,"description":"Name of the edition group the new event was linked into. Only\npresent when `edition_of` was given.\n"},"marketing_photos_copied":{"type":"integer","description":"How many of the `edition_of` event's marketing photos were\ncopied onto the new event. Only present when `edition_of` was\ngiven and `copy_marketing_photos` was not `false`.\n"}}}]},"Event":{"type":"object","description":"An event on the Movemint platform. All properties are always present in the response; nullable properties may have a null value.","required":["id","name","latitude","longitude","start_date","end_date","sport_type","registration_open_date","registration_close_date","phone_number","email","website","description","max_participants","address","city","state","zip","presented_by","handle","created_at","updated_at","blurb","custom_waiver","status","collect_gender_identity","option_nonbinary","option_prefer_not_to_say","instagram_url","strava_club_url","x_url","facebook_url","donation_goal_cents","registration_included_in_donation_goal","currency","volunteer_message","allow_participant_transfer","participant_transfer_close_date","country","tax_address","collect_phone_number","collect_dob","collect_address","collect_emergency_contact","peer_to_peer_fundraiser","merchandise_tax_rate","service_fee_tax_rate","registration_tax_rate","stripe_account_id","onboarding_step","new_participant_owner_email_setting","show_signup_count","protecht_enabled","send_participant_confirmation_emails","teams_enabled","show_teams_on_start_list","show_teams_on_results","show_relay_teams_on_start_list","timezone","email_owner_on_merchandise_order","email_check_in_confirmation","team_password_setting","sms_enabled","is_free","show_start_list","event_cancellation_insurance_enabled","last_transaction_date","allow_event_variant_transfers","partner_program_eligible","show_event_variant_price_schedule","require_one_sub_event","frictionless_protecht","buy_now_pay_later","show_location","merchandise_store_close_date_time_utc","presale_registration_open_date","presale_registration_code","write_to_strava_activity_on_finish","tax_exempt","name_with_start_date","formatted_start_date","name_with_year"],"properties":{"id":{"type":"integer","format":"int64","description":"Unique identifier"},"name":{"type":"string","description":"Event name"},"latitude":{"type":"string","description":"Venue latitude (decimal as string for precision)"},"longitude":{"type":"string","description":"Venue longitude (decimal as string for precision)"},"start_date":{"type":"string","format":"date-time","description":"Event start date and time (UTC)"},"end_date":{"type":"string","format":"date-time","nullable":true,"description":"Event end date and time (UTC), if applicable"},"sport_type":{"type":"string","description":"Type of sport"},"registration_open_date":{"type":"string","format":"date-time","description":"When registration opens (UTC)"},"registration_close_date":{"type":"string","format":"date-time","nullable":true,"description":"When registration closes (UTC)"},"phone_number":{"type":"string","nullable":true,"description":"Contact phone number"},"email":{"type":"string","format":"email","description":"Contact email for the event"},"website":{"type":"string","format":"uri","description":"Event website URL"},"description":{"type":"string","description":"Full event description (may contain HTML)"},"max_participants":{"type":"integer","nullable":true,"description":"Maximum number of participants allowed; null if unlimited"},"address":{"type":"string","description":"Venue address or venue name"},"city":{"type":"string","description":"City"},"state":{"type":"integer","description":"State enum value (e.g. 21 for Massachusetts)"},"zip":{"type":"string","description":"ZIP or postal code"},"presented_by":{"type":"string","nullable":true,"description":"Presenting sponsor or organization name"},"handle":{"type":"string","description":"Unique URL-safe handle used in paths"},"created_at":{"type":"string","format":"date-time","description":"Record creation timestamp (UTC)"},"updated_at":{"type":"string","format":"date-time","description":"Last update timestamp (UTC)"},"blurb":{"type":"string","description":"Short event summary"},"custom_waiver":{"type":"string","nullable":true,"description":"Custom waiver text shown during registration"},"status":{"type":"string","enum":["draft","live","unlisted","landing_page","past_event"],"description":"Event visibility/status"},"collect_gender_identity":{"type":"boolean","description":"Whether gender identity is collected during registration"},"option_nonbinary":{"type":"boolean","description":"Whether non-binary is offered as a gender identity option"},"option_prefer_not_to_say":{"type":"boolean","description":"Whether \"prefer not to say\" is offered for gender identity"},"instagram_url":{"type":"string","format":"uri","nullable":true,"description":"Instagram profile URL"},"strava_club_url":{"type":"string","format":"uri","nullable":true,"description":"Strava club URL"},"x_url":{"type":"string","format":"uri","nullable":true,"description":"X (Twitter) profile URL"},"facebook_url":{"type":"string","format":"uri","nullable":true,"description":"Facebook page URL"},"donation_goal_cents":{"type":"integer","format":"int64","nullable":true,"description":"Donation goal in cents, if fundraising is enabled"},"registration_included_in_donation_goal":{"type":"boolean","description":"Whether registration revenue counts toward donation goal"},"currency":{"type":"string","description":"ISO 4217 currency code"},"volunteer_message":{"type":"string","nullable":true,"description":"Message or instructions for volunteers"},"allow_participant_transfer":{"type":"boolean","description":"Whether participant transfers are allowed"},"participant_transfer_close_date":{"type":"string","format":"date-time","nullable":true,"description":"Deadline for participant transfers (UTC)"},"country":{"type":"integer","description":"Country enum value (e.g. 187 for United States)"},"tax_address":{"type":"string","nullable":true,"description":"Address used for tax purposes"},"collect_phone_number":{"type":"boolean","description":"Whether phone number is collected during registration"},"collect_dob":{"type":"boolean","description":"Whether date of birth is collected during registration"},"collect_address":{"type":"boolean","description":"Whether address is collected during registration"},"collect_emergency_contact":{"type":"boolean","description":"Whether emergency contact is collected during registration"},"peer_to_peer_fundraiser":{"type":"boolean","description":"Whether peer-to-peer fundraising is enabled"},"merchandise_tax_rate":{"type":"string","nullable":true,"description":"Tax rate for merchandise (decimal as string, e.g. 0.0)"},"service_fee_tax_rate":{"type":"string","nullable":true,"description":"Tax rate for service fees (decimal as string, e.g. 0.0625)"},"registration_tax_rate":{"type":"string","nullable":true,"description":"Tax rate for registration (decimal as string)"},"stripe_account_id":{"type":"integer","format":"int64","nullable":true,"description":"Stripe Connect account ID when connected"},"onboarding_step":{"type":"integer","nullable":true,"description":"Current step in event onboarding flow"},"new_participant_owner_email_setting":{"type":"string","enum":["never_email_owner","email_owner_every_participant"],"description":"When the event owner is emailed about new participants"},"show_signup_count":{"type":"boolean","description":"Whether the signup count is publicly visible"},"protecht_enabled":{"type":"boolean","description":"Whether event cancellation insurance (Protecht) is offered"},"send_participant_confirmation_emails":{"type":"boolean","description":"Whether confirmation emails are sent to participants"},"teams_enabled":{"type":"boolean","description":"Whether team registration is enabled"},"show_teams_on_start_list":{"type":"boolean","description":"Whether teams are shown on the start list"},"show_teams_on_results":{"type":"boolean","description":"Whether teams are shown on results"},"show_relay_teams_on_start_list":{"type":"boolean","description":"Whether relay teams are shown on the start list"},"timezone":{"type":"string","description":"IANA timezone string"},"email_owner_on_merchandise_order":{"type":"boolean","description":"Whether the owner is emailed on merchandise orders"},"email_check_in_confirmation":{"type":"boolean","description":"Whether check-in confirmation emails are sent"},"team_password_setting":{"type":"string","enum":["no_password","optional","required"],"description":"Whether team join requires a password"},"sms_enabled":{"type":"boolean","description":"Whether SMS notifications are enabled"},"is_free":{"type":"boolean","description":"Whether the event is free to register"},"show_start_list":{"type":"boolean","description":"Whether the start list is publicly visible"},"event_cancellation_insurance_enabled":{"type":"boolean","description":"Whether event cancellation insurance is enabled"},"last_transaction_date":{"type":"string","format":"date-time","nullable":true,"description":"Timestamp of last transaction (UTC)"},"allow_event_variant_transfers":{"type":"boolean","description":"Whether transfers between event variants are allowed"},"partner_program_eligible":{"type":"boolean","description":"Whether the event is eligible for partner program"},"show_event_variant_price_schedule":{"type":"boolean","description":"Whether event variant price schedule is shown"},"require_one_sub_event":{"type":"boolean","description":"Whether participant must choose at least one sub-event"},"frictionless_protecht":{"type":"boolean","description":"Whether frictionless Protecht signup is enabled"},"buy_now_pay_later":{"type":"boolean","description":"Whether buy-now-pay-later is offered"},"show_location":{"type":"boolean","description":"Whether the event location is shown publicly"},"merchandise_store_close_date_time_utc":{"type":"string","format":"date-time","nullable":true,"description":"When the merchandise store closes (UTC)"},"presale_registration_open_date":{"type":"string","format":"date-time","nullable":true,"description":"When presale registration opens (UTC)"},"presale_registration_code":{"type":"string","nullable":true,"description":"Code required for presale registration"},"write_to_strava_activity_on_finish":{"type":"boolean","description":"Whether finishing writes to Strava activity"},"tax_exempt":{"type":"boolean","description":"Whether the event is tax exempt"},"name_with_start_date":{"type":"string","description":"Event name combined with formatted start date"},"formatted_start_date":{"type":"string","description":"Human-readable formatted start date"},"name_with_year":{"type":"string","description":"Event name with year"}}}}}}
```

## The CopyMarketingPhotosRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"CopyMarketingPhotosRequest":{"type":"object","required":["source_event_handle"],"properties":{"source_event_handle":{"type":"string","description":"Handle of the event to copy photos from. Must be an event the\ncaller administers with the `marketing` scope, and must not be this\nevent.\n"},"photo_uuids":{"type":"array","items":{"type":"string"},"description":"Uuids of the specific photos to copy. Omit to copy the whole source\ngallery.\n"}}}}}}
```

## The CopyMarketingPhotosResponse object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"CopyMarketingPhotosResponse":{"type":"object","required":["copied","failed","source_event_handle","photos"],"properties":{"copied":{"type":"integer","description":"How many photos were copied."},"failed":{"type":"integer","description":"How many were skipped because their stored image could not be read.\n"},"source_event_handle":{"type":"string","description":"Handle of the event the photos came from."},"photos":{"type":"array","description":"This event's gallery after the copy, in display order.","items":{"$ref":"#/components/schemas/MarketingPhoto"}}}},"MarketingPhoto":{"type":"object","required":["uuid","status","sizes"],"properties":{"uuid":{"type":"string","description":"Stable identifier for the photo across endpoints."},"status":{"type":"string","description":"Lifecycle state. `ready` means processing is complete and the\n`sizes` map is populated; other values indicate the ingest\npipeline is still running.\n"},"sizes":{"type":"object","description":"Map of size name (e.g., `original`, `lg`, `md`, `sm`) to\n`{ url, width, height }`. May be empty/partial while the photo\nis still processing.\n","additionalProperties":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"width":{"type":"integer"},"height":{"type":"integer"}}}}}}}}}
```

## The DuplicateEventRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"DuplicateEventRequest":{"type":"object","required":["name"],"properties":{"name":{"type":"string","description":"Name for the new event."},"start_date":{"type":"string","format":"date","description":"Start date for the copy. Omitted keeps the source event's dates.\n"},"end_date":{"type":"string","format":"date","description":"End date for the copy. Omitted keeps the source event's dates.\n"},"as_edition":{"type":"boolean","default":false,"description":"Link the copy into the source event's edition group, creating the\ngroup on first use — for another year of the same race.\n"},"copy_sub_events":{"type":"boolean","default":true,"description":"Copy the source's sub-events and their price tiers."},"copy_sponsors":{"type":"boolean","default":true,"description":"Copy the source's sponsors."},"copy_questions":{"type":"boolean","default":true,"description":"Copy the source's registration questions."},"copy_waivers":{"type":"boolean","default":true,"description":"Copy the source's active waivers."},"copy_marketing_photos":{"type":"boolean","default":true,"description":"Copy the source's marketing photos as independent photos."}}}}}}
```

## The DuplicateEventResponse object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"DuplicateEventResponse":{"allOf":[{"$ref":"#/components/schemas/Event"},{"type":"object","properties":{"duplicated_from":{"type":"string","description":"Handle of the event this copy was made from."},"edition_group_name":{"type":"string","nullable":true,"description":"Name of the edition group the copy was linked into. Only\npresent when `as_edition` was true.\n"}}}]},"Event":{"type":"object","description":"An event on the Movemint platform. All properties are always present in the response; nullable properties may have a null value.","required":["id","name","latitude","longitude","start_date","end_date","sport_type","registration_open_date","registration_close_date","phone_number","email","website","description","max_participants","address","city","state","zip","presented_by","handle","created_at","updated_at","blurb","custom_waiver","status","collect_gender_identity","option_nonbinary","option_prefer_not_to_say","instagram_url","strava_club_url","x_url","facebook_url","donation_goal_cents","registration_included_in_donation_goal","currency","volunteer_message","allow_participant_transfer","participant_transfer_close_date","country","tax_address","collect_phone_number","collect_dob","collect_address","collect_emergency_contact","peer_to_peer_fundraiser","merchandise_tax_rate","service_fee_tax_rate","registration_tax_rate","stripe_account_id","onboarding_step","new_participant_owner_email_setting","show_signup_count","protecht_enabled","send_participant_confirmation_emails","teams_enabled","show_teams_on_start_list","show_teams_on_results","show_relay_teams_on_start_list","timezone","email_owner_on_merchandise_order","email_check_in_confirmation","team_password_setting","sms_enabled","is_free","show_start_list","event_cancellation_insurance_enabled","last_transaction_date","allow_event_variant_transfers","partner_program_eligible","show_event_variant_price_schedule","require_one_sub_event","frictionless_protecht","buy_now_pay_later","show_location","merchandise_store_close_date_time_utc","presale_registration_open_date","presale_registration_code","write_to_strava_activity_on_finish","tax_exempt","name_with_start_date","formatted_start_date","name_with_year"],"properties":{"id":{"type":"integer","format":"int64","description":"Unique identifier"},"name":{"type":"string","description":"Event name"},"latitude":{"type":"string","description":"Venue latitude (decimal as string for precision)"},"longitude":{"type":"string","description":"Venue longitude (decimal as string for precision)"},"start_date":{"type":"string","format":"date-time","description":"Event start date and time (UTC)"},"end_date":{"type":"string","format":"date-time","nullable":true,"description":"Event end date and time (UTC), if applicable"},"sport_type":{"type":"string","description":"Type of sport"},"registration_open_date":{"type":"string","format":"date-time","description":"When registration opens (UTC)"},"registration_close_date":{"type":"string","format":"date-time","nullable":true,"description":"When registration closes (UTC)"},"phone_number":{"type":"string","nullable":true,"description":"Contact phone number"},"email":{"type":"string","format":"email","description":"Contact email for the event"},"website":{"type":"string","format":"uri","description":"Event website URL"},"description":{"type":"string","description":"Full event description (may contain HTML)"},"max_participants":{"type":"integer","nullable":true,"description":"Maximum number of participants allowed; null if unlimited"},"address":{"type":"string","description":"Venue address or venue name"},"city":{"type":"string","description":"City"},"state":{"type":"integer","description":"State enum value (e.g. 21 for Massachusetts)"},"zip":{"type":"string","description":"ZIP or postal code"},"presented_by":{"type":"string","nullable":true,"description":"Presenting sponsor or organization name"},"handle":{"type":"string","description":"Unique URL-safe handle used in paths"},"created_at":{"type":"string","format":"date-time","description":"Record creation timestamp (UTC)"},"updated_at":{"type":"string","format":"date-time","description":"Last update timestamp (UTC)"},"blurb":{"type":"string","description":"Short event summary"},"custom_waiver":{"type":"string","nullable":true,"description":"Custom waiver text shown during registration"},"status":{"type":"string","enum":["draft","live","unlisted","landing_page","past_event"],"description":"Event visibility/status"},"collect_gender_identity":{"type":"boolean","description":"Whether gender identity is collected during registration"},"option_nonbinary":{"type":"boolean","description":"Whether non-binary is offered as a gender identity option"},"option_prefer_not_to_say":{"type":"boolean","description":"Whether \"prefer not to say\" is offered for gender identity"},"instagram_url":{"type":"string","format":"uri","nullable":true,"description":"Instagram profile URL"},"strava_club_url":{"type":"string","format":"uri","nullable":true,"description":"Strava club URL"},"x_url":{"type":"string","format":"uri","nullable":true,"description":"X (Twitter) profile URL"},"facebook_url":{"type":"string","format":"uri","nullable":true,"description":"Facebook page URL"},"donation_goal_cents":{"type":"integer","format":"int64","nullable":true,"description":"Donation goal in cents, if fundraising is enabled"},"registration_included_in_donation_goal":{"type":"boolean","description":"Whether registration revenue counts toward donation goal"},"currency":{"type":"string","description":"ISO 4217 currency code"},"volunteer_message":{"type":"string","nullable":true,"description":"Message or instructions for volunteers"},"allow_participant_transfer":{"type":"boolean","description":"Whether participant transfers are allowed"},"participant_transfer_close_date":{"type":"string","format":"date-time","nullable":true,"description":"Deadline for participant transfers (UTC)"},"country":{"type":"integer","description":"Country enum value (e.g. 187 for United States)"},"tax_address":{"type":"string","nullable":true,"description":"Address used for tax purposes"},"collect_phone_number":{"type":"boolean","description":"Whether phone number is collected during registration"},"collect_dob":{"type":"boolean","description":"Whether date of birth is collected during registration"},"collect_address":{"type":"boolean","description":"Whether address is collected during registration"},"collect_emergency_contact":{"type":"boolean","description":"Whether emergency contact is collected during registration"},"peer_to_peer_fundraiser":{"type":"boolean","description":"Whether peer-to-peer fundraising is enabled"},"merchandise_tax_rate":{"type":"string","nullable":true,"description":"Tax rate for merchandise (decimal as string, e.g. 0.0)"},"service_fee_tax_rate":{"type":"string","nullable":true,"description":"Tax rate for service fees (decimal as string, e.g. 0.0625)"},"registration_tax_rate":{"type":"string","nullable":true,"description":"Tax rate for registration (decimal as string)"},"stripe_account_id":{"type":"integer","format":"int64","nullable":true,"description":"Stripe Connect account ID when connected"},"onboarding_step":{"type":"integer","nullable":true,"description":"Current step in event onboarding flow"},"new_participant_owner_email_setting":{"type":"string","enum":["never_email_owner","email_owner_every_participant"],"description":"When the event owner is emailed about new participants"},"show_signup_count":{"type":"boolean","description":"Whether the signup count is publicly visible"},"protecht_enabled":{"type":"boolean","description":"Whether event cancellation insurance (Protecht) is offered"},"send_participant_confirmation_emails":{"type":"boolean","description":"Whether confirmation emails are sent to participants"},"teams_enabled":{"type":"boolean","description":"Whether team registration is enabled"},"show_teams_on_start_list":{"type":"boolean","description":"Whether teams are shown on the start list"},"show_teams_on_results":{"type":"boolean","description":"Whether teams are shown on results"},"show_relay_teams_on_start_list":{"type":"boolean","description":"Whether relay teams are shown on the start list"},"timezone":{"type":"string","description":"IANA timezone string"},"email_owner_on_merchandise_order":{"type":"boolean","description":"Whether the owner is emailed on merchandise orders"},"email_check_in_confirmation":{"type":"boolean","description":"Whether check-in confirmation emails are sent"},"team_password_setting":{"type":"string","enum":["no_password","optional","required"],"description":"Whether team join requires a password"},"sms_enabled":{"type":"boolean","description":"Whether SMS notifications are enabled"},"is_free":{"type":"boolean","description":"Whether the event is free to register"},"show_start_list":{"type":"boolean","description":"Whether the start list is publicly visible"},"event_cancellation_insurance_enabled":{"type":"boolean","description":"Whether event cancellation insurance is enabled"},"last_transaction_date":{"type":"string","format":"date-time","nullable":true,"description":"Timestamp of last transaction (UTC)"},"allow_event_variant_transfers":{"type":"boolean","description":"Whether transfers between event variants are allowed"},"partner_program_eligible":{"type":"boolean","description":"Whether the event is eligible for partner program"},"show_event_variant_price_schedule":{"type":"boolean","description":"Whether event variant price schedule is shown"},"require_one_sub_event":{"type":"boolean","description":"Whether participant must choose at least one sub-event"},"frictionless_protecht":{"type":"boolean","description":"Whether frictionless Protecht signup is enabled"},"buy_now_pay_later":{"type":"boolean","description":"Whether buy-now-pay-later is offered"},"show_location":{"type":"boolean","description":"Whether the event location is shown publicly"},"merchandise_store_close_date_time_utc":{"type":"string","format":"date-time","nullable":true,"description":"When the merchandise store closes (UTC)"},"presale_registration_open_date":{"type":"string","format":"date-time","nullable":true,"description":"When presale registration opens (UTC)"},"presale_registration_code":{"type":"string","nullable":true,"description":"Code required for presale registration"},"write_to_strava_activity_on_finish":{"type":"boolean","description":"Whether finishing writes to Strava activity"},"tax_exempt":{"type":"boolean","description":"Whether the event is tax exempt"},"name_with_start_date":{"type":"string","description":"Event name combined with formatted start date"},"formatted_start_date":{"type":"string","description":"Human-readable formatted start date"},"name_with_year":{"type":"string","description":"Event name with year"}}}}}}
```

## The UpdateEventRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"UpdateEventRequest":{"type":"object","required":["event"],"properties":{"event":{"$ref":"#/components/schemas/EventWritableFields"}}},"EventWritableFields":{"type":"object","description":"Subset of `Event` fields that can be set or modified through\n`POST /api/v1/events` and `PATCH /api/v1/events/{handle}`. Other\nfields (status, pricing model, sub-events, etc.) have dedicated\nendpoints. All fields are optional on update; on create, you almost\nalways want to send `name`, `start_date`, `end_date`, and a\nlocation.\n","properties":{"name":{"type":"string"},"handle":{"type":"string","description":"URL slug. Auto-generated on create if omitted."},"start_date":{"type":"string","format":"date"},"end_date":{"type":"string","format":"date"},"registration_open_date":{"type":"string","format":"date-time"},"registration_close_date":{"type":"string","format":"date-time"},"description":{"type":"string"},"email":{"type":"string","format":"email"},"phone_number":{"type":"string"},"website":{"type":"string","format":"uri"},"address":{"type":"string"},"city":{"type":"string"},"state":{"type":"string"},"zip":{"type":"string"},"country":{"type":"string"},"latitude":{"type":"number","format":"double"},"longitude":{"type":"number","format":"double"},"timezone":{"type":"string","description":"IANA timezone identifier (e.g., \"America/New_York\")."},"currency":{"type":"string","description":"ISO 4217 code (e.g., \"USD\")."},"sport_type":{"type":"string"},"max_participants":{"type":"integer"},"single_participant_only":{"type":"boolean"}}}}}}
```

## The ReadinessIssue object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"ReadinessIssue":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable machine-readable code for the issue."},"message":{"type":"string","description":"Human-readable explanation of what to fix."},"sub_event_id":{"type":"integer","format":"int64","description":"Present when the issue is scoped to a specific sub-event."}}}}}}
```

## The ReadinessReport object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"ReadinessReport":{"type":"object","required":["ready","blocking","warnings"],"properties":{"ready":{"type":"boolean","description":"True when there are no blocking issues."},"blocking":{"type":"array","items":{"$ref":"#/components/schemas/ReadinessIssue"}},"warnings":{"type":"array","items":{"$ref":"#/components/schemas/ReadinessIssue"}}}},"ReadinessIssue":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable machine-readable code for the issue."},"message":{"type":"string","description":"Human-readable explanation of what to fix."},"sub_event_id":{"type":"integer","format":"int64","description":"Present when the issue is scoped to a specific sub-event."}}}}}}
```

## The EventStatusUpdate object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"EventStatusUpdate":{"type":"object","required":["status"],"properties":{"status":{"type":"string","enum":["draft","live","unlisted","landing_page","past_event"]}}}}}}
```

## The ReadinessGatedError object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"ReadinessGatedError":{"type":"object","required":["error"],"properties":{"error":{"type":"string"},"blocking":{"type":"array","items":{"$ref":"#/components/schemas/ReadinessIssue"}},"warnings":{"type":"array","items":{"$ref":"#/components/schemas/ReadinessIssue"}}}},"ReadinessIssue":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable machine-readable code for the issue."},"message":{"type":"string","description":"Human-readable explanation of what to fix."},"sub_event_id":{"type":"integer","format":"int64","description":"Present when the issue is scoped to a specific sub-event."}}}}}}
```

## The PricingModelUpdate object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"PricingModelUpdate":{"type":"object","required":["is_free"],"properties":{"is_free":{"type":"boolean","description":"True for a free event, false for a paid event."}}}}}}
```

## The CoverPhotoUpdate object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"CoverPhotoUpdate":{"type":"object","required":["marketing_photo_uuid"],"properties":{"marketing_photo_uuid":{"type":"string","description":"UUID of a `ready` photo in the event's marketing album."}}}}}}
```

## The MarketingPhoto object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"MarketingPhoto":{"type":"object","required":["uuid","status","sizes"],"properties":{"uuid":{"type":"string","description":"Stable identifier for the photo across endpoints."},"status":{"type":"string","description":"Lifecycle state. `ready` means processing is complete and the\n`sizes` map is populated; other values indicate the ingest\npipeline is still running.\n"},"sizes":{"type":"object","description":"Map of size name (e.g., `original`, `lg`, `md`, `sm`) to\n`{ url, width, height }`. May be empty/partial while the photo\nis still processing.\n","additionalProperties":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"width":{"type":"integer"},"height":{"type":"integer"}}}}}}}}}
```

## The CreateMarketingPhotoRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"CreateMarketingPhotoRequest":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri","description":"Publicly accessible image URL."}}}}}}
```

## The ReorderMarketingPhotosRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"ReorderMarketingPhotosRequest":{"type":"object","required":["uuids"],"properties":{"uuids":{"type":"array","description":"Photo UUIDs in the desired display order.","items":{"type":"string"}}}}}}}
```

## The SubEventPrice object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"SubEventPrice":{"type":"object","required":["id","price_cents","price_dollars","is_sliding_scale","close_date","description"],"properties":{"id":{"type":"integer","format":"int64"},"price_cents":{"type":"integer","description":"Tier price in the event's currency, in minor units (cents)."},"price_dollars":{"type":"number","format":"double","description":"Convenience copy of `price_cents` divided by 100."},"is_sliding_scale":{"type":"boolean"},"close_date":{"type":"string","format":"date-time","nullable":true,"description":"When this tier ends. Null on the final/highest tier."},"description":{"type":"string","nullable":true}}}}}}
```

## The SubEvent object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"SubEvent":{"type":"object","required":["id","name","description","start_date","end_date","start_time","end_time","registration_open_date","registration_close_date","order","max_participants","min_age","max_age","allow_race_day_registration","race_day_price_cents","hidden","invite_only","requires_login","show_spots_remaining","multiple_registration","has_waitlist","require_applications","waitlist_auto_invite_enabled","waitlist_invite_response_window_hours","waitlist_under_capacity_grace_period_minutes","waitlist_invite_cutoff_at","has_multiple_participants","multi_participant_count","multi_participant_max_count","allowed_gender_ids","registration_code_set","distance","distance_meters","distance_display_unit","formatted_distance","prices"],"properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"start_date":{"type":"string","format":"date","nullable":true},"end_date":{"type":"string","format":"date","nullable":true},"start_time":{"type":"string","nullable":true,"description":"24-hour `HH:MM`."},"end_time":{"type":"string","nullable":true,"description":"24-hour `HH:MM`."},"registration_open_date":{"type":"string","format":"date-time","nullable":true},"registration_close_date":{"type":"string","format":"date-time","nullable":true},"order":{"type":"integer","nullable":true},"max_participants":{"type":"integer","nullable":true},"min_age":{"type":"integer","nullable":true},"max_age":{"type":"integer","nullable":true},"allow_race_day_registration":{"type":"boolean","nullable":true},"race_day_price_cents":{"type":"integer","nullable":true},"hidden":{"type":"boolean","nullable":true},"invite_only":{"type":"boolean","nullable":true},"requires_login":{"type":"boolean","description":"Whether athletes must be signed in to register for this sub-event."},"show_spots_remaining":{"type":"boolean","nullable":true},"multiple_registration":{"type":"boolean","nullable":true},"has_waitlist":{"type":"boolean","nullable":true},"require_applications":{"type":"boolean","description":"When true, every registrant enters the waitlist/application flow for\nthis sub-event regardless of remaining capacity. Surfaced to athletes\nas an application rather than a waitlist.\n"},"waitlist_auto_invite_enabled":{"type":"boolean","nullable":true},"waitlist_invite_response_window_hours":{"type":"integer","nullable":true},"waitlist_under_capacity_grace_period_minutes":{"type":"integer","nullable":true},"waitlist_invite_cutoff_at":{"type":"string","format":"date-time","nullable":true},"has_multiple_participants":{"type":"boolean","nullable":true},"multi_participant_count":{"type":"integer","nullable":true},"multi_participant_max_count":{"type":"integer","nullable":true},"allowed_gender_ids":{"type":"array","nullable":true,"description":"Array of `GenderIdentity` integer IDs that may register for this\nsub-event. `null` means all genders are allowed.\n","items":{"type":"integer"}},"registration_code_set":{"type":"boolean","description":"Whether a private registration code is configured."},"distance":{"type":"number","nullable":true,"description":"Sub-event distance expressed in `distance_display_unit` (e.g. 13.1\nwhen the unit is `miles`). This is the value to send back on a write.\n"},"distance_meters":{"type":"integer","nullable":true,"description":"Sub-event distance normalized to meters. This is the canonical,\nqueryable value; `distance_display_unit` records the unit it was\nentered in.\n"},"distance_display_unit":{"type":"string","nullable":true,"enum":["meters","kilometers","miles"],"description":"Display unit the organizer entered the distance in."},"formatted_distance":{"type":"string","nullable":true,"description":"Preformatted distance in the display unit, e.g. `\"13.1 mi\"`."},"prices":{"type":"array","items":{"$ref":"#/components/schemas/SubEventPrice"}}}},"SubEventPrice":{"type":"object","required":["id","price_cents","price_dollars","is_sliding_scale","close_date","description"],"properties":{"id":{"type":"integer","format":"int64"},"price_cents":{"type":"integer","description":"Tier price in the event's currency, in minor units (cents)."},"price_dollars":{"type":"number","format":"double","description":"Convenience copy of `price_cents` divided by 100."},"is_sliding_scale":{"type":"boolean"},"close_date":{"type":"string","format":"date-time","nullable":true,"description":"When this tier ends. Null on the final/highest tier."},"description":{"type":"string","nullable":true}}}}}}
```

## The SubEventPriceTierInput object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"SubEventPriceTierInput":{"type":"object","description":"One pricing tier. Provide either `price_cents` or `price_dollars`\n(not both). Tiers without a `close_date` represent the final /\nhighest tier.\n","properties":{"price_cents":{"type":"integer"},"price_dollars":{"type":"number","format":"double"},"is_sliding_scale":{"type":"boolean"},"close_date":{"type":"string","format":"date-time","nullable":true},"description":{"type":"string","nullable":true}}}}}}
```

## The SubEventWritableFields object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"SubEventWritableFields":{"type":"object","description":"Fields accepted by sub-event create/update. Direct date/time fields\naccept ISO-8601 strings (`YYYY-MM-DD` for dates, `HH:MM` for\ntimes-of-day, full ISO-8601 for datetimes).\n\n**Pricing.** Send `prices` for tiered pricing, OR `price_cents` /\n`price_dollars` as a single-tier shorthand. Supplying any of these\nreplaces the existing tier set entirely.\n\n**Gender restrictions.** `allowed_gender_ids` is an array of\n`GenderIdentity` integer IDs. Empty / omitted means \"all allowed\".\n","properties":{"name":{"type":"string"},"description":{"type":"string"},"start_date":{"type":"string","format":"date"},"end_date":{"type":"string","format":"date"},"start_time":{"type":"string","description":"24-hour `HH:MM`."},"end_time":{"type":"string","description":"24-hour `HH:MM`."},"registration_open_date":{"type":"string","format":"date-time"},"registration_close_date":{"type":"string","format":"date-time"},"max_participants":{"type":"integer","nullable":true},"min_age":{"type":"integer","nullable":true},"max_age":{"type":"integer","nullable":true},"allow_race_day_registration":{"type":"boolean"},"race_day_price":{"type":"integer","description":"Race-day price in minor units (cents)."},"race_day_price_cents":{"type":"integer"},"race_day_price_dollars":{"type":"number","format":"double"},"hidden":{"type":"boolean"},"invite_only":{"type":"boolean"},"requires_login":{"type":"boolean","description":"Require athletes to be signed in to register for this sub-event."},"show_spots_remaining":{"type":"boolean"},"multiple_registration":{"type":"boolean"},"has_waitlist":{"type":"boolean"},"require_applications":{"type":"boolean","description":"Force every registrant into the waitlist/application flow regardless\nof capacity. Surfaced to athletes as an application, not a waitlist.\n"},"waitlist_auto_invite_enabled":{"type":"boolean"},"waitlist_invite_response_window_hours":{"type":"integer","nullable":true},"waitlist_under_capacity_grace_period_minutes":{"type":"integer","nullable":true},"waitlist_invite_cutoff_at":{"type":"string","format":"date-time","nullable":true},"has_multiple_participants":{"type":"boolean"},"multi_participant_count":{"type":"integer","nullable":true},"multi_participant_max_count":{"type":"integer","nullable":true},"registration_code":{"type":"string","description":"Empty string clears."},"distance":{"type":"number","nullable":true,"description":"Sub-event distance as a value in `distance_display_unit` (e.g. 13.1\nwith unit `miles`, or 5 with `kilometers`). Normalized to meters\nserver-side so the entered value round-trips. Send together with\n`distance_display_unit`; a blank value clears the distance.\n"},"distance_display_unit":{"type":"string","nullable":true,"enum":["meters","kilometers","miles"],"description":"Unit the `distance` value is in and displays in. Required when\n`distance` is set.\n"},"allowed_gender_ids":{"type":"array","items":{"type":"integer"}},"prices":{"type":"array","items":{"$ref":"#/components/schemas/SubEventPriceTierInput"}},"price_cents":{"type":"integer","description":"Single-tier shorthand. Mutually exclusive with `prices`."},"price_dollars":{"type":"number","format":"double","description":"Single-tier shorthand. Mutually exclusive with `prices`."}}},"SubEventPriceTierInput":{"type":"object","description":"One pricing tier. Provide either `price_cents` or `price_dollars`\n(not both). Tiers without a `close_date` represent the final /\nhighest tier.\n","properties":{"price_cents":{"type":"integer"},"price_dollars":{"type":"number","format":"double"},"is_sliding_scale":{"type":"boolean"},"close_date":{"type":"string","format":"date-time","nullable":true},"description":{"type":"string","nullable":true}}}}}}
```

## The CreateSubEventRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"CreateSubEventRequest":{"allOf":[{"$ref":"#/components/schemas/SubEventWritableFields"},{"type":"object","required":["name"]}]},"SubEventWritableFields":{"type":"object","description":"Fields accepted by sub-event create/update. Direct date/time fields\naccept ISO-8601 strings (`YYYY-MM-DD` for dates, `HH:MM` for\ntimes-of-day, full ISO-8601 for datetimes).\n\n**Pricing.** Send `prices` for tiered pricing, OR `price_cents` /\n`price_dollars` as a single-tier shorthand. Supplying any of these\nreplaces the existing tier set entirely.\n\n**Gender restrictions.** `allowed_gender_ids` is an array of\n`GenderIdentity` integer IDs. Empty / omitted means \"all allowed\".\n","properties":{"name":{"type":"string"},"description":{"type":"string"},"start_date":{"type":"string","format":"date"},"end_date":{"type":"string","format":"date"},"start_time":{"type":"string","description":"24-hour `HH:MM`."},"end_time":{"type":"string","description":"24-hour `HH:MM`."},"registration_open_date":{"type":"string","format":"date-time"},"registration_close_date":{"type":"string","format":"date-time"},"max_participants":{"type":"integer","nullable":true},"min_age":{"type":"integer","nullable":true},"max_age":{"type":"integer","nullable":true},"allow_race_day_registration":{"type":"boolean"},"race_day_price":{"type":"integer","description":"Race-day price in minor units (cents)."},"race_day_price_cents":{"type":"integer"},"race_day_price_dollars":{"type":"number","format":"double"},"hidden":{"type":"boolean"},"invite_only":{"type":"boolean"},"requires_login":{"type":"boolean","description":"Require athletes to be signed in to register for this sub-event."},"show_spots_remaining":{"type":"boolean"},"multiple_registration":{"type":"boolean"},"has_waitlist":{"type":"boolean"},"require_applications":{"type":"boolean","description":"Force every registrant into the waitlist/application flow regardless\nof capacity. Surfaced to athletes as an application, not a waitlist.\n"},"waitlist_auto_invite_enabled":{"type":"boolean"},"waitlist_invite_response_window_hours":{"type":"integer","nullable":true},"waitlist_under_capacity_grace_period_minutes":{"type":"integer","nullable":true},"waitlist_invite_cutoff_at":{"type":"string","format":"date-time","nullable":true},"has_multiple_participants":{"type":"boolean"},"multi_participant_count":{"type":"integer","nullable":true},"multi_participant_max_count":{"type":"integer","nullable":true},"registration_code":{"type":"string","description":"Empty string clears."},"distance":{"type":"number","nullable":true,"description":"Sub-event distance as a value in `distance_display_unit` (e.g. 13.1\nwith unit `miles`, or 5 with `kilometers`). Normalized to meters\nserver-side so the entered value round-trips. Send together with\n`distance_display_unit`; a blank value clears the distance.\n"},"distance_display_unit":{"type":"string","nullable":true,"enum":["meters","kilometers","miles"],"description":"Unit the `distance` value is in and displays in. Required when\n`distance` is set.\n"},"allowed_gender_ids":{"type":"array","items":{"type":"integer"}},"prices":{"type":"array","items":{"$ref":"#/components/schemas/SubEventPriceTierInput"}},"price_cents":{"type":"integer","description":"Single-tier shorthand. Mutually exclusive with `prices`."},"price_dollars":{"type":"number","format":"double","description":"Single-tier shorthand. Mutually exclusive with `prices`."}}},"SubEventPriceTierInput":{"type":"object","description":"One pricing tier. Provide either `price_cents` or `price_dollars`\n(not both). Tiers without a `close_date` represent the final /\nhighest tier.\n","properties":{"price_cents":{"type":"integer"},"price_dollars":{"type":"number","format":"double"},"is_sliding_scale":{"type":"boolean"},"close_date":{"type":"string","format":"date-time","nullable":true},"description":{"type":"string","nullable":true}}}}}}
```

## The UpdateSubEventRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"UpdateSubEventRequest":{"$ref":"#/components/schemas/SubEventWritableFields"},"SubEventWritableFields":{"type":"object","description":"Fields accepted by sub-event create/update. Direct date/time fields\naccept ISO-8601 strings (`YYYY-MM-DD` for dates, `HH:MM` for\ntimes-of-day, full ISO-8601 for datetimes).\n\n**Pricing.** Send `prices` for tiered pricing, OR `price_cents` /\n`price_dollars` as a single-tier shorthand. Supplying any of these\nreplaces the existing tier set entirely.\n\n**Gender restrictions.** `allowed_gender_ids` is an array of\n`GenderIdentity` integer IDs. Empty / omitted means \"all allowed\".\n","properties":{"name":{"type":"string"},"description":{"type":"string"},"start_date":{"type":"string","format":"date"},"end_date":{"type":"string","format":"date"},"start_time":{"type":"string","description":"24-hour `HH:MM`."},"end_time":{"type":"string","description":"24-hour `HH:MM`."},"registration_open_date":{"type":"string","format":"date-time"},"registration_close_date":{"type":"string","format":"date-time"},"max_participants":{"type":"integer","nullable":true},"min_age":{"type":"integer","nullable":true},"max_age":{"type":"integer","nullable":true},"allow_race_day_registration":{"type":"boolean"},"race_day_price":{"type":"integer","description":"Race-day price in minor units (cents)."},"race_day_price_cents":{"type":"integer"},"race_day_price_dollars":{"type":"number","format":"double"},"hidden":{"type":"boolean"},"invite_only":{"type":"boolean"},"requires_login":{"type":"boolean","description":"Require athletes to be signed in to register for this sub-event."},"show_spots_remaining":{"type":"boolean"},"multiple_registration":{"type":"boolean"},"has_waitlist":{"type":"boolean"},"require_applications":{"type":"boolean","description":"Force every registrant into the waitlist/application flow regardless\nof capacity. Surfaced to athletes as an application, not a waitlist.\n"},"waitlist_auto_invite_enabled":{"type":"boolean"},"waitlist_invite_response_window_hours":{"type":"integer","nullable":true},"waitlist_under_capacity_grace_period_minutes":{"type":"integer","nullable":true},"waitlist_invite_cutoff_at":{"type":"string","format":"date-time","nullable":true},"has_multiple_participants":{"type":"boolean"},"multi_participant_count":{"type":"integer","nullable":true},"multi_participant_max_count":{"type":"integer","nullable":true},"registration_code":{"type":"string","description":"Empty string clears."},"distance":{"type":"number","nullable":true,"description":"Sub-event distance as a value in `distance_display_unit` (e.g. 13.1\nwith unit `miles`, or 5 with `kilometers`). Normalized to meters\nserver-side so the entered value round-trips. Send together with\n`distance_display_unit`; a blank value clears the distance.\n"},"distance_display_unit":{"type":"string","nullable":true,"enum":["meters","kilometers","miles"],"description":"Unit the `distance` value is in and displays in. Required when\n`distance` is set.\n"},"allowed_gender_ids":{"type":"array","items":{"type":"integer"}},"prices":{"type":"array","items":{"$ref":"#/components/schemas/SubEventPriceTierInput"}},"price_cents":{"type":"integer","description":"Single-tier shorthand. Mutually exclusive with `prices`."},"price_dollars":{"type":"number","format":"double","description":"Single-tier shorthand. Mutually exclusive with `prices`."}}},"SubEventPriceTierInput":{"type":"object","description":"One pricing tier. Provide either `price_cents` or `price_dollars`\n(not both). Tiers without a `close_date` represent the final /\nhighest tier.\n","properties":{"price_cents":{"type":"integer"},"price_dollars":{"type":"number","format":"double"},"is_sliding_scale":{"type":"boolean"},"close_date":{"type":"string","format":"date-time","nullable":true},"description":{"type":"string","nullable":true}}}}}}
```

## The EmailAudienceInput object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"EmailAudienceInput":{"type":"object","required":["type","id"],"description":"A recipient-audience reference to attach to (or exclude from) the email.\nValid `type`s depend on the sender scope: **event** emails accept\n`config` (a pre-built audience — see `available_audiences`); **group**\nemails accept `crm_audience` (a saved CRM audience id). Both scopes\naccept `filter_context` (the id of a custom audience previously created\nvia the custom_audience endpoint and already attached to this email).\nA ref that is unknown, of a type this sender scope doesn't accept, or\nowned by another sender is rejected with `422` and the whole request is\napplied atomically — nothing changes unless every ref is usable.\nUnknown and out-of-scope refs report identically, so a caller can't use\nthe error to probe which ids exist under a sender they can't see.\n","properties":{"type":{"type":"string","enum":["config","crm_audience","filter_context"]},"id":{"description":"The audience id. A string configuration key for `config`, an integer\nid for `crm_audience` / `filter_context`.\n","oneOf":[{"type":"string"},{"type":"integer"}]},"include":{"type":"boolean","description":"True to include the audience, false to exclude it. Defaults to true."}}}}}}
```

## The EmailAudienceRef object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"EmailAudienceRef":{"type":"object","required":["type","id","include"],"description":"A recipient audience currently attached to the email.","properties":{"type":{"type":"string","enum":["config","crm_audience","filter_context","platform_segment"]},"id":{"oneOf":[{"type":"string"},{"type":"integer"}]},"include":{"type":"boolean"}}}}}}
```

## The EmailWritableFields object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"EmailWritableFields":{"type":"object","description":"Fields accepted by email create/update. On update, only keys present in\nthe request are applied — omitted fields are left untouched. `email_type`\nis honored on create only. The sender (`send_from`) is always forced to\nthe event/group in the URL and is never client-settable.\n","properties":{"name":{"type":"string","description":"Internal campaign name (max 255 chars). Defaults to a dated name on create."},"subject":{"type":"string","description":"Email subject line (max 255 chars)."},"preview_text":{"type":"string","description":"Preheader / preview text (max 255 chars)."},"email_type":{"type":"string","enum":["marketing","transactional"],"description":"Create-only. Defaults to `marketing`."},"send_from_athlete":{"type":"boolean","description":"Whether to include the sending admin's name in the from-name."},"send_to_future_audience_members":{"type":"boolean","description":"Auto-send to people who later match the audience (applies at send time only)."},"audiences":{"type":"array","items":{"$ref":"#/components/schemas/EmailAudienceInput"}}}},"EmailAudienceInput":{"type":"object","required":["type","id"],"description":"A recipient-audience reference to attach to (or exclude from) the email.\nValid `type`s depend on the sender scope: **event** emails accept\n`config` (a pre-built audience — see `available_audiences`); **group**\nemails accept `crm_audience` (a saved CRM audience id). Both scopes\naccept `filter_context` (the id of a custom audience previously created\nvia the custom_audience endpoint and already attached to this email).\nA ref that is unknown, of a type this sender scope doesn't accept, or\nowned by another sender is rejected with `422` and the whole request is\napplied atomically — nothing changes unless every ref is usable.\nUnknown and out-of-scope refs report identically, so a caller can't use\nthe error to probe which ids exist under a sender they can't see.\n","properties":{"type":{"type":"string","enum":["config","crm_audience","filter_context"]},"id":{"description":"The audience id. A string configuration key for `config`, an integer\nid for `crm_audience` / `filter_context`.\n","oneOf":[{"type":"string"},{"type":"integer"}]},"include":{"type":"boolean","description":"True to include the audience, false to exclude it. Defaults to true."}}}}}}
```

## The CreateEmailRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"CreateEmailRequest":{"allOf":[{"$ref":"#/components/schemas/EmailWritableFields"}]},"EmailWritableFields":{"type":"object","description":"Fields accepted by email create/update. On update, only keys present in\nthe request are applied — omitted fields are left untouched. `email_type`\nis honored on create only. The sender (`send_from`) is always forced to\nthe event/group in the URL and is never client-settable.\n","properties":{"name":{"type":"string","description":"Internal campaign name (max 255 chars). Defaults to a dated name on create."},"subject":{"type":"string","description":"Email subject line (max 255 chars)."},"preview_text":{"type":"string","description":"Preheader / preview text (max 255 chars)."},"email_type":{"type":"string","enum":["marketing","transactional"],"description":"Create-only. Defaults to `marketing`."},"send_from_athlete":{"type":"boolean","description":"Whether to include the sending admin's name in the from-name."},"send_to_future_audience_members":{"type":"boolean","description":"Auto-send to people who later match the audience (applies at send time only)."},"audiences":{"type":"array","items":{"$ref":"#/components/schemas/EmailAudienceInput"}}}},"EmailAudienceInput":{"type":"object","required":["type","id"],"description":"A recipient-audience reference to attach to (or exclude from) the email.\nValid `type`s depend on the sender scope: **event** emails accept\n`config` (a pre-built audience — see `available_audiences`); **group**\nemails accept `crm_audience` (a saved CRM audience id). Both scopes\naccept `filter_context` (the id of a custom audience previously created\nvia the custom_audience endpoint and already attached to this email).\nA ref that is unknown, of a type this sender scope doesn't accept, or\nowned by another sender is rejected with `422` and the whole request is\napplied atomically — nothing changes unless every ref is usable.\nUnknown and out-of-scope refs report identically, so a caller can't use\nthe error to probe which ids exist under a sender they can't see.\n","properties":{"type":{"type":"string","enum":["config","crm_audience","filter_context"]},"id":{"description":"The audience id. A string configuration key for `config`, an integer\nid for `crm_audience` / `filter_context`.\n","oneOf":[{"type":"string"},{"type":"integer"}]},"include":{"type":"boolean","description":"True to include the audience, false to exclude it. Defaults to true."}}}}}}
```

## The UpdateEmailRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"UpdateEmailRequest":{"$ref":"#/components/schemas/EmailWritableFields"},"EmailWritableFields":{"type":"object","description":"Fields accepted by email create/update. On update, only keys present in\nthe request are applied — omitted fields are left untouched. `email_type`\nis honored on create only. The sender (`send_from`) is always forced to\nthe event/group in the URL and is never client-settable.\n","properties":{"name":{"type":"string","description":"Internal campaign name (max 255 chars). Defaults to a dated name on create."},"subject":{"type":"string","description":"Email subject line (max 255 chars)."},"preview_text":{"type":"string","description":"Preheader / preview text (max 255 chars)."},"email_type":{"type":"string","enum":["marketing","transactional"],"description":"Create-only. Defaults to `marketing`."},"send_from_athlete":{"type":"boolean","description":"Whether to include the sending admin's name in the from-name."},"send_to_future_audience_members":{"type":"boolean","description":"Auto-send to people who later match the audience (applies at send time only)."},"audiences":{"type":"array","items":{"$ref":"#/components/schemas/EmailAudienceInput"}}}},"EmailAudienceInput":{"type":"object","required":["type","id"],"description":"A recipient-audience reference to attach to (or exclude from) the email.\nValid `type`s depend on the sender scope: **event** emails accept\n`config` (a pre-built audience — see `available_audiences`); **group**\nemails accept `crm_audience` (a saved CRM audience id). Both scopes\naccept `filter_context` (the id of a custom audience previously created\nvia the custom_audience endpoint and already attached to this email).\nA ref that is unknown, of a type this sender scope doesn't accept, or\nowned by another sender is rejected with `422` and the whole request is\napplied atomically — nothing changes unless every ref is usable.\nUnknown and out-of-scope refs report identically, so a caller can't use\nthe error to probe which ids exist under a sender they can't see.\n","properties":{"type":{"type":"string","enum":["config","crm_audience","filter_context"]},"id":{"description":"The audience id. A string configuration key for `config`, an integer\nid for `crm_audience` / `filter_context`.\n","oneOf":[{"type":"string"},{"type":"integer"}]},"include":{"type":"boolean","description":"True to include the audience, false to exclude it. Defaults to true."}}}}}}
```

## The EmailDesignRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"EmailDesignRequest":{"type":"object","description":"The email body as a block-builder document. Provide the document as a\nnative JSON object under `design`, or as a JSON string under\n`blocks_json`. The document shape is validated server-side (rows /\ncolumns / typed blocks, hex colors, safe URLs) and compiled to the\nrendered HTML that would ship.\n","properties":{"design":{"type":"object","description":"The block document (version, document settings, rows).","additionalProperties":true},"blocks_json":{"type":"string","description":"The block document serialized as a JSON string. Alternative to `design`."}}}}}}
```

## The EmailCustomAudienceRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"EmailCustomAudienceRequest":{"type":"object","description":"Creates a custom recipient audience from CRM-style filters and attaches\nit to the email. The audience materializes asynchronously — poll the\nreturned `audience_calculation.calculating` flag.\n","properties":{"include":{"type":"boolean","description":"Include (true, default) or exclude (false) the matched recipients."},"filters":{"type":"object","description":"CRM-style filter selection (e.g. `{ \"entity_types\": [\"EventParticipants\"],\n\"genders\": [\"Male\"] }`). Must resolve to at least one real filter.\n","additionalProperties":true}}}}}}
```

## The AudienceCalculation object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"AudienceCalculation":{"type":"object","required":["calculating","pending_audience_ids"],"description":"Async materialization status for the email's audiences.","properties":{"calculating":{"type":"boolean"},"pending_audience_ids":{"type":"array","items":{"type":"integer"}}}}}}}
```

## The EmailListResult object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"EmailListResult":{"type":"object","required":["emails"],"properties":{"emails":{"type":"array","items":{"$ref":"#/components/schemas/Email"}}}},"Email":{"type":"object","required":["id","name","email_type","subject","preview_text","send_status","send_from","send_from_athlete","send_to_future_audience_members","editable","has_content","created_at","updated_at"],"description":"An email campaign. Summary fields are always present; the detailed\nfields (`audiences`, `design`, `rendered_html`, `sendable_blockers`,\n`available_audiences`) are returned by show/create/update/design but\nomitted from the list endpoint.\n","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string","nullable":true},"email_type":{"type":"string","enum":["marketing","transactional"]},"subject":{"type":"string","nullable":true},"preview_text":{"type":"string","nullable":true},"send_status":{"type":"string","enum":["draft","scheduled","sent","sending"]},"send_from":{"type":"object","required":["scope","id"],"properties":{"scope":{"type":"string","enum":["event","group"]},"id":{"type":"integer","format":"int64"}}},"send_from_athlete":{"type":"boolean","nullable":true},"send_to_future_audience_members":{"type":"boolean"},"audiences":{"type":"array","items":{"$ref":"#/components/schemas/EmailAudienceRef"}},"editable":{"type":"boolean","description":"True while the email can still be edited (draft or scheduled)."},"has_content":{"type":"boolean","description":"Whether the email has rendered body content."},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"design":{"type":"object","nullable":true,"description":"The block document (detailed responses only).","additionalProperties":true},"rendered_html":{"type":"string","nullable":true,"description":"Compiled HTML (detailed responses only)."},"sendable_blockers":{"type":"object","description":"Read-only map of field name → reason code describing what is still\nmissing before the email could ever be scheduled. Keys are the\nrequest field they refer to (`subject`, `send_from`,\n`send_from_athlete`, `audiences`, `rendered_html`); an empty object\nmeans nothing is outstanding. Codes are stable — `missing` for an\nunset field, `calculating` while an attached audience is still\nmaterializing (retry shortly). Present on detailed responses; does\nnot enable sending.\n","additionalProperties":{"type":"string","enum":["missing","calculating"]}},"available_audiences":{"type":"array","description":"Selectable audience sections for this sender scope (detailed responses only).","items":{"type":"object","additionalProperties":true}}}},"EmailAudienceRef":{"type":"object","required":["type","id","include"],"description":"A recipient audience currently attached to the email.","properties":{"type":{"type":"string","enum":["config","crm_audience","filter_context","platform_segment"]},"id":{"oneOf":[{"type":"string"},{"type":"integer"}]},"include":{"type":"boolean"}}}}}}
```

## The EmailResult object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"EmailResult":{"type":"object","required":["email"],"properties":{"email":{"$ref":"#/components/schemas/Email"}}},"Email":{"type":"object","required":["id","name","email_type","subject","preview_text","send_status","send_from","send_from_athlete","send_to_future_audience_members","editable","has_content","created_at","updated_at"],"description":"An email campaign. Summary fields are always present; the detailed\nfields (`audiences`, `design`, `rendered_html`, `sendable_blockers`,\n`available_audiences`) are returned by show/create/update/design but\nomitted from the list endpoint.\n","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string","nullable":true},"email_type":{"type":"string","enum":["marketing","transactional"]},"subject":{"type":"string","nullable":true},"preview_text":{"type":"string","nullable":true},"send_status":{"type":"string","enum":["draft","scheduled","sent","sending"]},"send_from":{"type":"object","required":["scope","id"],"properties":{"scope":{"type":"string","enum":["event","group"]},"id":{"type":"integer","format":"int64"}}},"send_from_athlete":{"type":"boolean","nullable":true},"send_to_future_audience_members":{"type":"boolean"},"audiences":{"type":"array","items":{"$ref":"#/components/schemas/EmailAudienceRef"}},"editable":{"type":"boolean","description":"True while the email can still be edited (draft or scheduled)."},"has_content":{"type":"boolean","description":"Whether the email has rendered body content."},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"design":{"type":"object","nullable":true,"description":"The block document (detailed responses only).","additionalProperties":true},"rendered_html":{"type":"string","nullable":true,"description":"Compiled HTML (detailed responses only)."},"sendable_blockers":{"type":"object","description":"Read-only map of field name → reason code describing what is still\nmissing before the email could ever be scheduled. Keys are the\nrequest field they refer to (`subject`, `send_from`,\n`send_from_athlete`, `audiences`, `rendered_html`); an empty object\nmeans nothing is outstanding. Codes are stable — `missing` for an\nunset field, `calculating` while an attached audience is still\nmaterializing (retry shortly). Present on detailed responses; does\nnot enable sending.\n","additionalProperties":{"type":"string","enum":["missing","calculating"]}},"available_audiences":{"type":"array","description":"Selectable audience sections for this sender scope (detailed responses only).","items":{"type":"object","additionalProperties":true}}}},"EmailAudienceRef":{"type":"object","required":["type","id","include"],"description":"A recipient audience currently attached to the email.","properties":{"type":{"type":"string","enum":["config","crm_audience","filter_context","platform_segment"]},"id":{"oneOf":[{"type":"string"},{"type":"integer"}]},"include":{"type":"boolean"}}}}}}
```

## The EmailWriteResult object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"EmailWriteResult":{"type":"object","required":["email","audience_calculation"],"properties":{"email":{"$ref":"#/components/schemas/Email"},"audience_calculation":{"$ref":"#/components/schemas/AudienceCalculation"}}},"Email":{"type":"object","required":["id","name","email_type","subject","preview_text","send_status","send_from","send_from_athlete","send_to_future_audience_members","editable","has_content","created_at","updated_at"],"description":"An email campaign. Summary fields are always present; the detailed\nfields (`audiences`, `design`, `rendered_html`, `sendable_blockers`,\n`available_audiences`) are returned by show/create/update/design but\nomitted from the list endpoint.\n","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string","nullable":true},"email_type":{"type":"string","enum":["marketing","transactional"]},"subject":{"type":"string","nullable":true},"preview_text":{"type":"string","nullable":true},"send_status":{"type":"string","enum":["draft","scheduled","sent","sending"]},"send_from":{"type":"object","required":["scope","id"],"properties":{"scope":{"type":"string","enum":["event","group"]},"id":{"type":"integer","format":"int64"}}},"send_from_athlete":{"type":"boolean","nullable":true},"send_to_future_audience_members":{"type":"boolean"},"audiences":{"type":"array","items":{"$ref":"#/components/schemas/EmailAudienceRef"}},"editable":{"type":"boolean","description":"True while the email can still be edited (draft or scheduled)."},"has_content":{"type":"boolean","description":"Whether the email has rendered body content."},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"design":{"type":"object","nullable":true,"description":"The block document (detailed responses only).","additionalProperties":true},"rendered_html":{"type":"string","nullable":true,"description":"Compiled HTML (detailed responses only)."},"sendable_blockers":{"type":"object","description":"Read-only map of field name → reason code describing what is still\nmissing before the email could ever be scheduled. Keys are the\nrequest field they refer to (`subject`, `send_from`,\n`send_from_athlete`, `audiences`, `rendered_html`); an empty object\nmeans nothing is outstanding. Codes are stable — `missing` for an\nunset field, `calculating` while an attached audience is still\nmaterializing (retry shortly). Present on detailed responses; does\nnot enable sending.\n","additionalProperties":{"type":"string","enum":["missing","calculating"]}},"available_audiences":{"type":"array","description":"Selectable audience sections for this sender scope (detailed responses only).","items":{"type":"object","additionalProperties":true}}}},"EmailAudienceRef":{"type":"object","required":["type","id","include"],"description":"A recipient audience currently attached to the email.","properties":{"type":{"type":"string","enum":["config","crm_audience","filter_context","platform_segment"]},"id":{"oneOf":[{"type":"string"},{"type":"integer"}]},"include":{"type":"boolean"}}},"AudienceCalculation":{"type":"object","required":["calculating","pending_audience_ids"],"description":"Async materialization status for the email's audiences.","properties":{"calculating":{"type":"boolean"},"pending_audience_ids":{"type":"array","items":{"type":"integer"}}}}}}}
```

## The EmailPreviewResult object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"EmailPreviewResult":{"type":"object","required":["rendered_html","preview_text"],"properties":{"rendered_html":{"type":"string","nullable":true},"preview_text":{"type":"string","nullable":true}}}}}}
```

## The EmailCustomAudienceResult object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"EmailCustomAudienceResult":{"type":"object","required":["audience","audience_calculation"],"properties":{"audience":{"$ref":"#/components/schemas/EmailAudienceRef"},"audience_calculation":{"$ref":"#/components/schemas/AudienceCalculation"}}},"EmailAudienceRef":{"type":"object","required":["type","id","include"],"description":"A recipient audience currently attached to the email.","properties":{"type":{"type":"string","enum":["config","crm_audience","filter_context","platform_segment"]},"id":{"oneOf":[{"type":"string"},{"type":"integer"}]},"include":{"type":"boolean"}}},"AudienceCalculation":{"type":"object","required":["calculating","pending_audience_ids"],"description":"Async materialization status for the email's audiences.","properties":{"calculating":{"type":"boolean"},"pending_audience_ids":{"type":"array","items":{"type":"integer"}}}}}}}
```

## The Email object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"Email":{"type":"object","required":["id","name","email_type","subject","preview_text","send_status","send_from","send_from_athlete","send_to_future_audience_members","editable","has_content","created_at","updated_at"],"description":"An email campaign. Summary fields are always present; the detailed\nfields (`audiences`, `design`, `rendered_html`, `sendable_blockers`,\n`available_audiences`) are returned by show/create/update/design but\nomitted from the list endpoint.\n","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string","nullable":true},"email_type":{"type":"string","enum":["marketing","transactional"]},"subject":{"type":"string","nullable":true},"preview_text":{"type":"string","nullable":true},"send_status":{"type":"string","enum":["draft","scheduled","sent","sending"]},"send_from":{"type":"object","required":["scope","id"],"properties":{"scope":{"type":"string","enum":["event","group"]},"id":{"type":"integer","format":"int64"}}},"send_from_athlete":{"type":"boolean","nullable":true},"send_to_future_audience_members":{"type":"boolean"},"audiences":{"type":"array","items":{"$ref":"#/components/schemas/EmailAudienceRef"}},"editable":{"type":"boolean","description":"True while the email can still be edited (draft or scheduled)."},"has_content":{"type":"boolean","description":"Whether the email has rendered body content."},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"design":{"type":"object","nullable":true,"description":"The block document (detailed responses only).","additionalProperties":true},"rendered_html":{"type":"string","nullable":true,"description":"Compiled HTML (detailed responses only)."},"sendable_blockers":{"type":"object","description":"Read-only map of field name → reason code describing what is still\nmissing before the email could ever be scheduled. Keys are the\nrequest field they refer to (`subject`, `send_from`,\n`send_from_athlete`, `audiences`, `rendered_html`); an empty object\nmeans nothing is outstanding. Codes are stable — `missing` for an\nunset field, `calculating` while an attached audience is still\nmaterializing (retry shortly). Present on detailed responses; does\nnot enable sending.\n","additionalProperties":{"type":"string","enum":["missing","calculating"]}},"available_audiences":{"type":"array","description":"Selectable audience sections for this sender scope (detailed responses only).","items":{"type":"object","additionalProperties":true}}}},"EmailAudienceRef":{"type":"object","required":["type","id","include"],"description":"A recipient audience currently attached to the email.","properties":{"type":{"type":"string","enum":["config","crm_audience","filter_context","platform_segment"]},"id":{"oneOf":[{"type":"string"},{"type":"integer"}]},"include":{"type":"boolean"}}}}}}
```

## The CreateEventResultRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"CreateEventResultRequest":{"type":"object","required":["event_result"],"properties":{"event_result":{"type":"object","required":["name","result_type"],"properties":{"name":{"type":"string","description":"Name of the result (e.g., \"5K\")"},"result_type":{"type":"string","enum":["irl","irl_custom_divisions"],"description":"Division mode"},"event_variant_id":{"type":"integer","format":"int64","description":"Optional event variant to associate"},"time_precision":{"type":"string","enum":["full_second","tenth_of_second","hundredth_of_second"],"description":"Display precision for result times (defaults to full_second)"},"distance":{"type":"number","description":"Race distance, in distance_unit."},"distance_unit":{"type":"string","enum":["miles","kilometers","meters","yards"]},"pace_type":{"type":"string","description":"Superseded by pace_unit when that is set.","enum":["pace","speed"]},"pace_unit":{"type":"string","description":"The rate results display in. Omit to derive one from pace_type\n+ distance_unit.\n","enum":["min_per_mile","min_per_kilometer","min_per_100_meters","min_per_100_yards","min_per_500_meters","miles_per_hour","kilometers_per_hour","meters_per_second"]},"split_time_basis":{"type":"string","description":"How the source reports intermediate splits, times and distances\nalike (defaults to cumulative).\n","enum":["cumulative","per_leg"]},"show_pace":{"type":"boolean","description":"Whether to display a pace/speed for the overall result\n(defaults to true).\n"},"last_place_celebration":{"type":"string","enum":["lanterne_rouge","dfl"]},"splits":{"type":"array","description":"Inline splits to create with the result","items":{"type":"object","required":["position","is_finish"],"properties":{"name":{"type":"string"},"position":{"type":"integer"},"is_finish":{"type":"boolean"},"distance":{"type":"number","description":"This split's distance, measured per the result's\n`split_time_basis`.\n"},"pace_unit":{"type":"string","description":"Per-split override. Omit to inherit the result's. An\nunrecognized value is treated as omitted.\n","enum":["min_per_mile","min_per_kilometer","min_per_100_meters","min_per_100_yards","min_per_500_meters","miles_per_hour","kilometers_per_hour","meters_per_second"]},"distance_unit":{"type":"string","description":"Per-split override. Omit to inherit the result's.","enum":["miles","kilometers","meters","yards"]},"show_pace":{"type":"boolean","description":"Whether to display a pace/speed for this split (defaults\nto true).\n"}}}}}}}}}}}
```

## The UpdateEventResultRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"UpdateEventResultRequest":{"type":"object","required":["event_result"],"properties":{"event_result":{"type":"object","properties":{"name":{"type":"string"},"event_variant_id":{"type":"integer","format":"int64"},"time_precision":{"type":"string","enum":["full_second","tenth_of_second","hundredth_of_second"],"description":"Display precision for result times"},"distance":{"type":"number","description":"Race distance, in distance_unit."},"distance_unit":{"type":"string","enum":["miles","kilometers","meters","yards"]},"pace_type":{"type":"string","description":"Superseded by pace_unit when that is set.","enum":["pace","speed"]},"pace_unit":{"type":"string","description":"The rate results display in. Omit to derive one from pace_type\n+ distance_unit.\n","enum":["min_per_mile","min_per_kilometer","min_per_100_meters","min_per_100_yards","min_per_500_meters","miles_per_hour","kilometers_per_hour","meters_per_second"]},"split_time_basis":{"type":"string","description":"How the source reports intermediate splits, times and distances\nalike. Changing it re-derives the result from its source (the\nuploaded file, or Race Result) in the background, so finisher\nand split times take a moment to catch up.\n","enum":["cumulative","per_leg"]},"show_pace":{"type":"boolean","description":"Whether to display a pace/speed for the overall result\n(defaults to true).\n"},"last_place_celebration":{"type":"string","enum":["lanterne_rouge","dfl"]}}}}}}}}
```

## The CreateSplitRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"CreateSplitRequest":{"type":"object","required":["split"],"properties":{"split":{"type":"object","required":["position","is_finish"],"properties":{"name":{"type":"string"},"position":{"type":"integer"},"is_finish":{"type":"boolean"},"distance":{"type":"number","description":"This split's distance, in `distance_unit` (the result's, unless\noverridden below). Measured from the start under a `cumulative`\nsplit_time_basis, or covering this leg alone under `per_leg`.\n"},"pace_unit":{"type":"string","description":"Rate unit for this split only, overriding the result's. Omit to\ninherit. An unrecognized value is treated as omitted.\n","enum":["min_per_mile","min_per_kilometer","min_per_100_meters","min_per_100_yards","min_per_500_meters","miles_per_hour","kilometers_per_hour","meters_per_second"]},"distance_unit":{"type":"string","description":"Unit this split's `distance` is expressed in, overriding the\nresult's. Omit to inherit.\n","enum":["miles","kilometers","meters","yards"]},"show_pace":{"type":"boolean","description":"Whether to display a pace/speed for this split (defaults to\ntrue). Unlike the unit overrides above this does not inherit.\n"}}}}}}}}
```

## The CreateFinisherRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"CreateFinisherRequest":{"type":"object","required":["finisher"],"properties":{"finisher":{"type":"object","required":["first_name","last_name"],"properties":{"first_name":{"type":"string","description":"First name"},"last_name":{"type":"string","description":"Last name"},"movemint_confirmation_number":{"type":"string","description":"Movemint registration confirmation number. If provided, the\nfinisher is automatically linked to the matching event\nparticipant and their metadata (name, gender, DOB, address,\netc.) is copied to fill in any fields not explicitly provided\nby the timer.\n"},"gender":{"oneOf":[{"type":"string","description":"Gender string (male, female, nonbinary, m, f, x)"},{"type":"integer","description":"Gender identity integer (0=Male, 1=Female, 2=Nonbinary)"}]},"dob":{"type":"string","format":"date","description":"Date of birth (YYYY-MM-DD)"},"bib":{"type":"string","description":"Bib number. If `movemint_confirmation_number` is not provided,\nthe system will attempt to link the finisher to an event\nparticipant by bib number (only if exactly one participant\nmatches).\n"},"city":{"type":"string"},"address":{"type":"string"},"state":{"type":"integer","description":"State enum value"},"country":{"type":"integer","description":"Country enum value"},"zip_code":{"type":"string"},"chip_number":{"type":"string"},"split_efforts":{"type":"array","description":"Split effort times","items":{"type":"object","required":["event_result_split_id"],"properties":{"event_result_split_id":{"type":"integer","format":"int64","description":"ID of the split to record time for"},"place":{"type":"integer","description":"Place/position at this split"},"chip_time":{"type":"number","format":"double","description":"Chip time in seconds"},"clock_time":{"type":"number","format":"double","description":"Clock/gun time in seconds"}}}},"divisions":{"type":"array","description":"Custom division names (only used when result_type is\n`irl_custom_divisions`). Ignored for `irl` results.\n","items":{"type":"string"}}}}}}}}}
```

## The TransferSettings object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"TransferSettings":{"type":"object","required":["allow_transfers","allow_event_variant_transfers","close_date","price_cents","price_dollars"],"properties":{"allow_transfers":{"type":"boolean","description":"Whether participant-to-participant transfers are enabled."},"allow_event_variant_transfers":{"type":"boolean","description":"Whether participants may also transfer between sub-events (distances)."},"close_date":{"type":"string","format":"date-time","nullable":true,"description":"ISO datetime after which transfers stop. Defaults to registration close when null."},"price_cents":{"type":"integer","nullable":true,"description":"Transfer fee in cents. Null when no fee row exists."},"price_dollars":{"type":"number","nullable":true,"description":"Transfer fee in dollars (computed from price_cents)."}}}}}}
```

## The TransferSettingsUpdate object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"TransferSettingsUpdate":{"type":"object","properties":{"allow_transfers":{"type":"boolean"},"allow_event_variant_transfers":{"type":"boolean"},"price_cents":{"type":"integer","minimum":0,"description":"Transfer fee in cents. 0 clears the fee row."},"price_dollars":{"type":"number","minimum":0,"description":"Alternative to price_cents."},"close_date":{"type":"string","format":"date-time","nullable":true}}}}}}
```

## The FundraisingSettings object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"FundraisingSettings":{"type":"object","required":["peer_to_peer_fundraiser","team_fundraiser","registration_included_in_donation_goal","donation_goal_cents","donation_goal_dollars"],"properties":{"peer_to_peer_fundraiser":{"type":"boolean","description":"Whether individual participants can create personal fundraisers."},"team_fundraiser":{"type":"boolean","description":"Whether teams can fundraise collectively."},"registration_included_in_donation_goal":{"type":"boolean","description":"Whether registration revenue counts toward the donation goal."},"donation_goal_cents":{"type":"integer","nullable":true,"description":"Fundraising goal in cents. Null when no goal is set."},"donation_goal_dollars":{"type":"number","nullable":true,"description":"Fundraising goal in dollars (computed from donation_goal_cents)."}}}}}}
```

## The FundraisingSettingsUpdate object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"FundraisingSettingsUpdate":{"type":"object","properties":{"peer_to_peer_fundraiser":{"type":"boolean"},"team_fundraiser":{"type":"boolean"},"registration_included_in_donation_goal":{"type":"boolean"},"donation_goal_dollars":{"type":"number","minimum":0,"nullable":true,"description":"Fundraising goal in dollars. 0 or null clears the goal."},"donation_goal_cents":{"type":"integer","minimum":0,"nullable":true,"description":"Alternative to donation_goal_dollars, in cents."}}}}}}
```

## The DeferralSchedule object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"DeferralSchedule":{"type":"object","required":["id","defer_to_event_id","defer_to_group_id","valid_until","timezone","discount_type","discount_amount"],"properties":{"id":{"type":"integer","format":"int64"},"defer_to_event_id":{"type":"integer","format":"int64","nullable":true,"description":"Event id participants get credit for, or null if the credit goes to a Group."},"defer_to_group_id":{"type":"integer","format":"int64","nullable":true,"description":"Group id participants get credit for, or null when defer_to_event_id is set."},"valid_until":{"type":"string","format":"date-time","nullable":true,"description":"Cutoff datetime for accepting deferral requests."},"timezone":{"type":"string","nullable":true,"description":"IANA timezone of the schedule."},"discount_type":{"type":"string","enum":["percentage","fixed_amount"]},"discount_amount":{"type":"integer","description":"0–100 when discount_type=percentage, integer cents when fixed_amount."}}}}}}
```

## The DeferralScheduleUpdate object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"DeferralScheduleUpdate":{"type":"object","properties":{"allow_deferrals":{"type":"boolean","description":"Pass false to delete all deferral schedules for the event."},"defer_to_event_id":{"type":"integer","format":"int64","nullable":true,"description":"Required (when allow_deferrals is not false). Event id the participant will get credit for."},"valid_until":{"type":"string","format":"date-time","nullable":true},"timezone":{"type":"string","nullable":true},"discount_type":{"type":"string","enum":["percentage","fixed_amount"]},"discount_amount":{"type":"number","description":"0–100 when percentage; integer cents when fixed_amount."}}}}}}
```

## The Tag object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"Tag":{"type":"object","required":["id","group","name","icon_name"],"properties":{"id":{"type":"integer","format":"int64"},"group":{"type":"string","enum":["activity_type","event_type","maternity_and_family","adaptability"]},"name":{"type":"string"},"icon_name":{"type":"string","nullable":true}}}}}}
```

## The Tagging object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"Tagging":{"type":"object","required":["id","tag_id","group","name"],"properties":{"id":{"type":"integer","format":"int64"},"tag_id":{"type":"integer","format":"int64"},"group":{"type":"string","enum":["activity_type","event_type","maternity_and_family","adaptability"]},"name":{"type":"string"}}}}}}
```

## The AttachTagRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"AttachTagRequest":{"type":"object","description":"Provide either {group, name} or {tag_id}.","properties":{"group":{"type":"string","enum":["activity_type","event_type","maternity_and_family","adaptability"]},"name":{"type":"string"},"tag_id":{"type":"integer","format":"int64"}}}}}}
```

## The ReplaceTaggingsRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"ReplaceTaggingsRequest":{"type":"object","required":["tags"],"properties":{"tags":{"type":"array","items":{"type":"object","required":["group","name"],"properties":{"group":{"type":"string","enum":["activity_type","event_type","maternity_and_family","adaptability"]},"name":{"type":"string"}}}}}}}}}
```

## The CustomQuestionOption object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"CustomQuestionOption":{"type":"object","required":["id","label"],"properties":{"id":{"type":"integer","format":"int64"},"label":{"type":"string"}}}}}}
```

## The NestedQuestionChild object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"NestedQuestionChild":{"type":"object","description":"A conditional (nested) child question shown only when this question is answered with one of the trigger options. References a question that also appears in full elsewhere in the questions list.","required":["link_id","child_question_id","show_when"],"properties":{"link_id":{"type":"integer","format":"int64","description":"NestedQuestionLink id (used to delete the link)."},"child_question_id":{"type":"integer","format":"int64","description":"Question id (the `id` field) of the child question to show."},"show_when":{"type":"array","description":"Parent option labels that reveal the child question.","items":{"type":"string"}}}}}}}
```

## The CustomQuestion object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"CustomQuestion":{"type":"object","required":["id","question_id","title","question_type","required","order","starts_at","ends_at","options","children"],"properties":{"id":{"type":"integer","format":"int64","description":"TransactableCustomQuestion id (the link row, used for update/delete)."},"question_id":{"type":"integer","format":"int64"},"title":{"type":"string"},"question_type":{"type":"string","enum":["text","multiple_choice","time_hr_min_second","time_min_second"]},"required":{"type":"boolean"},"order":{"type":"integer"},"starts_at":{"type":"string","format":"date-time","nullable":true},"ends_at":{"type":"string","format":"date-time","nullable":true},"options":{"type":"array","description":"Answer options in the order they are shown to registrants.","items":{"$ref":"#/components/schemas/CustomQuestionOption"}},"children":{"type":"array","description":"Conditional child questions revealed by this question's answers. Only multiple-choice questions can have children; empty otherwise.","items":{"$ref":"#/components/schemas/NestedQuestionChild"}}}},"CustomQuestionOption":{"type":"object","required":["id","label"],"properties":{"id":{"type":"integer","format":"int64"},"label":{"type":"string"}}},"NestedQuestionChild":{"type":"object","description":"A conditional (nested) child question shown only when this question is answered with one of the trigger options. References a question that also appears in full elsewhere in the questions list.","required":["link_id","child_question_id","show_when"],"properties":{"link_id":{"type":"integer","format":"int64","description":"NestedQuestionLink id (used to delete the link)."},"child_question_id":{"type":"integer","format":"int64","description":"Question id (the `id` field) of the child question to show."},"show_when":{"type":"array","description":"Parent option labels that reveal the child question.","items":{"type":"string"}}}}}}}
```

## The CreateQuestionRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"CreateQuestionRequest":{"type":"object","required":["title","question_type"],"properties":{"title":{"type":"string"},"question_type":{"type":"string","enum":["text","multiple_choice","time_hr_min_second","time_min_second"]},"required":{"type":"boolean"},"options":{"type":"array","description":"Answer options, in the order registrants should see them.","items":{"type":"string"}},"starts_at":{"type":"string","format":"date-time"},"ends_at":{"type":"string","format":"date-time"}}}}}}
```

## The UpdateQuestionRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"UpdateQuestionRequest":{"type":"object","properties":{"title":{"type":"string"},"question_type":{"type":"string","enum":["text","multiple_choice","time_hr_min_second","time_min_second"]},"required":{"type":"boolean"},"options":{"type":"array","description":"Replaces the full option list, in the order registrants should see them. Options matched by text keep their existing id (and any nesting triggers or CRM filters pointing at them) and are repositioned to match; unlisted options are removed.","items":{"type":"string"}},"starts_at":{"type":"string","format":"date-time"},"ends_at":{"type":"string","format":"date-time"}}}}}}
```

## The CreateNestedQuestionLinkRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"CreateNestedQuestionLinkRequest":{"type":"object","required":["child_question_id","answer_matches"],"properties":{"child_question_id":{"type":"integer","format":"int64","description":"Question id (the `id` field of an event-level question) to reveal when the parent is answered with one of `answer_matches`."},"answer_matches":{"type":"array","minItems":1,"description":"Parent options that trigger the child. Each entry is either an option id (integer) or an exact option label (string). Errors if an entry matches no option or a label is ambiguous. Each parent option can be used by at most one link.","items":{"oneOf":[{"type":"integer","format":"int64"},{"type":"string"}]}}}}}}}
```

## The NestedQuestionLink object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"NestedQuestionLink":{"type":"object","required":["link_id","parent_question_id","child_question_id","show_when"],"properties":{"link_id":{"type":"integer","format":"int64"},"parent_question_id":{"type":"integer","format":"int64","description":"Question id (the `id` field) of the parent question."},"child_question_id":{"type":"integer","format":"int64","description":"Question id (the `id` field) of the child question."},"show_when":{"type":"array","description":"Parent option labels that reveal the child question.","items":{"type":"string"}}}}}}}
```

## The VolunteerTimeSlot object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"VolunteerTimeSlot":{"type":"object","required":["id","start_datetime","end_datetime","limit"],"properties":{"id":{"type":"integer","format":"int64"},"start_datetime":{"type":"string","format":"date-time","nullable":true},"end_datetime":{"type":"string","format":"date-time","nullable":true},"limit":{"type":"integer","nullable":true}}}}}}
```

## The VolunteerCategory object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"VolunteerCategory":{"type":"object","required":["id","name","description","limit","active","volunteer_count","time_slots"],"properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"limit":{"type":"integer","nullable":true},"active":{"type":"boolean"},"volunteer_count":{"type":"integer"},"time_slots":{"type":"array","items":{"$ref":"#/components/schemas/VolunteerTimeSlot"}}}},"VolunteerTimeSlot":{"type":"object","required":["id","start_datetime","end_datetime","limit"],"properties":{"id":{"type":"integer","format":"int64"},"start_datetime":{"type":"string","format":"date-time","nullable":true},"end_datetime":{"type":"string","format":"date-time","nullable":true},"limit":{"type":"integer","nullable":true}}}}}}
```

## The CreateVolunteerCategoryRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"CreateVolunteerCategoryRequest":{"type":"object","required":["name"],"properties":{"name":{"type":"string"},"description":{"type":"string"},"limit":{"type":"integer","minimum":0},"active":{"type":"boolean"}}}}}}
```

## The UpdateVolunteerCategoryRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"UpdateVolunteerCategoryRequest":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"limit":{"type":"integer","minimum":0},"active":{"type":"boolean"}}}}}}
```

## The CreateVolunteerTimeSlotRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"CreateVolunteerTimeSlotRequest":{"type":"object","required":["start_datetime","end_datetime"],"properties":{"start_datetime":{"type":"string","format":"date-time"},"end_datetime":{"type":"string","format":"date-time"},"limit":{"type":"integer","minimum":0}}}}}}
```

## The UpdateVolunteerTimeSlotRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"UpdateVolunteerTimeSlotRequest":{"type":"object","properties":{"start_datetime":{"type":"string","format":"date-time"},"end_datetime":{"type":"string","format":"date-time"},"limit":{"type":"integer","minimum":0}}}}}}
```

## The Discount object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"Discount":{"type":"object","required":["id","redemption_code","percentage_off","fixed_amount_off_cents","fixed_amount_off_dollars","times_redeemable","times_redeemed","redeem_by","description","minimum_event_participant_count","eligible_event_variant_ids"],"properties":{"id":{"type":"integer","format":"int64"},"redemption_code":{"type":"string"},"percentage_off":{"type":"integer","nullable":true},"fixed_amount_off_cents":{"type":"integer","nullable":true},"fixed_amount_off_dollars":{"type":"number","nullable":true},"times_redeemable":{"type":"integer","nullable":true},"times_redeemed":{"type":"integer"},"redeem_by":{"type":"string","format":"date-time","nullable":true},"description":{"type":"string","nullable":true},"minimum_event_participant_count":{"type":"integer","nullable":true},"eligible_event_variant_ids":{"type":"array","items":{"type":"integer","format":"int64"}}}}}}}
```

## The CreateDiscountRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"CreateDiscountRequest":{"type":"object","required":["redemption_code"],"properties":{"redemption_code":{"type":"string"},"percentage_off":{"type":"integer","minimum":1,"maximum":100},"fixed_amount_off_cents":{"type":"integer","minimum":1},"times_redeemable":{"type":"integer","minimum":0},"redeem_by":{"type":"string","format":"date-time"},"description":{"type":"string"},"minimum_event_participant_count":{"type":"integer","minimum":0},"eligible_event_variant_ids":{"type":"array","items":{"type":"integer"}}}}}}}
```

## The UpdateDiscountRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"UpdateDiscountRequest":{"type":"object","properties":{"redemption_code":{"type":"string"},"percentage_off":{"type":"integer","minimum":1,"maximum":100},"fixed_amount_off_cents":{"type":"integer","minimum":1},"times_redeemable":{"type":"integer","minimum":0},"redeem_by":{"type":"string","format":"date-time"},"description":{"type":"string"},"eligible_event_variant_ids":{"type":"array","items":{"type":"integer"}}}}}}}
```

## The Credit object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"Credit":{"type":"object","required":["id","code","amount_cents","amount_dollars","remaining_balance_cents","remaining_balance_dollars","currency","expiration_date","first_name","last_name","email","applies_to_merchandise"],"properties":{"id":{"type":"integer","format":"int64"},"code":{"type":"string"},"amount_cents":{"type":"integer"},"amount_dollars":{"type":"number"},"remaining_balance_cents":{"type":"integer"},"remaining_balance_dollars":{"type":"number"},"currency":{"type":"string"},"expiration_date":{"type":"string","format":"date-time","nullable":true},"first_name":{"type":"string","nullable":true},"last_name":{"type":"string","nullable":true},"email":{"type":"string","nullable":true},"applies_to_merchandise":{"type":"boolean"}}}}}}
```

## The CreditWritableFields object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"CreditWritableFields":{"type":"object","properties":{"code":{"type":"string"},"currency":{"type":"string","enum":["USD","CAD","AUD","DKK","NOK","MXN","GBP","EUR"]},"expiration_date":{"type":"string","format":"date-time"},"first_name":{"type":"string"},"last_name":{"type":"string"},"email":{"type":"string"},"applies_to_merchandise":{"type":"boolean"},"email_credit_to_participant":{"type":"boolean","description":"Defaults to true; set false to suppress the recipient email on create."}}}}}}
```

## The CreateCreditRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"CreateCreditRequest":{"allOf":[{"$ref":"#/components/schemas/CreditWritableFields"},{"type":"object","required":["code","amount_cents"],"properties":{"amount_cents":{"type":"integer","minimum":1}}}]},"CreditWritableFields":{"type":"object","properties":{"code":{"type":"string"},"currency":{"type":"string","enum":["USD","CAD","AUD","DKK","NOK","MXN","GBP","EUR"]},"expiration_date":{"type":"string","format":"date-time"},"first_name":{"type":"string"},"last_name":{"type":"string"},"email":{"type":"string"},"applies_to_merchandise":{"type":"boolean"},"email_credit_to_participant":{"type":"boolean","description":"Defaults to true; set false to suppress the recipient email on create."}}}}}}
```

## The UpdateCreditRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"UpdateCreditRequest":{"allOf":[{"$ref":"#/components/schemas/CreditWritableFields"},{"type":"object","properties":{"amount_cents":{"type":"integer","minimum":1,"description":"New face value; the same delta is applied to the remaining balance."}}}]},"CreditWritableFields":{"type":"object","properties":{"code":{"type":"string"},"currency":{"type":"string","enum":["USD","CAD","AUD","DKK","NOK","MXN","GBP","EUR"]},"expiration_date":{"type":"string","format":"date-time"},"first_name":{"type":"string"},"last_name":{"type":"string"},"email":{"type":"string"},"applies_to_merchandise":{"type":"boolean"},"email_credit_to_participant":{"type":"boolean","description":"Defaults to true; set false to suppress the recipient email on create."}}}}}}
```

## The CreateInvitedParticipantsRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"CreateInvitedParticipantsRequest":{"type":"object","required":["event_variant_id","emails"],"properties":{"event_variant_id":{"type":"integer","format":"int64","description":"The sub-event (event variant) to invite people to."},"emails":{"type":"array","minItems":1,"items":{"type":"string","format":"email"},"description":"Email addresses to invite. Duplicates and blanks are ignored, and\nanyone already invited to the sub-event is skipped rather than\nre-emailed.\n"},"custom_message":{"type":"string","description":"Optional personal note included in the invitation email."}}}}}}
```

## The InvitedParticipant object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"InvitedParticipant":{"type":"object","required":["confirmation_number","email","event_variant_id","status"],"properties":{"confirmation_number":{"type":"string"},"email":{"type":"string","format":"email"},"event_variant_id":{"type":"integer","format":"int64"},"status":{"type":"string","enum":["pending","claimed","expired"],"description":"A freshly created invitation is always `pending`."}}}}}}
```

## The InvitedParticipantsResult object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"InvitedParticipantsResult":{"type":"object","required":["created","skipped","errors"],"properties":{"created":{"type":"array","description":"Invitations created and emailed this request.","items":{"$ref":"#/components/schemas/InvitedParticipant"}},"skipped":{"type":"array","description":"Emails already invited to this sub-event (not re-emailed).","items":{"type":"string","format":"email"}},"errors":{"type":"array","description":"Per-email failure messages, if any.","items":{"type":"string"}}}},"InvitedParticipant":{"type":"object","required":["confirmation_number","email","event_variant_id","status"],"properties":{"confirmation_number":{"type":"string"},"email":{"type":"string","format":"email"},"event_variant_id":{"type":"integer","format":"int64"},"status":{"type":"string","enum":["pending","claimed","expired"],"description":"A freshly created invitation is always `pending`."}}}}}}
```

## The Wave object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"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","answer_transactable_custom_question_id","question_multiple_choice_option_ids","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":"TransactableCustomQuestion id of the time-based question whose answer gates eligibility, when set — not the underlying Question id. Independent of answer_transactable_custom_question_id: a wave carrying both gates admits only participants who clear both."},"min_time_seconds":{"type":"integer","nullable":true},"max_time_seconds":{"type":"integer","nullable":true},"answer_transactable_custom_question_id":{"type":"integer","format":"int64","nullable":true,"description":"TransactableCustomQuestion id of the multiple-choice question whose selected answers gate eligibility, when set — not the underlying Question id, and specific to the sub-event the question is attached to. Independent of transactable_custom_question_id: a wave carrying both gates admits only participants who clear both."},"question_multiple_choice_option_ids":{"type":"array","description":"QuestionMultipleChoiceOption ids this wave admits, all belonging to answer_transactable_custom_question_id's question. THE ORDER IS THE WAVE'S FILL ORDER — the wave takes everyone matching its first option, then its second, and so on until capacity — and it is this wave's own order, independent of the question's option order. An option may appear on several waves deliberately: a participant lands in the first wave, by position, that admits them and has room, so a repeated option spills an oversized answer group across waves.","items":{"type":"integer","format":"int64"}},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}}}}
```

## The WaveWritableFields object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"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":"TransactableCustomQuestion id of the time-based question to gate on — the question as attached to this event or one of its sub-events, NOT the underlying Question id, and not interchangeable with it. Get it from `GET /api/v1/events/{handle}/wave_gate_questions`, whose rows carry it as `id` (with the Question id alongside as `question_id`, which no wave endpoint accepts). One question attached to several sub-events is several rows sharing a `question_id`; pick the row for the sub-event you mean, or the gate reads a different sub-event's answers while looking correct. 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},"answer_transactable_custom_question_id":{"type":"integer","format":"int64","description":"TransactableCustomQuestion id of the multiple-choice question to gate on — same id space as `transactable_custom_question_id` above, and the same warnings apply: not the Question id, and specific to the sub-event the question is attached to. Required alongside `question_multiple_choice_option_ids`; sending this alone leaves the gate unconfigured, and clearing it clears the mapped options."},"question_multiple_choice_option_ids":{"type":"array","description":"Option ids to admit, in the order this wave should fill from them — the array order is significant and is independent of the question's own option order. Replace-not-merge: the ids sent become the wave's entire mapping. Ids outside answer_transactable_custom_question_id's question are ignored. Listing an option that another wave also lists is legitimate — a participant lands in the first wave, by position, that admits them and has room.","items":{"type":"integer","format":"int64"}},"event_variant_ids":{"type":"array","description":"Sub-event ids to link. Replace-not-merge. Pass [] for a shared wave.","items":{"type":"integer","format":"int64"}}}}}}}
```

## The CreateWaveRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"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":"TransactableCustomQuestion id of the time-based question to gate on — the question as attached to this event or one of its sub-events, NOT the underlying Question id, and not interchangeable with it. Get it from `GET /api/v1/events/{handle}/wave_gate_questions`, whose rows carry it as `id` (with the Question id alongside as `question_id`, which no wave endpoint accepts). One question attached to several sub-events is several rows sharing a `question_id`; pick the row for the sub-event you mean, or the gate reads a different sub-event's answers while looking correct. 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},"answer_transactable_custom_question_id":{"type":"integer","format":"int64","description":"TransactableCustomQuestion id of the multiple-choice question to gate on — same id space as `transactable_custom_question_id` above, and the same warnings apply: not the Question id, and specific to the sub-event the question is attached to. Required alongside `question_multiple_choice_option_ids`; sending this alone leaves the gate unconfigured, and clearing it clears the mapped options."},"question_multiple_choice_option_ids":{"type":"array","description":"Option ids to admit, in the order this wave should fill from them — the array order is significant and is independent of the question's own option order. Replace-not-merge: the ids sent become the wave's entire mapping. Ids outside answer_transactable_custom_question_id's question are ignored. Listing an option that another wave also lists is legitimate — a participant lands in the first wave, by position, that admits them and has room.","items":{"type":"integer","format":"int64"}},"event_variant_ids":{"type":"array","description":"Sub-event ids to link. Replace-not-merge. Pass [] for a shared wave.","items":{"type":"integer","format":"int64"}}}}}}}
```

## The UpdateWaveRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"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":"TransactableCustomQuestion id of the time-based question to gate on — the question as attached to this event or one of its sub-events, NOT the underlying Question id, and not interchangeable with it. Get it from `GET /api/v1/events/{handle}/wave_gate_questions`, whose rows carry it as `id` (with the Question id alongside as `question_id`, which no wave endpoint accepts). One question attached to several sub-events is several rows sharing a `question_id`; pick the row for the sub-event you mean, or the gate reads a different sub-event's answers while looking correct. 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},"answer_transactable_custom_question_id":{"type":"integer","format":"int64","description":"TransactableCustomQuestion id of the multiple-choice question to gate on — same id space as `transactable_custom_question_id` above, and the same warnings apply: not the Question id, and specific to the sub-event the question is attached to. Required alongside `question_multiple_choice_option_ids`; sending this alone leaves the gate unconfigured, and clearing it clears the mapped options."},"question_multiple_choice_option_ids":{"type":"array","description":"Option ids to admit, in the order this wave should fill from them — the array order is significant and is independent of the question's own option order. Replace-not-merge: the ids sent become the wave's entire mapping. Ids outside answer_transactable_custom_question_id's question are ignored. Listing an option that another wave also lists is legitimate — a participant lands in the first wave, by position, that admits them and has room.","items":{"type":"integer","format":"int64"}},"event_variant_ids":{"type":"array","description":"Sub-event ids to link. Replace-not-merge. Pass [] for a shared wave.","items":{"type":"integer","format":"int64"}}}}}}}
```

## The WaveGateQuestionList object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"WaveGateQuestionList":{"type":"object","required":["questions"],"properties":{"questions":{"type":"array","description":"Every question a wave on this event can gate on, in the organizer's display order. Empty when the event asks no time-based or multiple-choice question its registrants can answer. Each row carries its own denominator (`eligible_participant_count`), so \"N of M answered\" reads off a single row without combining scopes.","items":{"$ref":"#/components/schemas/WaveGateQuestion"}}}},"WaveGateQuestion":{"type":"object","required":["id","question_id","title","label","sub_event_id","sub_event_name","sub_transactable_type","time_based","multiple_choice","eligible_participant_count","answered_participant_count","options"],"properties":{"id":{"type":"integer","format":"int64","description":"The TransactableCustomQuestion id — the question as attached to this event or one of its sub-events. THIS is the id a wave's gate points at: send it as `answer_transactable_custom_question_id` when `multiple_choice` is true, or as `transactable_custom_question_id` when `time_based` is true. Do not send `question_id` in its place; the two id spaces are unrelated and a Question id here matches a different question or none."},"question_id":{"type":"integer","format":"int64","description":"The underlying Question. Rows sharing this value are the same question attached to different sub-events (or to different sub-audiences of one), sharing a title and an option set while holding separate answers. Informational only — no wave endpoint accepts it."},"title":{"type":"string","description":"The question as the organizer wrote it. Not unique across rows."},"label":{"type":"string","description":"The title qualified by what this row alone covers — its sub-event and its sub-audience, when it has them. Use this, not `title`, to tell sibling rows apart when presenting a choice."},"sub_event_id":{"type":"integer","format":"int64","nullable":true,"description":"The sub-event this row hangs off, or null when it is attached to the event and therefore covers every registrant."},"sub_event_name":{"type":"string","nullable":true},"sub_transactable_type":{"type":"string","nullable":true,"enum":["relay_captain","relay_teammate"],"description":"The sub-audience within the transactable that answers this row, or null when every registrant does. Only participant-answered audiences appear here; volunteer and waitlist rows are not returned at all."},"time_based":{"type":"boolean","description":"The answer is an elapsed time, so this question can drive a wave's TIME gate via `transactable_custom_question_id` plus `min_time_seconds` / `max_time_seconds`."},"multiple_choice":{"type":"boolean","description":"The answer is one of `options`, so this question can drive a wave's ANSWER gate via `answer_transactable_custom_question_id` plus `question_multiple_choice_option_ids`."},"eligible_participant_count":{"type":"integer","nullable":true,"description":"Registrants who could answer this question — the population the question is actually put to, and the denominator its option counts sit under.\n**On a multiple-choice row, unanswered = this minus `answered_participant_count`**: how many people an answer-gated wave built from these options would not admit, and therefore whether the split needs an ungated catch-all wave. The subtraction is meaningless on a time-based row, which has no options and so always reports `answered_participant_count: 0` — that zero means \"not counted here\", not \"nobody answered\".\nScoped the way the question is: a row attached to the event counts every registrant, while a row attached to a sub-event counts only that sub-event's registrants. Do not compare a sub-event question's option counts against the event's field size — the people in other sub-events were never asked.\n**Null when `sub_transactable_type` is set.** A `relay_captain` / `relay_teammate` row is put to a slice of its sub-event — one captain per team, or the teammates around them — and that slice is not expressible as a single grouped count, so it is not computed. Skip the subtraction on those rows rather than substituting the sub-event's field size: a 100-registrant relay across 25 teams would read as 75 captains yet to answer when in fact every captain has."},"answered_participant_count":{"type":"integer","description":"Registrants whose answer matches one of `options` — the sum of the per-option counts. Always 0 for a time-based question, which has no options to count against, so do not read that zero as an unanswered field. An answer left over from an option the organizer has since renamed or deleted matches nothing and is counted nowhere, so this can sit below the number of people who actually answered."},"options":{"type":"array","description":"The selectable answers, in the organizer's option order. Empty for a time-based question. This order is the QUESTION's; it is not the order a wave fills from, which each wave sets for itself.","items":{"$ref":"#/components/schemas/WaveGateQuestionOption"}}}},"WaveGateQuestionOption":{"type":"object","required":["id","option_text","position","participant_count"],"properties":{"id":{"type":"integer","format":"int64","description":"The QuestionMultipleChoiceOption id. Goes into a wave's `question_multiple_choice_option_ids`, where THE ARRAY ORDER IS THE WAVE'S FILL ORDER — the wave takes everyone matching its first option, then its second, and so on until it reaches capacity. That order is the wave's own and is independent of `position` below. The same option id may be listed on several waves on purpose: a participant lands in the first wave, by wave position, that both admits their answer and has room, so repeating an option on a later wave is how an oversized answer group spills across waves."},"option_text":{"type":"string","description":"What the participant sees, and what an answer physically stores — an option's count is its text's count, which is why renaming an option orphans the answers already given under the old text."},"position":{"type":"integer","description":"The option's index within the question, as the organizer ordered them. Presentation order only; a wave's fill order is set per wave."},"participant_count":{"type":"integer","description":"Registrants of THIS event who currently picked this option. Live at request time — it moves as registrations arrive — and the number to size a wave's capacity against."}}}}}}
```

## The WaveGateQuestion object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"WaveGateQuestion":{"type":"object","required":["id","question_id","title","label","sub_event_id","sub_event_name","sub_transactable_type","time_based","multiple_choice","eligible_participant_count","answered_participant_count","options"],"properties":{"id":{"type":"integer","format":"int64","description":"The TransactableCustomQuestion id — the question as attached to this event or one of its sub-events. THIS is the id a wave's gate points at: send it as `answer_transactable_custom_question_id` when `multiple_choice` is true, or as `transactable_custom_question_id` when `time_based` is true. Do not send `question_id` in its place; the two id spaces are unrelated and a Question id here matches a different question or none."},"question_id":{"type":"integer","format":"int64","description":"The underlying Question. Rows sharing this value are the same question attached to different sub-events (or to different sub-audiences of one), sharing a title and an option set while holding separate answers. Informational only — no wave endpoint accepts it."},"title":{"type":"string","description":"The question as the organizer wrote it. Not unique across rows."},"label":{"type":"string","description":"The title qualified by what this row alone covers — its sub-event and its sub-audience, when it has them. Use this, not `title`, to tell sibling rows apart when presenting a choice."},"sub_event_id":{"type":"integer","format":"int64","nullable":true,"description":"The sub-event this row hangs off, or null when it is attached to the event and therefore covers every registrant."},"sub_event_name":{"type":"string","nullable":true},"sub_transactable_type":{"type":"string","nullable":true,"enum":["relay_captain","relay_teammate"],"description":"The sub-audience within the transactable that answers this row, or null when every registrant does. Only participant-answered audiences appear here; volunteer and waitlist rows are not returned at all."},"time_based":{"type":"boolean","description":"The answer is an elapsed time, so this question can drive a wave's TIME gate via `transactable_custom_question_id` plus `min_time_seconds` / `max_time_seconds`."},"multiple_choice":{"type":"boolean","description":"The answer is one of `options`, so this question can drive a wave's ANSWER gate via `answer_transactable_custom_question_id` plus `question_multiple_choice_option_ids`."},"eligible_participant_count":{"type":"integer","nullable":true,"description":"Registrants who could answer this question — the population the question is actually put to, and the denominator its option counts sit under.\n**On a multiple-choice row, unanswered = this minus `answered_participant_count`**: how many people an answer-gated wave built from these options would not admit, and therefore whether the split needs an ungated catch-all wave. The subtraction is meaningless on a time-based row, which has no options and so always reports `answered_participant_count: 0` — that zero means \"not counted here\", not \"nobody answered\".\nScoped the way the question is: a row attached to the event counts every registrant, while a row attached to a sub-event counts only that sub-event's registrants. Do not compare a sub-event question's option counts against the event's field size — the people in other sub-events were never asked.\n**Null when `sub_transactable_type` is set.** A `relay_captain` / `relay_teammate` row is put to a slice of its sub-event — one captain per team, or the teammates around them — and that slice is not expressible as a single grouped count, so it is not computed. Skip the subtraction on those rows rather than substituting the sub-event's field size: a 100-registrant relay across 25 teams would read as 75 captains yet to answer when in fact every captain has."},"answered_participant_count":{"type":"integer","description":"Registrants whose answer matches one of `options` — the sum of the per-option counts. Always 0 for a time-based question, which has no options to count against, so do not read that zero as an unanswered field. An answer left over from an option the organizer has since renamed or deleted matches nothing and is counted nowhere, so this can sit below the number of people who actually answered."},"options":{"type":"array","description":"The selectable answers, in the organizer's option order. Empty for a time-based question. This order is the QUESTION's; it is not the order a wave fills from, which each wave sets for itself.","items":{"$ref":"#/components/schemas/WaveGateQuestionOption"}}}},"WaveGateQuestionOption":{"type":"object","required":["id","option_text","position","participant_count"],"properties":{"id":{"type":"integer","format":"int64","description":"The QuestionMultipleChoiceOption id. Goes into a wave's `question_multiple_choice_option_ids`, where THE ARRAY ORDER IS THE WAVE'S FILL ORDER — the wave takes everyone matching its first option, then its second, and so on until it reaches capacity. That order is the wave's own and is independent of `position` below. The same option id may be listed on several waves on purpose: a participant lands in the first wave, by wave position, that both admits their answer and has room, so repeating an option on a later wave is how an oversized answer group spills across waves."},"option_text":{"type":"string","description":"What the participant sees, and what an answer physically stores — an option's count is its text's count, which is why renaming an option orphans the answers already given under the old text."},"position":{"type":"integer","description":"The option's index within the question, as the organizer ordered them. Presentation order only; a wave's fill order is set per wave."},"participant_count":{"type":"integer","description":"Registrants of THIS event who currently picked this option. Live at request time — it moves as registrations arrive — and the number to size a wave's capacity against."}}}}}}
```

## The WaveGateQuestionOption object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"WaveGateQuestionOption":{"type":"object","required":["id","option_text","position","participant_count"],"properties":{"id":{"type":"integer","format":"int64","description":"The QuestionMultipleChoiceOption id. Goes into a wave's `question_multiple_choice_option_ids`, where THE ARRAY ORDER IS THE WAVE'S FILL ORDER — the wave takes everyone matching its first option, then its second, and so on until it reaches capacity. That order is the wave's own and is independent of `position` below. The same option id may be listed on several waves on purpose: a participant lands in the first wave, by wave position, that both admits their answer and has room, so repeating an option on a later wave is how an oversized answer group spills across waves."},"option_text":{"type":"string","description":"What the participant sees, and what an answer physically stores — an option's count is its text's count, which is why renaming an option orphans the answers already given under the old text."},"position":{"type":"integer","description":"The option's index within the question, as the organizer ordered them. Presentation order only; a wave's fill order is set per wave."},"participant_count":{"type":"integer","description":"Registrants of THIS event who currently picked this option. Live at request time — it moves as registrations arrive — and the number to size a wave's capacity against."}}}}}}
```

## The WaveAssignment object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"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}}}}}}
```

## The AssignParticipantRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"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."}}}}}}
```

## The BulkWaveAssignmentRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"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"}}}}}}}}}
```

## The WaveGenerationRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"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."}}}}}}
```

## The WaveGenerationResult object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"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}}}}}}}}}
```

## The WaveSettings object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"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"}}}}}}}}}
```

## The WaveSettingsUpdateRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"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"}}}}}}}
```

## The WaveParticipantList object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"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"}}}}}}
```

## The ReferralPolicy object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"ReferralPolicy":{"type":"object","required":["id","active","referrer_cents","referrer_dollars","referee_cents","referee_dollars"],"properties":{"id":{"type":"integer","format":"int64"},"active":{"type":"boolean"},"referrer_cents":{"type":"integer"},"referrer_dollars":{"type":"number"},"referee_cents":{"type":"integer"},"referee_dollars":{"type":"number"}}}}}}
```

## The ReferralPolicyUpdate object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"ReferralPolicyUpdate":{"type":"object","properties":{"active":{"type":"boolean"},"referrer_cents":{"type":"integer","minimum":0},"referee_cents":{"type":"integer","minimum":0}}}}}}
```

## The Sponsor object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"Sponsor":{"type":"object","required":["id","sponsor_id","name","url","featured","order","logo_url"],"properties":{"id":{"type":"integer","format":"int64","description":"EventsSponsor link id (used for update/delete)."},"sponsor_id":{"type":"integer","format":"int64"},"name":{"type":"string"},"url":{"type":"string","nullable":true},"featured":{"type":"boolean"},"order":{"type":"integer","nullable":true},"logo_url":{"type":"string","nullable":true}}}}}}
```

## The CreateSponsorRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"CreateSponsorRequest":{"type":"object","required":["name","logo_url"],"properties":{"name":{"type":"string"},"url":{"type":"string"},"logo_url":{"type":"string","format":"uri"},"featured":{"type":"boolean"}}}}}}
```

## The UpdateSponsorRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"UpdateSponsorRequest":{"type":"object","properties":{"name":{"type":"string"},"url":{"type":"string"},"logo_url":{"type":"string","format":"uri"},"featured":{"type":"boolean"}}}}}}
```

## The DonationCategory object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"DonationCategory":{"type":"object","required":["id","name","description","website","active","donation_goal_cents","order","suggested_amounts_dollars","default_amount_dollars","logo_attached","stripe_product_id"],"properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"website":{"type":"string","nullable":true},"active":{"type":"boolean"},"donation_goal_cents":{"type":"integer","nullable":true},"order":{"type":"integer","nullable":true},"suggested_amounts_dollars":{"type":"array","items":{"type":"number"}},"default_amount_dollars":{"type":"number","nullable":true},"logo_attached":{"type":"boolean"},"stripe_product_id":{"type":"string","nullable":true}}}}}}
```

## The CreateDonationCategoryRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"CreateDonationCategoryRequest":{"type":"object","required":["name"],"properties":{"name":{"type":"string"},"description":{"type":"string"},"website":{"type":"string"},"active":{"type":"boolean"},"donation_goal_cents":{"type":"integer","minimum":0},"logo_url":{"type":"string","format":"uri"},"suggested_amounts_dollars":{"type":"array","items":{"type":"number"}},"default_amount_dollars":{"type":"number"}}}}}}
```

## The UpdateDonationCategoryRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"UpdateDonationCategoryRequest":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"website":{"type":"string"},"active":{"type":"boolean"},"donation_goal_cents":{"type":"integer","minimum":0},"logo_url":{"type":"string","format":"uri"},"suggested_amounts_dollars":{"type":"array","items":{"type":"number"}},"default_amount_dollars":{"type":"number"}}}}}}
```

## The StripeAccountRequiredError object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"StripeAccountRequiredError":{"type":"object","required":["error","message","connect_path"],"properties":{"error":{"type":"string","enum":["stripe_account_required"]},"message":{"type":"string"},"connect_path":{"type":"string"}}}}}}
```

## The MerchandiseOption object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"MerchandiseOption":{"type":"object","required":["id","name","quantity"],"properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"quantity":{"type":"integer","nullable":true}}}}}}
```

## The Merchandise object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"Merchandise":{"type":"object","required":["id","name","description","merchandise_type","price_cents","price_dollars","quantity","currency","active","show_in_store","show_in_registration","collect_shipping","stripe_product_id","options","photo_count"],"properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"merchandise_type":{"type":"string","enum":["clothing","food","lodging","other","other_non_taxable","athletic_membership"]},"price_cents":{"type":"integer"},"price_dollars":{"type":"number"},"quantity":{"type":"integer","nullable":true},"currency":{"type":"string"},"active":{"type":"boolean"},"show_in_store":{"type":"boolean"},"show_in_registration":{"type":"boolean"},"collect_shipping":{"type":"boolean"},"stripe_product_id":{"type":"string","nullable":true},"options":{"type":"array","items":{"$ref":"#/components/schemas/MerchandiseOption"}},"photo_count":{"type":"integer"}}},"MerchandiseOption":{"type":"object","required":["id","name","quantity"],"properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"quantity":{"type":"integer","nullable":true}}}}}}
```

## The CreateMerchandiseRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"CreateMerchandiseRequest":{"type":"object","required":["name","merchandise_type","price_cents"],"properties":{"name":{"type":"string"},"description":{"type":"string"},"merchandise_type":{"type":"string","enum":["clothing","food","lodging","other","other_non_taxable","athletic_membership"]},"price_cents":{"type":"integer","minimum":0},"quantity":{"type":"integer","minimum":0},"active":{"type":"boolean"},"show_in_store":{"type":"boolean"},"show_in_registration":{"type":"boolean"},"collect_shipping":{"type":"boolean"},"options":{"type":"array","items":{"type":"object","required":["name"],"properties":{"name":{"type":"string"},"quantity":{"type":"integer","minimum":0}}}},"images":{"type":"array","items":{"type":"string","format":"uri"}}}}}}}
```

## The UpdateMerchandiseRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"UpdateMerchandiseRequest":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"merchandise_type":{"type":"string","enum":["clothing","food","lodging","other","other_non_taxable","athletic_membership"]},"price_cents":{"type":"integer","minimum":0},"quantity":{"type":"integer","minimum":0},"active":{"type":"boolean"},"show_in_store":{"type":"boolean"},"show_in_registration":{"type":"boolean"},"collect_shipping":{"type":"boolean"},"options":{"type":"array","items":{"type":"object","required":["name"],"properties":{"name":{"type":"string"},"quantity":{"type":"integer","minimum":0}}}},"images":{"type":"array","items":{"type":"string","format":"uri"}}}}}}}
```

## The RequiredSelectionVariant object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"RequiredSelectionVariant":{"type":"object","required":["id","title","quantity"],"properties":{"id":{"type":"integer","format":"int64"},"title":{"type":"string"},"quantity":{"type":"integer","nullable":true}}}}}}
```

## The RequiredSelectionOption object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"RequiredSelectionOption":{"type":"object","required":["id","name","description","category","free","price_cents","quantity","active","offer_shipping","variants"],"properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"category":{"type":"string","enum":["clothing","food","lodging","other","other_non_taxable","athletic_membership"]},"free":{"type":"boolean","description":"True for the first option, whose price is forced to $0."},"price_cents":{"type":"integer"},"quantity":{"type":"integer","nullable":true},"active":{"type":"boolean"},"offer_shipping":{"type":"boolean"},"variants":{"type":"array","items":{"$ref":"#/components/schemas/RequiredSelectionVariant"}}}},"RequiredSelectionVariant":{"type":"object","required":["id","title","quantity"],"properties":{"id":{"type":"integer","format":"int64"},"title":{"type":"string"},"quantity":{"type":"integer","nullable":true}}}}}}
```

## The RequiredSelection object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"RequiredSelection":{"type":"object","required":["id","title","subtitle","requirement_scope","applies_to_all_sub_events","sub_event_ids","visibility","options"],"properties":{"id":{"type":"integer","format":"int64"},"title":{"type":"string"},"subtitle":{"type":"string","nullable":true},"requirement_scope":{"type":"string","enum":["per_cart","per_person","per_registration"]},"applies_to_all_sub_events":{"type":"boolean"},"sub_event_ids":{"type":"array","items":{"type":"integer","format":"int64"}},"visibility":{"type":"string","enum":["Shown","Hidden"]},"options":{"type":"array","items":{"$ref":"#/components/schemas/RequiredSelectionOption"}}}},"RequiredSelectionOption":{"type":"object","required":["id","name","description","category","free","price_cents","quantity","active","offer_shipping","variants"],"properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"category":{"type":"string","enum":["clothing","food","lodging","other","other_non_taxable","athletic_membership"]},"free":{"type":"boolean","description":"True for the first option, whose price is forced to $0."},"price_cents":{"type":"integer"},"quantity":{"type":"integer","nullable":true},"active":{"type":"boolean"},"offer_shipping":{"type":"boolean"},"variants":{"type":"array","items":{"$ref":"#/components/schemas/RequiredSelectionVariant"}}}},"RequiredSelectionVariant":{"type":"object","required":["id","title","quantity"],"properties":{"id":{"type":"integer","format":"int64"},"title":{"type":"string"},"quantity":{"type":"integer","nullable":true}}}}}}
```

## The RequiredSelectionWritableFields object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"RequiredSelectionWritableFields":{"type":"object","properties":{"title":{"type":"string"},"description":{"type":"string"},"requirement_scope":{"type":"string","enum":["per_registration","per_person","per_cart"],"description":"Defaults to per_registration."},"applies_to_all_sub_events":{"type":"boolean","description":"Defaults to true. Set false to restrict to sub_event_ids."},"sub_event_ids":{"type":"array","items":{"type":"integer"},"description":"Required when applies_to_all_sub_events is false."},"options":{"type":"array","description":"The first option is the free path (its price is forced to $0).","items":{"type":"object","required":["name","category"],"properties":{"id":{"type":"integer","description":"Existing option id to keep/edit; omit to add a new option."},"name":{"type":"string"},"description":{"type":"string"},"category":{"type":"string","enum":["clothing","food","lodging","other","other_non_taxable","athletic_membership"]},"price_cents":{"type":"integer","minimum":0},"quantity":{"type":"integer","minimum":0},"active":{"type":"boolean"},"offer_shipping":{"type":"boolean"},"variants":{"type":"array","items":{"type":"object","required":["title"],"properties":{"id":{"type":"integer","description":"Existing variant id to keep/edit; omit to add a new variant."},"title":{"type":"string"},"quantity":{"type":"integer","minimum":0}}}}}}}}}}}}
```

## The CreateRequiredSelectionRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"CreateRequiredSelectionRequest":{"allOf":[{"$ref":"#/components/schemas/RequiredSelectionWritableFields"},{"type":"object","required":["title","options"]}]},"RequiredSelectionWritableFields":{"type":"object","properties":{"title":{"type":"string"},"description":{"type":"string"},"requirement_scope":{"type":"string","enum":["per_registration","per_person","per_cart"],"description":"Defaults to per_registration."},"applies_to_all_sub_events":{"type":"boolean","description":"Defaults to true. Set false to restrict to sub_event_ids."},"sub_event_ids":{"type":"array","items":{"type":"integer"},"description":"Required when applies_to_all_sub_events is false."},"options":{"type":"array","description":"The first option is the free path (its price is forced to $0).","items":{"type":"object","required":["name","category"],"properties":{"id":{"type":"integer","description":"Existing option id to keep/edit; omit to add a new option."},"name":{"type":"string"},"description":{"type":"string"},"category":{"type":"string","enum":["clothing","food","lodging","other","other_non_taxable","athletic_membership"]},"price_cents":{"type":"integer","minimum":0},"quantity":{"type":"integer","minimum":0},"active":{"type":"boolean"},"offer_shipping":{"type":"boolean"},"variants":{"type":"array","items":{"type":"object","required":["title"],"properties":{"id":{"type":"integer","description":"Existing variant id to keep/edit; omit to add a new variant."},"title":{"type":"string"},"quantity":{"type":"integer","minimum":0}}}}}}}}}}}}
```

## The UpdateRequiredSelectionRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"UpdateRequiredSelectionRequest":{"description":"Partial update: send only the fields to change. Omit `options` to leave the option set untouched; include it to replace the entire set (an option's id keeps it, no id adds it), where the first option is always the free path.\n","allOf":[{"$ref":"#/components/schemas/RequiredSelectionWritableFields"}]},"RequiredSelectionWritableFields":{"type":"object","properties":{"title":{"type":"string"},"description":{"type":"string"},"requirement_scope":{"type":"string","enum":["per_registration","per_person","per_cart"],"description":"Defaults to per_registration."},"applies_to_all_sub_events":{"type":"boolean","description":"Defaults to true. Set false to restrict to sub_event_ids."},"sub_event_ids":{"type":"array","items":{"type":"integer"},"description":"Required when applies_to_all_sub_events is false."},"options":{"type":"array","description":"The first option is the free path (its price is forced to $0).","items":{"type":"object","required":["name","category"],"properties":{"id":{"type":"integer","description":"Existing option id to keep/edit; omit to add a new option."},"name":{"type":"string"},"description":{"type":"string"},"category":{"type":"string","enum":["clothing","food","lodging","other","other_non_taxable","athletic_membership"]},"price_cents":{"type":"integer","minimum":0},"quantity":{"type":"integer","minimum":0},"active":{"type":"boolean"},"offer_shipping":{"type":"boolean"},"variants":{"type":"array","items":{"type":"object","required":["title"],"properties":{"id":{"type":"integer","description":"Existing variant id to keep/edit; omit to add a new variant."},"title":{"type":"string"},"quantity":{"type":"integer","minimum":0}}}}}}}}}}}}
```

## The CourseMap object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"CourseMap":{"type":"object","required":["id","name","provider","provider_route_id","provider_created_at"],"properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"provider":{"type":"string","enum":["strava","ride_with_gps","other"]},"provider_route_id":{"type":"string","description":"Numeric provider id, returned as a string to avoid JS number precision loss."},"provider_created_at":{"type":"string","format":"date-time","nullable":true}}}}}}
```

## The CreateCourseMapRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"CreateCourseMapRequest":{"type":"object","description":"For Strava routes pass `{source: \"strava\", strava_route_id}`. For\nRide with GPS pass `{source: \"ride_with_gps\", route_id}`.\n","required":["source"],"properties":{"source":{"type":"string","enum":["strava","ride_with_gps"]},"strava_route_id":{"type":"integer"},"route_id":{"type":"integer"}}}}}}
```

## The CourseMapOAuthError object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"CourseMapOAuthError":{"type":"object","required":["error","provider","message"],"properties":{"error":{"type":"string","enum":["oauth_required","insufficient_scope"]},"provider":{"type":"string","enum":["strava","ride_with_gps"]},"message":{"type":"string"},"connect_url":{"type":"string"}}}}}}
```

## The UnknownTagError object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"UnknownTagError":{"type":"object","required":["error","message"],"properties":{"error":{"type":"string","enum":["unknown_tag"]},"message":{"type":"string"},"missing":{"type":"array","description":"Tags that did not resolve. Present on bulk-replace; absent on single-attach.","items":{"type":"object","properties":{"group":{"type":"string"},"name":{"type":"string"},"tag_id":{"type":"integer","format":"int64"}}}}}}}}}
```

## The Error object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"Error":{"type":"object","description":"A generic error response","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message"}}}}}}
```

## The ValidationError object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"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"}}}}}}
```

## The CrmEntitySummary object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"CrmEntitySummary":{"type":"object","description":"A single CRM record returned by search.","required":["crm_entity_id","entity_kind","full_name","email","event_handle","event_name","tags","has_notes"],"properties":{"crm_entity_id":{"type":"integer","format":"int64"},"entity_kind":{"type":"string","description":"The record's model kind (EventParticipant, ExternalContact, Donation, …)."},"full_name":{"type":"string","nullable":true},"email":{"type":"string","nullable":true},"event_handle":{"type":"string","nullable":true},"event_name":{"type":"string","nullable":true},"tags":{"type":"array","items":{"type":"string"}},"has_notes":{"type":"boolean"}}}}}}
```

## The CrmEntitySearchResult object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"CrmEntitySearchResult":{"type":"object","required":["entities"],"properties":{"entities":{"type":"array","items":{"$ref":"#/components/schemas/CrmEntitySummary"}}}},"CrmEntitySummary":{"type":"object","description":"A single CRM record returned by search.","required":["crm_entity_id","entity_kind","full_name","email","event_handle","event_name","tags","has_notes"],"properties":{"crm_entity_id":{"type":"integer","format":"int64"},"entity_kind":{"type":"string","description":"The record's model kind (EventParticipant, ExternalContact, Donation, …)."},"full_name":{"type":"string","nullable":true},"email":{"type":"string","nullable":true},"event_handle":{"type":"string","nullable":true},"event_name":{"type":"string","nullable":true},"tags":{"type":"array","items":{"type":"string"}},"has_notes":{"type":"boolean"}}}}}}
```

## The CrmCountResult object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"CrmCountResult":{"type":"object","required":["count"],"properties":{"count":{"type":"integer","description":"Number of records matching the filters."}}}}}}
```

## The CrmEntityDetailResult object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"CrmEntityDetailResult":{"type":"object","required":["entity"],"properties":{"entity":{"type":"object","description":"The record's current fields. `entity_kind` and `crm_entity_id` are\nalways present; every other key is included only when it applies to\nthe record's kind and has a value, so the key set varies by kind.\n","required":["entity_kind","crm_entity_id"],"properties":{"entity_kind":{"type":"string"},"crm_entity_id":{"type":"integer","format":"int64"},"custom_answers":{"type":"object","description":"Registration-question answers, keyed by question title.","additionalProperties":{"type":"string"}}},"additionalProperties":true}}}}}}
```

## The CrmNote object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"CrmNote":{"type":"object","required":["id","body","note_type","author_name","created_at"],"properties":{"id":{"type":"integer","format":"int64"},"body":{"type":"string"},"note_type":{"type":"string","enum":["general","refund"]},"author_name":{"type":"string","nullable":true},"created_at":{"type":"string","format":"date-time","nullable":true}}}}}}
```

## The CrmNoteListResult object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"CrmNoteListResult":{"type":"object","required":["notes"],"properties":{"notes":{"type":"array","items":{"$ref":"#/components/schemas/CrmNote"}}}},"CrmNote":{"type":"object","required":["id","body","note_type","author_name","created_at"],"properties":{"id":{"type":"integer","format":"int64"},"body":{"type":"string"},"note_type":{"type":"string","enum":["general","refund"]},"author_name":{"type":"string","nullable":true},"created_at":{"type":"string","format":"date-time","nullable":true}}}}}}
```

## The CrmNoteResult object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"CrmNoteResult":{"type":"object","required":["note"],"properties":{"note":{"$ref":"#/components/schemas/CrmNote"}}},"CrmNote":{"type":"object","required":["id","body","note_type","author_name","created_at"],"properties":{"id":{"type":"integer","format":"int64"},"body":{"type":"string"},"note_type":{"type":"string","enum":["general","refund"]},"author_name":{"type":"string","nullable":true},"created_at":{"type":"string","format":"date-time","nullable":true}}}}}}
```

## The CreateCrmNoteRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"CreateCrmNoteRequest":{"type":"object","required":["body"],"properties":{"body":{"type":"string","description":"The note text (internal, team-only)."}}}}}}
```

## The CrmTimelineEntry object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"CrmTimelineEntry":{"type":"object","required":["occurred_at","action","actor","details"],"properties":{"occurred_at":{"type":"string","format":"date-time"},"action":{"type":"string","description":"What happened, e.g. \"registered\", \"edited 2 fields\", \"transferred bib\", \"opened\"."},"actor":{"type":"string","nullable":true,"description":"Who made the change (\"System\" for automated changes)."},"details":{"type":"array","description":"Field-level detail lines, e.g. \"Email: old@x.com → new@x.com\".","items":{"type":"string"}}}}}}}
```

## The CrmTimelineEntity object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"CrmTimelineEntity":{"type":"object","description":"The record a timeline (or timeline entry) belongs to.","required":["crm_entity_id","entity_kind","full_name","event_name"],"properties":{"crm_entity_id":{"type":"integer","format":"int64"},"entity_kind":{"type":"string"},"full_name":{"type":"string","nullable":true},"event_name":{"type":"string","nullable":true}}}}}}
```

## The CrmMergedTimelineEntry object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"CrmMergedTimelineEntry":{"description":"A CrmTimelineEntry tagged with the record it came from, for merged feeds.","allOf":[{"$ref":"#/components/schemas/CrmTimelineEntry"},{"type":"object","required":["crm_entity_id","event_name"],"properties":{"crm_entity_id":{"type":"integer","format":"int64","description":"The record this entry belongs to."},"event_name":{"type":"string","nullable":true,"description":"The event of the record this entry belongs to."}}}]},"CrmTimelineEntry":{"type":"object","required":["occurred_at","action","actor","details"],"properties":{"occurred_at":{"type":"string","format":"date-time"},"action":{"type":"string","description":"What happened, e.g. \"registered\", \"edited 2 fields\", \"transferred bib\", \"opened\"."},"actor":{"type":"string","nullable":true,"description":"Who made the change (\"System\" for automated changes)."},"details":{"type":"array","description":"Field-level detail lines, e.g. \"Email: old@x.com → new@x.com\".","items":{"type":"string"}}}}}}}
```

## The CrmMergedTimelineResult object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"CrmMergedTimelineResult":{"type":"object","required":["entities","timeline","has_more","unavailable_crm_entity_ids"],"properties":{"entities":{"type":"array","description":"The records whose timelines were merged (the ids the caller could access).","items":{"$ref":"#/components/schemas/CrmTimelineEntity"}},"timeline":{"type":"array","items":{"$ref":"#/components/schemas/CrmMergedTimelineEntry"}},"has_more":{"type":"boolean","description":"True when older entries were trimmed past the global cap."},"unavailable_crm_entity_ids":{"type":"array","description":"Requested ids that were not found or not permitted, and so excluded.","items":{"type":"integer","format":"int64"}}}},"CrmTimelineEntity":{"type":"object","description":"The record a timeline (or timeline entry) belongs to.","required":["crm_entity_id","entity_kind","full_name","event_name"],"properties":{"crm_entity_id":{"type":"integer","format":"int64"},"entity_kind":{"type":"string"},"full_name":{"type":"string","nullable":true},"event_name":{"type":"string","nullable":true}}},"CrmMergedTimelineEntry":{"description":"A CrmTimelineEntry tagged with the record it came from, for merged feeds.","allOf":[{"$ref":"#/components/schemas/CrmTimelineEntry"},{"type":"object","required":["crm_entity_id","event_name"],"properties":{"crm_entity_id":{"type":"integer","format":"int64","description":"The record this entry belongs to."},"event_name":{"type":"string","nullable":true,"description":"The event of the record this entry belongs to."}}}]},"CrmTimelineEntry":{"type":"object","required":["occurred_at","action","actor","details"],"properties":{"occurred_at":{"type":"string","format":"date-time"},"action":{"type":"string","description":"What happened, e.g. \"registered\", \"edited 2 fields\", \"transferred bib\", \"opened\"."},"actor":{"type":"string","nullable":true,"description":"Who made the change (\"System\" for automated changes)."},"details":{"type":"array","description":"Field-level detail lines, e.g. \"Email: old@x.com → new@x.com\".","items":{"type":"string"}}}}}}}
```

## The CrmColumn object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"CrmColumn":{"type":"object","required":["key","label"],"properties":{"key":{"type":"string","description":"The column key used in a mode's column list."},"label":{"type":"string","description":"Human-facing column label."}}}}}}
```

## The CrmColumnCatalog object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"CrmColumnCatalog":{"type":"object","required":["columns","default_columns","record_types"],"properties":{"columns":{"type":"array","items":{"$ref":"#/components/schemas/CrmColumn"}},"default_columns":{"type":"array","description":"The standard starting column keys for a new mode.","items":{"type":"string"}},"record_types":{"type":"array","description":"The record types a mode can be scoped to (humanized).","items":{"type":"string"}}}},"CrmColumn":{"type":"object","required":["key","label"],"properties":{"key":{"type":"string","description":"The column key used in a mode's column list."},"label":{"type":"string","description":"Human-facing column label."}}}}}}
```

## The CrmMode object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"CrmMode":{"type":"object","required":["id","key","name","template","custom","hidden","columns","record_types"],"properties":{"id":{"type":"integer","format":"int64","nullable":true,"description":"The saved-mode id; null for built-in template modes."},"key":{"type":"string"},"name":{"type":"string"},"template":{"type":"string"},"custom":{"type":"boolean","description":"Whether this is a user-created mode (the ones this surface can update/delete)."},"hidden":{"type":"boolean"},"columns":{"type":"array","description":"Ordered column keys shown by the mode.","items":{"type":"string"}},"record_types":{"type":"array","items":{"type":"string"}}}}}}}
```

## The CrmModeListResult object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"CrmModeListResult":{"type":"object","required":["modes"],"properties":{"modes":{"type":"array","items":{"$ref":"#/components/schemas/CrmMode"}}}},"CrmMode":{"type":"object","required":["id","key","name","template","custom","hidden","columns","record_types"],"properties":{"id":{"type":"integer","format":"int64","nullable":true,"description":"The saved-mode id; null for built-in template modes."},"key":{"type":"string"},"name":{"type":"string"},"template":{"type":"string"},"custom":{"type":"boolean","description":"Whether this is a user-created mode (the ones this surface can update/delete)."},"hidden":{"type":"boolean"},"columns":{"type":"array","description":"Ordered column keys shown by the mode.","items":{"type":"string"}},"record_types":{"type":"array","items":{"type":"string"}}}}}}}
```

## The CrmModeResult object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"CrmModeResult":{"type":"object","required":["mode"],"properties":{"mode":{"$ref":"#/components/schemas/CrmMode"}}},"CrmMode":{"type":"object","required":["id","key","name","template","custom","hidden","columns","record_types"],"properties":{"id":{"type":"integer","format":"int64","nullable":true,"description":"The saved-mode id; null for built-in template modes."},"key":{"type":"string"},"name":{"type":"string"},"template":{"type":"string"},"custom":{"type":"boolean","description":"Whether this is a user-created mode (the ones this surface can update/delete)."},"hidden":{"type":"boolean"},"columns":{"type":"array","description":"Ordered column keys shown by the mode.","items":{"type":"string"}},"record_types":{"type":"array","items":{"type":"string"}}}}}}}
```

## The SetCrmModeVisibilityRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"SetCrmModeVisibilityRequest":{"type":"object","required":["mode_key","hidden"],"properties":{"mode_key":{"type":"string","description":"The mode's key (a built-in key or a custom \"saved_<id>\")."},"hidden":{"type":"boolean","description":"true to hide the tab, false to show it."}}}}}}
```

## The CreateCrmModeRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"CreateCrmModeRequest":{"type":"object","required":["name","columns"],"properties":{"name":{"type":"string","description":"Organizer-facing name (unique among the caller's modes)."},"columns":{"type":"array","description":"Ordered column keys to show (from the columns catalog).","items":{"type":"string"}},"record_types":{"type":"array","description":"Record types to scope to; omit or empty for all records.","items":{"type":"string"}}}}}}}
```

## The UpdateCrmModeRequest object

```json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"components":{"schemas":{"UpdateCrmModeRequest":{"type":"object","description":"Only the fields sent are changed.","properties":{"name":{"type":"string"},"columns":{"type":"array","description":"Full ordered column keys; REPLACES the mode's columns.","items":{"type":"string"}},"record_types":{"type":"array","description":"New record-type scope; [] for all records.","items":{"type":"string"}}}}}}}
```
