# Finishers

Manage finishers (individual finish records) for an event result.

## List finishers

> Returns all finishers for an event result with their split efforts,\
> ordered by creation date (newest first).<br>

````json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"tags":[{"name":"Finishers","description":"Manage finishers (individual finish records) for an event result."}],"servers":[{"url":"https://www.movemint.cc","description":"Production"}],"security":[{"bearerAuth":[]},{"oauth2":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Pass the access token in the `Authorization` header:\n```\nAuthorization: Bearer YOUR_ACCESS_TOKEN\n```\n"},"oauth2":{"type":"oauth2","description":"OAuth 2.0 authentication using the Authorization Code or Client\nCredentials grant flow.\n","flows":{"authorizationCode":{"authorizationUrl":"https://www.movemint.cc/oauth/authorize","tokenUrl":"https://www.movemint.cc/oauth/token","refreshUrl":"https://www.movemint.cc/oauth/token","scopes":{}},"clientCredentials":{"tokenUrl":"https://www.movemint.cc/oauth/token","scopes":{}}}}},"parameters":{"EventHandle":{"name":"handle","in":"path","required":true,"description":"The unique handle (slug) of the event","schema":{"type":"string"}},"EventResultId":{"name":"event_result_id","in":"path","required":true,"description":"The ID of the event result","schema":{"type":"integer","format":"int64"}}},"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"}}},"OAuthError":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Machine-readable error code"},"error_description":{"type":"string","description":"Human-readable description of the error"}}},"Error":{"type":"object","description":"A generic error response","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message"}}}},"responses":{"Unauthorized":{"description":"Unauthorized - invalid or missing token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"Forbidden":{"description":"Forbidden - user is not an admin of this event","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"EventOrResultNotFound":{"description":"Event or event result not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/api/v1/events/{handle}/event_results/{event_result_id}/finishers":{"get":{"tags":["Finishers"],"summary":"List finishers","description":"Returns all finishers for an event result with their split efforts,\nordered by creation date (newest first).\n","operationId":"listFinishers","parameters":[{"$ref":"#/components/parameters/EventHandle"},{"$ref":"#/components/parameters/EventResultId"}],"responses":{"200":{"description":"List of finishers","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Finisher"}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/EventOrResultNotFound"}}}}}}
````

## Create a finisher

> Add a finisher to an event result with their split efforts.\
> \
> \*\*Participant linking:\*\* If \`movemint\_confirmation\_number\` is provided,\
> the finisher is linked to the matching event participant and their\
> metadata (name, gender, DOB, address, etc.) is used to fill in any\
> fields not explicitly provided. If no confirmation number is given\
> but a \`bib\` is provided, the system attempts to match by bib number\
> (only when exactly one participant has that bib).\
> \
> \*\*For \`irl\` results:\*\* divisions are automatically computed from the\
> finisher's gender and age. The \`divisions\` field is ignored.\
> \
> \*\*For \`irl\_custom\_divisions\` results:\*\* pass custom division names in\
> the \`divisions\` array. The finisher is also automatically added to\
> their overall gender division.\
> \
> The \`gender\` field accepts either a string (\`"male"\`, \`"female"\`,\
> \`"nonbinary"\`, \`"m"\`, \`"f"\`) or an integer gender identity value\
> (\`0\` = Male, \`1\` = Female, \`2\` = Nonbinary).<br>

````json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"tags":[{"name":"Finishers","description":"Manage finishers (individual finish records) for an event result."}],"servers":[{"url":"https://www.movemint.cc","description":"Production"}],"security":[{"bearerAuth":[]},{"oauth2":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Pass the access token in the `Authorization` header:\n```\nAuthorization: Bearer YOUR_ACCESS_TOKEN\n```\n"},"oauth2":{"type":"oauth2","description":"OAuth 2.0 authentication using the Authorization Code or Client\nCredentials grant flow.\n","flows":{"authorizationCode":{"authorizationUrl":"https://www.movemint.cc/oauth/authorize","tokenUrl":"https://www.movemint.cc/oauth/token","refreshUrl":"https://www.movemint.cc/oauth/token","scopes":{}},"clientCredentials":{"tokenUrl":"https://www.movemint.cc/oauth/token","scopes":{}}}}},"parameters":{"EventHandle":{"name":"handle","in":"path","required":true,"description":"The unique handle (slug) of the event","schema":{"type":"string"}},"EventResultId":{"name":"event_result_id","in":"path","required":true,"description":"The ID of the event result","schema":{"type":"integer","format":"int64"}}},"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"}}}}}},"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"}}},"OAuthError":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Machine-readable error code"},"error_description":{"type":"string","description":"Human-readable description of the error"}}},"Error":{"type":"object","description":"A generic error response","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message"}}},"ValidationError":{"type":"object","description":"A validation error response with a list of error messages","required":["errors"],"properties":{"errors":{"type":"array","items":{"type":"string"},"description":"List of validation error messages"}}}},"responses":{"Unauthorized":{"description":"Unauthorized - invalid or missing token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"Forbidden":{"description":"Forbidden - user is not an admin of this event","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"EventOrResultNotFound":{"description":"Event or event result not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/api/v1/events/{handle}/event_results/{event_result_id}/finishers":{"post":{"tags":["Finishers"],"summary":"Create a finisher","description":"Add a finisher to an event result with their split efforts.\n\n**Participant linking:** If `movemint_confirmation_number` is provided,\nthe finisher is linked to the matching event participant and their\nmetadata (name, gender, DOB, address, etc.) is used to fill in any\nfields not explicitly provided. If no confirmation number is given\nbut a `bib` is provided, the system attempts to match by bib number\n(only when exactly one participant has that bib).\n\n**For `irl` results:** divisions are automatically computed from the\nfinisher's gender and age. The `divisions` field is ignored.\n\n**For `irl_custom_divisions` results:** pass custom division names in\nthe `divisions` array. The finisher is also automatically added to\ntheir overall gender division.\n\nThe `gender` field accepts either a string (`\"male\"`, `\"female\"`,\n`\"nonbinary\"`, `\"m\"`, `\"f\"`) or an integer gender identity value\n(`0` = Male, `1` = Female, `2` = Nonbinary).\n","operationId":"createFinisher","parameters":[{"$ref":"#/components/parameters/EventHandle"},{"$ref":"#/components/parameters/EventResultId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateFinisherRequest"}}}},"responses":{"201":{"description":"Finisher created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Finisher"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/EventOrResultNotFound"},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}}}}}}}
````

## Clear all finishers

> Remove all finishers and their split efforts from an event result.\
> This is useful when a timer needs to re-upload the entire results set.<br>

````json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"tags":[{"name":"Finishers","description":"Manage finishers (individual finish records) for an event result."}],"servers":[{"url":"https://www.movemint.cc","description":"Production"}],"security":[{"bearerAuth":[]},{"oauth2":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Pass the access token in the `Authorization` header:\n```\nAuthorization: Bearer YOUR_ACCESS_TOKEN\n```\n"},"oauth2":{"type":"oauth2","description":"OAuth 2.0 authentication using the Authorization Code or Client\nCredentials grant flow.\n","flows":{"authorizationCode":{"authorizationUrl":"https://www.movemint.cc/oauth/authorize","tokenUrl":"https://www.movemint.cc/oauth/token","refreshUrl":"https://www.movemint.cc/oauth/token","scopes":{}},"clientCredentials":{"tokenUrl":"https://www.movemint.cc/oauth/token","scopes":{}}}}},"parameters":{"EventHandle":{"name":"handle","in":"path","required":true,"description":"The unique handle (slug) of the event","schema":{"type":"string"}},"EventResultId":{"name":"event_result_id","in":"path","required":true,"description":"The ID of the event result","schema":{"type":"integer","format":"int64"}}},"responses":{"Unauthorized":{"description":"Unauthorized - invalid or missing token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"Forbidden":{"description":"Forbidden - user is not an admin of this event","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"EventOrResultNotFound":{"description":"Event or event result not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"OAuthError":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Machine-readable error code"},"error_description":{"type":"string","description":"Human-readable description of the error"}}},"Error":{"type":"object","description":"A generic error response","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message"}}}}},"paths":{"/api/v1/events/{handle}/event_results/{event_result_id}/finishers/clear":{"delete":{"tags":["Finishers"],"summary":"Clear all finishers","description":"Remove all finishers and their split efforts from an event result.\nThis is useful when a timer needs to re-upload the entire results set.\n","operationId":"clearFinishers","parameters":[{"$ref":"#/components/parameters/EventHandle"},{"$ref":"#/components/parameters/EventResultId"}],"responses":{"200":{"description":"All finishers cleared","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/EventOrResultNotFound"}}}}}}
````

## Get a finisher

> Returns a single finisher with their split efforts.<br>

````json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"tags":[{"name":"Finishers","description":"Manage finishers (individual finish records) for an event result."}],"servers":[{"url":"https://www.movemint.cc","description":"Production"}],"security":[{"bearerAuth":[]},{"oauth2":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Pass the access token in the `Authorization` header:\n```\nAuthorization: Bearer YOUR_ACCESS_TOKEN\n```\n"},"oauth2":{"type":"oauth2","description":"OAuth 2.0 authentication using the Authorization Code or Client\nCredentials grant flow.\n","flows":{"authorizationCode":{"authorizationUrl":"https://www.movemint.cc/oauth/authorize","tokenUrl":"https://www.movemint.cc/oauth/token","refreshUrl":"https://www.movemint.cc/oauth/token","scopes":{}},"clientCredentials":{"tokenUrl":"https://www.movemint.cc/oauth/token","scopes":{}}}}},"parameters":{"EventHandle":{"name":"handle","in":"path","required":true,"description":"The unique handle (slug) of the event","schema":{"type":"string"}},"EventResultId":{"name":"event_result_id","in":"path","required":true,"description":"The ID of the event result","schema":{"type":"integer","format":"int64"}},"ResourceId":{"name":"id","in":"path","required":true,"description":"The ID of the resource","schema":{"type":"integer","format":"int64"}}},"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"}}},"OAuthError":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Machine-readable error code"},"error_description":{"type":"string","description":"Human-readable description of the error"}}},"Error":{"type":"object","description":"A generic error response","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message"}}}},"responses":{"Unauthorized":{"description":"Unauthorized - invalid or missing token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"Forbidden":{"description":"Forbidden - user is not an admin of this event","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"FinisherNotFound":{"description":"Event, event result, or finisher not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/api/v1/events/{handle}/event_results/{event_result_id}/finishers/{id}":{"get":{"tags":["Finishers"],"summary":"Get a finisher","description":"Returns a single finisher with their split efforts.\n","operationId":"getFinisher","parameters":[{"$ref":"#/components/parameters/EventHandle"},{"$ref":"#/components/parameters/EventResultId"},{"$ref":"#/components/parameters/ResourceId"}],"responses":{"200":{"description":"Finisher details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Finisher"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/FinisherNotFound"}}}}}}
````

## Delete a finisher

> Permanently delete a finisher and all associated split efforts and\
> division split efforts.<br>

````json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"tags":[{"name":"Finishers","description":"Manage finishers (individual finish records) for an event result."}],"servers":[{"url":"https://www.movemint.cc","description":"Production"}],"security":[{"bearerAuth":[]},{"oauth2":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Pass the access token in the `Authorization` header:\n```\nAuthorization: Bearer YOUR_ACCESS_TOKEN\n```\n"},"oauth2":{"type":"oauth2","description":"OAuth 2.0 authentication using the Authorization Code or Client\nCredentials grant flow.\n","flows":{"authorizationCode":{"authorizationUrl":"https://www.movemint.cc/oauth/authorize","tokenUrl":"https://www.movemint.cc/oauth/token","refreshUrl":"https://www.movemint.cc/oauth/token","scopes":{}},"clientCredentials":{"tokenUrl":"https://www.movemint.cc/oauth/token","scopes":{}}}}},"parameters":{"EventHandle":{"name":"handle","in":"path","required":true,"description":"The unique handle (slug) of the event","schema":{"type":"string"}},"EventResultId":{"name":"event_result_id","in":"path","required":true,"description":"The ID of the event result","schema":{"type":"integer","format":"int64"}},"ResourceId":{"name":"id","in":"path","required":true,"description":"The ID of the resource","schema":{"type":"integer","format":"int64"}}},"responses":{"Unauthorized":{"description":"Unauthorized - invalid or missing token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"Forbidden":{"description":"Forbidden - user is not an admin of this event","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"FinisherNotFound":{"description":"Event, event result, or finisher not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"OAuthError":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Machine-readable error code"},"error_description":{"type":"string","description":"Human-readable description of the error"}}},"Error":{"type":"object","description":"A generic error response","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message"}}}}},"paths":{"/api/v1/events/{handle}/event_results/{event_result_id}/finishers/{id}":{"delete":{"tags":["Finishers"],"summary":"Delete a finisher","description":"Permanently delete a finisher and all associated split efforts and\ndivision split efforts.\n","operationId":"deleteFinisher","parameters":[{"$ref":"#/components/parameters/EventHandle"},{"$ref":"#/components/parameters/EventResultId"},{"$ref":"#/components/parameters/ResourceId"}],"responses":{"204":{"description":"Finisher deleted"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/FinisherNotFound"}}}}}}
````

## Update a finisher

> Update a finisher's details and/or replace their split efforts.\
> If \`split\_efforts\` is provided, all existing split efforts are\
> replaced with the new ones. If \`divisions\` is provided (for\
> \`irl\_custom\_divisions\` results), custom division assignments are\
> replaced.<br>

````json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"tags":[{"name":"Finishers","description":"Manage finishers (individual finish records) for an event result."}],"servers":[{"url":"https://www.movemint.cc","description":"Production"}],"security":[{"bearerAuth":[]},{"oauth2":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Pass the access token in the `Authorization` header:\n```\nAuthorization: Bearer YOUR_ACCESS_TOKEN\n```\n"},"oauth2":{"type":"oauth2","description":"OAuth 2.0 authentication using the Authorization Code or Client\nCredentials grant flow.\n","flows":{"authorizationCode":{"authorizationUrl":"https://www.movemint.cc/oauth/authorize","tokenUrl":"https://www.movemint.cc/oauth/token","refreshUrl":"https://www.movemint.cc/oauth/token","scopes":{}},"clientCredentials":{"tokenUrl":"https://www.movemint.cc/oauth/token","scopes":{}}}}},"parameters":{"EventHandle":{"name":"handle","in":"path","required":true,"description":"The unique handle (slug) of the event","schema":{"type":"string"}},"EventResultId":{"name":"event_result_id","in":"path","required":true,"description":"The ID of the event result","schema":{"type":"integer","format":"int64"}},"ResourceId":{"name":"id","in":"path","required":true,"description":"The ID of the resource","schema":{"type":"integer","format":"int64"}}},"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"}}}}}},"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"}}},"OAuthError":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Machine-readable error code"},"error_description":{"type":"string","description":"Human-readable description of the error"}}},"Error":{"type":"object","description":"A generic error response","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message"}}},"ValidationError":{"type":"object","description":"A validation error response with a list of error messages","required":["errors"],"properties":{"errors":{"type":"array","items":{"type":"string"},"description":"List of validation error messages"}}}},"responses":{"Unauthorized":{"description":"Unauthorized - invalid or missing token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"Forbidden":{"description":"Forbidden - user is not an admin of this event","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"FinisherNotFound":{"description":"Event, event result, or finisher not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/api/v1/events/{handle}/event_results/{event_result_id}/finishers/{id}":{"patch":{"tags":["Finishers"],"summary":"Update a finisher","description":"Update a finisher's details and/or replace their split efforts.\nIf `split_efforts` is provided, all existing split efforts are\nreplaced with the new ones. If `divisions` is provided (for\n`irl_custom_divisions` results), custom division assignments are\nreplaced.\n","operationId":"updateFinisher","parameters":[{"$ref":"#/components/parameters/EventHandle"},{"$ref":"#/components/parameters/EventResultId"},{"$ref":"#/components/parameters/ResourceId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateFinisherRequest"}}}},"responses":{"200":{"description":"Finisher updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Finisher"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/FinisherNotFound"},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}}}}}}}
````
