# create_route

Add a route (how to get there).

`POST /v1/guides/{productId}/routes` · MCP tool `create_route` · scope `write` · stable · since 2026-09-17

Planning facts the creator vouches for: route type, grade and its scale, effort, duration, gain, distance, trailhead, transit per mode, equipment ([] means explicitly none), sources (where the numbers come from) and the line from the creator's GPX or KML. Link spots with set_route_spots afterwards.

## Path parameters

- `productId` (string, required): Id of the guide (a product of type map). From list_guides or create_guide.

## Body parameters

- `activity` (string, optional): hike, walk, bike, drive, ski or paddle. A route without one is a hike; empty string clears.
- `ascentMin` (number or null, optional): Minutes up, when the source gives up and down separately. null clears.
- `descentM` (number, optional): Descent in meters, 0 or more. Never derived from gainM: give it when the source does.
- `descentMin` (number or null, optional): Minutes down. null clears.
- `description` (string, optional): The route in the creator's words, shown on the route card. Empty string clears.
- `distanceKm` (number, optional): Distance in kilometers, 0 or more.
- `durationBasis` (string or null, optional): What durationMin counts: round_trip (the default), one_way or ascent. null clears. One of `round_trip`, `one_way`, `ascent`.
- `durationMin` (number, optional): Duration in minutes, 0 or more; durationBasis says what it counts (round trip unless set).
- `effortLabel` (string, optional): Easy, Moderate, Hard (free text). Empty string clears.
- `equipment` (array of strings, optional): Gear, at most 50 items; [] means explicitly no special gear (shown as None), absent means unknown.
- `extraProps` (array of ExtraProp, optional): Free label and value rows shown on the card, full replacement ([] clears), at most 24: [{ label (at most 60 characters), value (at most 500) }]. A row with both sides empty is dropped, a half-empty one refused.
  Fields of ExtraProp: https://developers.sceniq.earth/fields/extra-prop.md
- `factsCheckedOn` (string, optional): The day the facts were last checked against their sources (YYYY-MM-DD). Empty string clears.
- `figureSources` (array of FigureSource, optional): Where each number comes from, full replacement: [{ field: durationMin|distanceKm|gainM|descentM|sacGrade, kind: sourced|computed, url?, note? }].
  Fields of FigureSource: https://developers.sceniq.earth/fields/figure-source.md
- `gainM` (number, optional): Elevation gain in meters, 0 or more.
- `gradeScale` (string, optional): sac, via_ferrata, cai, yds, mtb, whitewater or other. A route without one uses sac; empty string clears.
- `name` (string, optional): Route name, e.g. Fairy Falls trail or Oeschinensee loop. Without one the apps show Hike from <start> (Drive from, Bike ride from ... by activity), or Route N when there is no start either. Empty string clears.
- `reviewBy` (string, optional): The day the facts need a new check (YYYY-MM-DD), e.g. when a season, fare or timetable runs out. get_guide_readiness and get_publish_status warn once it has passed. Empty string clears.
- `reviewNotes` (string, optional): Notes for the creator's review (why a value was chosen, what could not be verified). Never shown to buyers; get_guide_readiness lists them. Empty string clears.
- `sacGrade` (string, optional): The grade as written in gradeScale, e.g. T2 (SAC), EE (CAI), Class 3 (US), S2 (mountain bike). Empty string clears.
- `season` (RouteSeason or null, optional): When the route can be walked, null clears: { months? [1-12], closureNote? (stairs chained November to April), statusUrl? }. Buyers opening it out of season see the closure.
  Fields of RouteSeason: https://developers.sceniq.earth/fields/route-season.md
- `segments` (array of RouteSegment, optional): Sections with their own access (free to Scout Lookout, permit for the chains): [{ name, km?, accessNote? }].
  Fields of RouteSegment: https://developers.sceniq.earth/fields/route-segment.md
