Skip to main content

Overview

Edits a route and answers it back. Every field is optional and an omitted field is unchanged; send null to clear start_time, end_time, max_rsvps or theme. Hosts only: the creator or a co-host.

Authentication

A Login with Cyclemate access token, or a signed-in rider’s session token. Every route belongs to a rider: your app acts for the rider who connected it, and the route is theirs. Your app reaches only the routes it created: a route the rider made in our apps, or through another app, answers 404.
An API key on its own is rejected, as are anonymous requests. To create routes as your organisation, sign up for a Cyclemate account and connect your app to it with Login with Cyclemate.

Rate limits

Riders and apps acting for them may make 60 requests a minute; a request that routes between stops counts once per hop. Every rider may create 10 routes in any 24 hours, counted across our apps and every connected app: the eleventh answers 429 with code: "daily_limit" and the seconds until a slot frees.

Path parameters

string
required
The route’s id.

Request body

string
1 to 120 characters.
string
Up to 4,000 characters.
string
default:"🚴"
One emoji.
string
The link slug: 3 to 60 lowercase letters, digits and hyphens. Route and product names are reserved. Generated from the name when omitted. A taken alias answers 409.
string
default:"public"
public, unlisted (anyone with the link) or private (hosts only).
string
default:"dynamic"
dynamic or fixed. A dynamic route is re-planned between its stops as roads change, so it has no hidden shaping points; geometry and a hidden leg require fixed.
object
The page theme. Keys: headerFont, headerFlair, headerColor (#rrggbb), headerLayout, backgroundColor, backgroundTexture, animation, stickers (up to 12 of { id, position: { x, y } }). Every value must be one the app offers; an unknown one answers 400 naming it.
string[]
Up to 10 category slugs, for example coffee, park, live-music.
string
ISO 8601. Setting it makes the route a group ride. end_time (after it; derived from the route’s duration when omitted), max_rsvps (0 to 1000) and rsvp_questions are accepted only with a start time.
array
Up to 20 of { prompt, required, type?, options? }; type is text or choice, and a choice question lists options as { label, limit? }. Ids are generated when omitted and must be sent back unchanged on edit.
boolean
default:"true"
With show_safety_colors, show_why_this_route and show_street_by_street: which sections the route’s page shows.
array
2 to 25 stops as { location: [longitude, latitude], name? }, all in one city. We plan the safest cycling route between them, one leg per hop, and name each stop as given.
array
Your own line, 1 to 24 legs of { geometry, end_name?, hidden? }. geometry is a GeoJSON LineString; each leg starts within 25 m of the previous leg’s end. The whole route is at most 10,000 coordinates and 200 km and must start and end in the same city. hidden: true marks a shaping point that is not shown as a stop (fixed routes only). Pass start_name for the start.
object
A single GeoJSON LineString, the same as one leg. Fixed routes only. start_name and end_name name its ends.
string
With legs or geometry.
string
With geometry.
string
The id of one of the route’s images, to make it the cover.

Response body

string
The route’s id, a UUID string. Pass it as event_id to POST /multi-modal/v2/ to ride it.
string
The route’s link slug, chosen or generated from the name.
string
The route’s page on cyclemate.club.
string
string
string
string
public, unlisted or private.
string
dynamic (we re-plan the line between the stops as roads change) or fixed (the line is kept as given).
object
The page theme, when one is set. The same object you send.
array
Each { slug, name, emoji }.
string
Present on a group ride, with end_time, and max_rsvps and rsvp_questions when set.
boolean
With show_safety_colors, show_why_this_route and show_street_by_street: which sections the page shows.
string
The city the route is in: london, new_york_city, los_angeles or bay_area.
object
The rider who created the route: { name, slug, image_url }. null once that rider has deleted their account.
object
distance_m, duration_s, polyline (precision 5), geometry (a GeoJSON LineString; omitted in lists) and stops: the start then every stop in order, each { name, location }, with hidden: true on a shaping point that is not shown as a stop.
string
pending while we match the line to the road network (a fixed route) or plan it between the stops (a dynamic route), ready once turn-by-turn steps and the safety summary are stored, unavailable when the line could not be matched or no route exists between the stops. A pending route is already viewable and rideable; poll every few seconds.
array
Each { id, url, status, cover }. status is pending until our image check has run, then approved. Hosts see every image with its status; everyone else sees approved images only.
string
string

Variants

Replacing the line

Send stops, legs or geometry to replace the whole route. Its plan is dropped and rebuilt, so route_status returns to pending.

Changing the mode

Switching a fixed route to dynamic keeps its stops but drops any hidden shaping points, since a dynamic route is planned through its stops only. Switching to fixed keeps the current line.

Making a route a group ride

Send start_time to turn a route into a group ride; send start_time: null to turn a group ride back into a route, which also clears max_rsvps and rsvp_questions.

Error responses

Every error body is { "error", "code" }; error is a sentence, code is stable.

400 Bad request

Invalid body or query: the message names the field. code is invalid_body, or for a route input outside_coverage (the route starts outside the cities we cover), cross_city (its stops span two cities) or no_route (no cycling route exists between two stops).

401 Unauthorized

Missing or invalid credentials, or an anonymous caller.

404 Not found

No route with that id that you may see. A private route you do not host, a route you may read but not edit, and a route your app did not create all answer 404, never 403.

405 Method not allowed

409 Conflict

The alias you chose is already taken, by another route or by a rider’s profile link.

429 Too many requests

The burst limit, with a Retry-After header; or the daily creation cap, which adds code: "daily_limit".

500 Internal server error