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

# Course Maps

Attach Strava and Ride with GPS routes to an event as course maps. OAuth-gated: callers without a current Strava / RWG token receive a structured `oauth_required` error with a `connect_url`.

## GET /api/v1/events/{handle}/course\_maps

> List course maps attached to the event

````json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"tags":[{"name":"Course Maps","description":"Attach Strava and Ride with GPS routes to an event as course maps.\nOAuth-gated: callers without a current Strava / RWG token receive a\nstructured `oauth_required` error with a `connect_url`.\n"}],"servers":[{"url":"https://www.movemint.cc","description":"Production"}],"security":[{"bearerAuth":[]},{"oauth2":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Pass the access token in the `Authorization` header:\n```\nAuthorization: Bearer YOUR_ACCESS_TOKEN\n```\n"},"oauth2":{"type":"oauth2","description":"OAuth 2.0 authentication using the Authorization Code or Client\nCredentials grant flow.\n","flows":{"authorizationCode":{"authorizationUrl":"https://www.movemint.cc/oauth/authorize","tokenUrl":"https://www.movemint.cc/oauth/token","refreshUrl":"https://www.movemint.cc/oauth/token","scopes":{}},"clientCredentials":{"tokenUrl":"https://www.movemint.cc/oauth/token","scopes":{}}}}},"parameters":{"EventHandle":{"name":"handle","in":"path","required":true,"description":"The unique handle (slug) of the event","schema":{"type":"string"}}},"schemas":{"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}}},"OAuthError":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Machine-readable error code"},"error_description":{"type":"string","description":"Human-readable description of the error"}}},"Error":{"type":"object","description":"A generic error response","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message"}}}},"responses":{"Unauthorized":{"description":"Unauthorized - invalid or missing token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"Forbidden":{"description":"Forbidden - user is not an admin of this event","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"EventNotFound":{"description":"Event not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/api/v1/events/{handle}/course_maps":{"get":{"tags":["Course Maps"],"summary":"List course maps attached to the event","operationId":"listCourseMaps","parameters":[{"$ref":"#/components/parameters/EventHandle"}],"responses":{"200":{"description":"Course maps","content":{"application/json":{"schema":{"type":"object","required":["course_maps"],"properties":{"course_maps":{"type":"array","items":{"$ref":"#/components/schemas/CourseMap"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/EventNotFound"}}}}}}
````

## Attach a course map from Strava or Ride with GPS

> Attaches an existing route owned by the organizer's connected\
> Strava or RWG account. OAuth-gated; returns 422 \`oauth\_required\`\
> with a \`connect\_url\` if the corresponding integration isn't\
> connected. Strava routes additionally require the \`read\_all\`\
> scope; insufficient scope is surfaced as 422 \`insufficient\_scope\`.<br>

````json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"tags":[{"name":"Course Maps","description":"Attach Strava and Ride with GPS routes to an event as course maps.\nOAuth-gated: callers without a current Strava / RWG token receive a\nstructured `oauth_required` error with a `connect_url`.\n"}],"servers":[{"url":"https://www.movemint.cc","description":"Production"}],"security":[{"bearerAuth":[]},{"oauth2":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Pass the access token in the `Authorization` header:\n```\nAuthorization: Bearer YOUR_ACCESS_TOKEN\n```\n"},"oauth2":{"type":"oauth2","description":"OAuth 2.0 authentication using the Authorization Code or Client\nCredentials grant flow.\n","flows":{"authorizationCode":{"authorizationUrl":"https://www.movemint.cc/oauth/authorize","tokenUrl":"https://www.movemint.cc/oauth/token","refreshUrl":"https://www.movemint.cc/oauth/token","scopes":{}},"clientCredentials":{"tokenUrl":"https://www.movemint.cc/oauth/token","scopes":{}}}}},"parameters":{"EventHandle":{"name":"handle","in":"path","required":true,"description":"The unique handle (slug) of the event","schema":{"type":"string"}}},"schemas":{"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"}}},"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}}},"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"}}},"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"}}}},"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"}}}}}},"paths":{"/api/v1/events/{handle}/course_maps":{"post":{"tags":["Course Maps"],"summary":"Attach a course map from Strava or Ride with GPS","description":"Attaches an existing route owned by the organizer's connected\nStrava or RWG account. OAuth-gated; returns 422 `oauth_required`\nwith a `connect_url` if the corresponding integration isn't\nconnected. Strava routes additionally require the `read_all`\nscope; insufficient scope is surfaced as 422 `insufficient_scope`.\n","operationId":"createCourseMap","parameters":[{"$ref":"#/components/parameters/EventHandle"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCourseMapRequest"}}}},"responses":{"201":{"description":"Attached","content":{"application/json":{"schema":{"type":"object","required":["course_map"],"properties":{"course_map":{"$ref":"#/components/schemas/CourseMap"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Route not found in the athlete's account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"OAuth required, insufficient scope, or validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CourseMapOAuthError"}}}}}}}}}
````

## DELETE /api/v1/events/{handle}/course\_maps/{id}

> Detach a course map from the event

````json
{"openapi":"3.1.0","info":{"title":"Movemint API","version":"1.0"},"tags":[{"name":"Course Maps","description":"Attach Strava and Ride with GPS routes to an event as course maps.\nOAuth-gated: callers without a current Strava / RWG token receive a\nstructured `oauth_required` error with a `connect_url`.\n"}],"servers":[{"url":"https://www.movemint.cc","description":"Production"}],"security":[{"bearerAuth":[]},{"oauth2":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Pass the access token in the `Authorization` header:\n```\nAuthorization: Bearer YOUR_ACCESS_TOKEN\n```\n"},"oauth2":{"type":"oauth2","description":"OAuth 2.0 authentication using the Authorization Code or Client\nCredentials grant flow.\n","flows":{"authorizationCode":{"authorizationUrl":"https://www.movemint.cc/oauth/authorize","tokenUrl":"https://www.movemint.cc/oauth/token","refreshUrl":"https://www.movemint.cc/oauth/token","scopes":{}},"clientCredentials":{"tokenUrl":"https://www.movemint.cc/oauth/token","scopes":{}}}}},"parameters":{"EventHandle":{"name":"handle","in":"path","required":true,"description":"The unique handle (slug) of the event","schema":{"type":"string"}},"ResourceId":{"name":"id","in":"path","required":true,"description":"The ID of the resource","schema":{"type":"integer","format":"int64"}}},"responses":{"Unauthorized":{"description":"Unauthorized - invalid or missing token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"Forbidden":{"description":"Forbidden - user is not an admin of this event","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"EventNotFound":{"description":"Event not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"OAuthError":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Machine-readable error code"},"error_description":{"type":"string","description":"Human-readable description of the error"}}},"Error":{"type":"object","description":"A generic error response","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message"}}}}},"paths":{"/api/v1/events/{handle}/course_maps/{id}":{"delete":{"tags":["Course Maps"],"summary":"Detach a course map from the event","operationId":"deleteCourseMap","parameters":[{"$ref":"#/components/parameters/EventHandle"},{"$ref":"#/components/parameters/ResourceId"}],"responses":{"200":{"description":"Detached","content":{"application/json":{"schema":{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","enum":[true]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/EventNotFound"}}}}}}
````