- `shape` (string or null, optional): loop, out_and_back or one_way. null clears. One of `loop`, `out_and_back`, `one_way`.
- `sourceGrade` (string, optional): The source's own grade (Easy on the park page) next to your effortLabel. Empty string clears.
- `sources` (array of strings, optional): Where the facts come from, full replacement ([] clears), at most 25 entries: links to official trail pages or plain text (the creator's GPX). Buyers see them under Sources, links by their host.
- `stages` (array of RouteStage, optional): Days or legs of a trek, full replacement: [{ name, km?, min?, gainM?, note? }].
  Fields of RouteStage: https://developers.sceniq.earth/fields/route-stage.md
- `start` (string, optional): Trailhead or starting point in words. Empty string clears.
- `startMapsUrl` (string, optional): Map link to the trailhead: https on Google Maps, Apple Maps, Swisstopo, OpenStreetMap or SchweizMobil, or a geo: URI. Empty string clears.
- `status` (StatusNotice or null, optional): Closure or works notice, null clears: { state: open|partly_closed|closed|reopening, note?, since?, until? (the day the state is expected to end; buyers stop seeing the notice after it), sourceUrl?, checkedOn? }. reopening with until means reopens on that day.
  Fields of StatusNotice: https://developers.sceniq.earth/fields/status-notice.md
- `track` (RouteTrack, optional): The route line from the creator's GPX or KML: { coordinates: [[lon, lat] or [lon, lat, ele]], source: gpx|kml, fileName }. 2 to 1,000 points; simplify long recordings first.
  Fields of RouteTrack: https://developers.sceniq.earth/fields/route-track.md
- `transit` (array of TransitNote, optional): Transit notes shown under Transit on the route card, full replacement ([] clears), at most 20: [{ mode: train|bus|cable_car|car|boat|ferry|plane, note }]. Rows with an empty note are dropped.
  Fields of TransitNote: https://developers.sceniq.earth/fields/transit-note.md
- `variants` (array of RouteVariant, optional): Alternatives, full replacement: [{ name, start?, extraKm?, extraMin?, purpose? }].
  Fields of RouteVariant: https://developers.sceniq.earth/fields/route-variant.md

## Returns

201: RouteWrite.

- `routeId` (string, required): The route's id.
- `name` (string or null, required): The route's name.
- `activity` (string or null, required): hike, walk, bike, drive, ski or paddle; null means hike.
- `sacGrade` (string or null, required): The grade as written in gradeScale.
- `gradeScale` (string or null, required): sac, via_ferrata, cai, yds, mtb, whitewater or other; null means sac.
- `effortLabel` (string or null, required): Easy, Moderate, Hard (free text).
- `durationMin` (number or null, required): Duration in minutes (see durationBasis).
- `gainM` (number or null, required): Elevation gain in meters.
- `descentM` (number or null, required): Descent in meters.
- `distanceKm` (number or null, required): Distance in kilometers.
- `start` (string or null, required): The trailhead in words.
- `startMapsUrl` (string or null, required): Map link to the trailhead.
- `transit` (array of TransitNote, required): Transit notes per mode.
  Fields of TransitNote: https://developers.sceniq.earth/fields/transit-note.md
- `description` (string or null, required): The route in the creator's words.
- `equipment` (array of strings or null, required): Gear; [] means explicitly none, null means unknown.
- `sources` (array of strings, required): Where the facts come from.
- `extraProps` (array of ExtraProp, required): Free label and value rows.
  Fields of ExtraProp: https://developers.sceniq.earth/fields/extra-prop.md
- `track` (RouteTrack or null, required): The route line.
  Fields of RouteTrack: https://developers.sceniq.earth/fields/route-track.md
- `status` (StatusNotice or null, required): A closure notice.
  Fields of StatusNotice: https://developers.sceniq.earth/fields/status-notice.md
- `season` (RouteSeason or null, required): When the route can be walked.
  Fields of RouteSeason: https://developers.sceniq.earth/fields/route-season.md
- `variants` (array of RouteVariant, required): Alternatives.
  Fields of RouteVariant: https://developers.sceniq.earth/fields/route-variant.md
- `stages` (array of RouteStage, required): Days or legs of a trek.
  Fields of RouteStage: https://developers.sceniq.earth/fields/route-stage.md
- `segments` (array of RouteSegment, required): Sections with their own access.
  Fields of RouteSegment: https://developers.sceniq.earth/fields/route-segment.md
- `shape` (string or null, required): loop, out_and_back or one_way. One of `loop`, `out_and_back`, `one_way`.
- `durationBasis` (string or null, required): What durationMin counts: round_trip, one_way or ascent. One of `round_trip`, `one_way`, `ascent`.
- `ascentMin` (number or null, required): Minutes up.
- `descentMin` (number or null, required): Minutes down.
- `sourceGrade` (string or null, required): The source's own grade.
- `figureSources` (array of FigureSource, required): Where each number comes from.
  Fields of FigureSource: https://developers.sceniq.earth/fields/figure-source.md
- `reviewNotes` (string or null, required): Notes for the creator's review, never shown to buyers.
- `factsCheckedOn` (string or null, required): The day the facts were last checked (YYYY-MM-DD).
- `reviewBy` (string or null, required): The day the facts need a new check (YYYY-MM-DD).
- `createdAt` (number, required): When the row was created (Unix time in milliseconds).
- `updatedAt` (number, required): When the row last changed (Unix time in milliseconds).
- `spots` (array of objects, required): The spots the route passes, in order.
  - `spotKey` (string, required): The spot's key.
  - `order` (number, required): Position on the route.
  - `quickest` (boolean, required): true when this is the fastest approach to the spot.
  - `role` (string, required): required: the way in. optional: a walk from the spot that never sets its Accessibility. One of `required`, `optional`.
- `facilities` (array of objects, required): The places the route uses, in order.
  - `facilityId` (string, required): The place's id.
  - `order` (number, required): Position on the route.
- `warnings` (array of strings, optional): Notes about things the write accepted but you should look at (a plain http link). Present only when there are any.

## Examples

### Add a hike with its grade, figures, season, sources and GPX line

```bash
curl -X POST "https://sceniq.earth/api/v1/guides/j5738kd1q9x2m7v4c6b8n0p3r5t1w9y2/routes" \
  -H "Authorization: Bearer $SCENIQ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Fairy Falls trail to the Grand Prismatic overlook",
  "activity": "hike",
  "sacGrade": "Class 1",
  "gradeScale": "yds",
  "sourceGrade": "Easy",
  "effortLabel": "Easy",
  "durationMin": 45,
  "durationBasis": "round_trip",
  "distanceKm": 2,
  "gainM": 35,
  "descentM": 35,
  "shape": "out_and_back",
  "start": "Fairy Falls trailhead on the Grand Loop Road, 1.6 km south of Midway Geyser Basin",
  "startMapsUrl": "https://maps.apple.com/?ll=44.5156,-110.8326&q=Fairy%20Falls%20Trailhead",
  "description": "A flat kilometer on the old Fountain Freight Road, then a short climb to a platform above Grand Prismatic Spring. Go mid morning on a warm day, once the steam has lifted.",
  "transit": [
    {
      "mode": "car",
      "note": "Park at the Fairy Falls trailhead lot, which fills by 09:30 in July and August. No public transport runs in the park."
    },
    {
      "mode": "plane",
      "note": "Yellowstone Airport (WYS) in West Yellowstone, 45 km by road, has flights from June to September."
    }
  ],
  "equipment": [
    "Bear spray",
    "A warm layer for the morning"
  ],
  "sources": [
    "https://www.nps.gov/places/000/grand-prismatic-spring.htm",
    "GPX recorded by Mara Lindgren on 2026-09-14"
  ],
  "extraProps": [
    {
      "label": "Dogs",
      "value": "Not allowed on park trails"
    }
  ],
  "season": {
    "months": [
      4,
      5,
      6,
      7,
      8,
      9,
      10
    ],
    "closureNote": "Park roads close to cars from early November to mid April; the trailhead is then reached by snowcoach only.",
    "statusUrl": "https://www.nps.gov/yell/planyourvisit/conditions.htm"
  },
  "variants": [
    {
      "name": "On to Fairy Falls",
      "extraKm": 6.8,
      "extraMin": 120,
      "purpose": "A 60 m waterfall 3.4 km further along the same trail, quiet before 09:00."
    }
  ],
  "segments": [
    {
      "name": "Fountain Freight Road",
      "km": 1.1,
      "accessNote": "Flat gravel road over the Firehole River, closed to cars. Bikes allowed."
    },
    {
      "name": "Overlook spur",
      "km": 0.3,
      "accessNote": "Hikers only. The one climb of the route."
    }
  ],
  "figureSources": [
    {
      "field": "distanceKm",
      "kind": "sourced",
      "url": "https://www.nps.gov/places/000/grand-prismatic-spring.htm"
    },
    {
      "field": "gainM",
      "kind": "computed",
      "note": "From the GPX, smoothed"
    },
    {
      "field": "durationMin",
      "kind": "computed",
      "note": "Walking time without the stop on the platform"
    }
  ],
  "track": {
    "coordinates": [
      [
        -110.8326,
        44.5156,
        2181
      ],
      [
        -110.8349,
        44.517,
        2182
      ],
      [
        -110.8372,
        44.5183,
        2183
      ],
      [
        -110.8391,
        44.519,
        2186
      ],
      [
        -110.8402,
        44.5196,
        2201
      ],
      [
        -110.8406,
        44.5199,
        2214
      ]
    ],
    "source": "gpx",
    "fileName": "fairy-falls-overlook-2026-09-14.gpx"
  },
  "reviewNotes": "The NPS page gives no elevation gain; the figure comes from the GPX.",
  "factsCheckedOn": "2026-09-20",
  "reviewBy": "2027-04-01"
}'
```

MCP `tools/call`:

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "create_route",
    "arguments": {
      "productId": "j5738kd1q9x2m7v4c6b8n0p3r5t1w9y2",
      "name": "Fairy Falls trail to the Grand Prismatic overlook",
      "activity": "hike",
      "sacGrade": "Class 1",
      "gradeScale": "yds",
      "sourceGrade": "Easy",
      "effortLabel": "Easy",
      "durationMin": 45,
      "durationBasis": "round_trip",
      "distanceKm": 2,
      "gainM": 35,
      "descentM": 35,
      "shape": "out_and_back",
      "start": "Fairy Falls trailhead on the Grand Loop Road, 1.6 km south of Midway Geyser Basin",
      "startMapsUrl": "https://maps.apple.com/?ll=44.5156,-110.8326&q=Fairy%20Falls%20Trailhead",
      "description": "A flat kilometer on the old Fountain Freight Road, then a short climb to a platform above Grand Prismatic Spring. Go mid morning on a warm day, once the steam has lifted.",
      "transit": [
        {
          "mode": "car",
          "note": "Park at the Fairy Falls trailhead lot, which fills by 09:30 in July and August. No public transport runs in the park."
        },
        {
          "mode": "plane",
          "note": "Yellowstone Airport (WYS) in West Yellowstone, 45 km by road, has flights from June to September."
        }
      ],
      "equipment": [
        "Bear spray",
        "A warm layer for the morning"
      ],
      "sources": [
        "https://www.nps.gov/places/000/grand-prismatic-spring.htm",
        "GPX recorded by Mara Lindgren on 2026-09-14"
      ],
      "extraProps": [
        {
          "label": "Dogs",
          "value": "Not allowed on park trails"
        }
      ],
      "season": {
        "months": [
          4,
          5,
          6,
          7,
          8,
          9,
          10
        ],
        "closureNote": "Park roads close to cars from early November to mid April; the trailhead is then reached by snowcoach only.",
        "statusUrl": "https://www.nps.gov/yell/planyourvisit/conditions.htm"
      },
      "variants": [
        {
          "name": "On to Fairy Falls",
          "extraKm": 6.8,
          "extraMin": 120,
          "purpose": "A 60 m waterfall 3.4 km further along the same trail, quiet before 09:00."
        }
      ],
      "segments": [
        {
          "name": "Fountain Freight Road",
          "km": 1.1,
          "accessNote": "Flat gravel road over the Firehole River, closed to cars. Bikes allowed."
        },
        {
          "name": "Overlook spur",
          "km": 0.3,
          "accessNote": "Hikers only. The one climb of the route."
        }
      ],
      "figureSources": [
        {
          "field": "distanceKm",
          "kind": "sourced",
          "url": "https://www.nps.gov/places/000/grand-prismatic-spring.htm"
        },
        {
          "field": "gainM",
          "kind": "computed",
          "note": "From the GPX, smoothed"
        },
        {
          "field": "durationMin",
          "kind": "computed",
          "note": "Walking time without the stop on the platform"
        }
      ],
      "track": {
        "coordinates": [
          [
            -110.8326,
            44.5156,
            2181
          ],
          [
            -110.8349,
            44.517,
            2182
          ],
          [
            -110.8372,
            44.5183,
            2183
          ],
          [
            -110.8391,
            44.519,
            2186
          ],
          [
            -110.8402,
            44.5196,
            2201
          ],
          [
            -110.8406,
            44.5199,
            2214
          ]
        ],
        "source": "gpx",
        "fileName": "fairy-falls-overlook-2026-09-14.gpx"
      },
      "reviewNotes": "The NPS page gives no elevation gain; the figure comes from the GPX.",
      "factsCheckedOn": "2026-09-20",
      "reviewBy": "2027-04-01"
    }
  }
}
```

Response 201:

```json
{
  "routeId": "kx7f2h8j4k0k6z2x8c4v0b6n2m8q4w0e",
  "name": "Fairy Falls trail to the Grand Prismatic overlook",
  "activity": "hike",
  "sacGrade": "Class 1",
  "gradeScale": "yds",
  "effortLabel": "Easy",
  "durationMin": 45,
  "gainM": 35,
  "descentM": 35,
  "distanceKm": 2,
  "start": "Fairy Falls trailhead on the Grand Loop Road, 1.6 km south of Midway Geyser Basin",
  "startMapsUrl": "https://maps.apple.com/?ll=44.5156,-110.8326&q=Fairy%20Falls%20Trailhead",
  "transit": [
    {
      "mode": "car",
      "note": "Park at the Fairy Falls trailhead lot, which fills by 09:30 in July and August. No public transport runs in the park."
    },
    {
      "mode": "plane",
      "note": "Yellowstone Airport (WYS) in West Yellowstone, 45 km by road, has flights from June to September."
    }
  ],
  "description": "A flat kilometer on the old Fountain Freight Road, then a short climb to a platform above Grand Prismatic Spring. Go mid morning on a warm day, once the steam has lifted.",
  "equipment": [
    "Bear spray",
    "A warm layer for the morning"
  ],
  "sources": [
    "https://www.nps.gov/places/000/grand-prismatic-spring.htm",
    "GPX recorded by Mara Lindgren on 2026-09-14"
  ],
  "extraProps": [
    {
      "label": "Dogs",
      "value": "Not allowed on park trails"
    }
  ],
  "track": {
    "coordinates": [
      [
        -110.8326,
        44.5156,
        2181
      ],
      [
        -110.8349,
        44.517,
        2182
      ],
      [
        -110.8372,
        44.5183,
        2183
      ],
      [
        -110.8391,
        44.519,
        2186
      ],
      [
        -110.8402,
        44.5196,
        2201
      ],
      [
        -110.8406,
        44.5199,
        2214
      ]
    ],
    "source": "gpx",
    "fileName": "fairy-falls-overlook-2026-09-14.gpx"
  },
  "status": null,
  "season": {
    "months": [
      4,
      5,
      6,
      7,
      8,
      9,
      10
    ],
    "closureNote": "Park roads close to cars from early November to mid April; the trailhead is then reached by snowcoach only.",
    "statusUrl": "https://www.nps.gov/yell/planyourvisit/conditions.htm"
  },
  "variants": [
    {
      "name": "On to Fairy Falls",
      "extraKm": 6.8,
      "extraMin": 120,
      "purpose": "A 60 m waterfall 3.4 km further along the same trail, quiet before 09:00."
    }
  ],
  "stages": [],
  "segments": [
    {
      "name": "Fountain Freight Road",
      "km": 1.1,
      "accessNote": "Flat gravel road over the Firehole River, closed to cars. Bikes allowed."
    },
    {
      "name": "Overlook spur",
      "km": 0.3,
      "accessNote": "Hikers only. The one climb of the route."
    }
  ],
  "shape": "out_and_back",
  "durationBasis": "round_trip",
  "ascentMin": null,
  "descentMin": null,
  "sourceGrade": "Easy",
  "figureSources": [
    {
      "field": "distanceKm",
      "kind": "sourced",
      "url": "https://www.nps.gov/places/000/grand-prismatic-spring.htm"
    },
    {
      "field": "gainM",
      "kind": "computed",
      "note": "From the GPX, smoothed"
    },
    {
      "field": "durationMin",
      "kind": "computed",
      "note": "Walking time without the stop on the platform"
    }
  ],
  "reviewNotes": "The NPS page gives no elevation gain; the figure comes from the GPX.",
  "factsCheckedOn": "2026-09-20",
  "reviewBy": "2027-04-01",
  "createdAt": 1789895640000,
  "updatedAt": 1789895640000,
  "spots": [],
  "facilities": []
}
```

### A short drive with only the basics: everything else comes back null or empty

```bash
curl -X POST "https://sceniq.earth/api/v1/guides/j5738kd1q9x2m7v4c6b8n0p3r5t1w9y2/routes" \
  -H "Authorization: Bearer $SCENIQ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Wawona Road from Yosemite Valley to Tunnel View",
  "activity": "drive",
  "durationMin": 10,
  "durationBasis": "one_way",
  "distanceKm": 6.5
}'
```

MCP `tools/call`:

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "create_route",
    "arguments": {
      "productId": "j5738kd1q9x2m7v4c6b8n0p3r5t1w9y2",
      "name": "Wawona Road from Yosemite Valley to Tunnel View",
      "activity": "drive",
      "durationMin": 10,
      "durationBasis": "one_way",
      "distanceKm": 6.5
    }
  }
}
```

Response 201:

```json
{
  "routeId": "kx7c5v7b9n1m3q5w7e9r1t3y5v7j9p1p",
  "name": "Wawona Road from Yosemite Valley to Tunnel View",
  "activity": "drive",
  "sacGrade": null,
  "gradeScale": null,
  "effortLabel": null,
  "durationMin": 10,
  "gainM": null,
  "descentM": null,
  "distanceKm": 6.5,
  "start": null,
  "startMapsUrl": null,
  "transit": [],
  "description": null,
  "equipment": null,
  "sources": [],
  "extraProps": [],
  "track": null,
  "status": null,
  "season": null,
  "variants": [],
  "stages": [],
  "segments": [],
  "shape": null,
  "durationBasis": "one_way",
  "ascentMin": null,
  "descentMin": null,
  "sourceGrade": null,
  "figureSources": [],
  "reviewNotes": null,
  "factsCheckedOn": null,
  "reviewBy": null,
  "createdAt": 1790673240000,
  "updatedAt": 1790673240000,
  "spots": [],
  "facilities": []
}
```

## Errors

- `invalid_argument` (400): A required field is missing, a field is unknown, or a value does not match its type (the Convex validator's path and value are in the message).
- `invalid_request` (400): A writer refused a value: a map link on a host that is not allowed, a title that is too long, a date that does not exist, too many items in a list. The message is the writer's own sentence.
- `unauthenticated` (401): The request carries no key. Send it as Authorization: Bearer sk_sceniq_... (or X-Api-Key).
- `invalid_api_key` (401): The key is unknown, revoked or expired.
- `api_scope_required` (403): A read-only key called a write operation, or a key without the publish option called publish_changes.
- `forbidden` (403): The key belongs to a creator account that is no longer active.
- `not_found` (404): The id does not exist or belongs to another creator. The two answers are identical on purpose, so ids never reveal what exists.
- `payload_too_large` (413): A JSON body over 2 MB, an image over 6 MB, a batch upload over 19 MB, or an MCP message over 2 MB.
- `rate_limited` (429): Over a limit: requests per key per minute, per creator per hour, uploads per key per minute, or check_links per guide per hour.
- `internal_error` (500): An unexpected failure. The message is hidden on purpose.

Reference: https://developers.sceniq.earth/reference/create_route
