Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,32 @@ that may never merge. They are not releases and are not listed here.
that passes them now fails with an unknown-argument error; drop the
flags. `mapbox search forward` keeps them. (#76)

- `mapbox matrix`, travel time and/or distance between every pair in a set
of up to 25 coordinates in one call, for driving (with or without live
traffic), walking, or cycling. No subcommand: like `mapbox directions`
below, this API has one operation, so there's nothing a second word (the
old `compute`) would disambiguate; see `spec::FLATTENED_SERVICES`.
Hand-authored into `custom-openapi/` for the same reason the other
Navigation commands were: no upstream spec exists yet. Reuses the
`profile`-vs-`--profile` collision fix (`ARG_NAME_OVERRIDES` gets a
fourth row) and the free-form (not `enum`) routing profile, for the same
OEM-account reason. `--sources`/`--destinations` take
semicolon-separated indices, not comma; verified against production
after the API answered a comma-separated list with a 422.

- `mapbox map-match`, snapping a noisy GPS trace to the road network and
returning the route it most likely followed, for driving (with or
without live traffic), walking, or cycling. No subcommand: like `mapbox
directions` below, this API has one operation, so there's nothing a
second word (the old `match`) would disambiguate; see
`spec::FLATTENED_SERVICES`. Hand-authored into `custom-openapi/` for the
same reason `mapbox directions` and `mapbox isochrone` were: no upstream
spec exists yet. Reuses the `profile`-vs-`--profile` collision fix
(`ARG_NAME_OVERRIDES` gets a third row) and the free-form (not `enum`)
routing profile, for the same OEM-account reason. Excludes POST, for the
same reason `directions` does: the API's own POST is for a trace too long
for a URL, a real gap rather than a design choice.

- `mapbox isochrone`, how far you can get from a point in a given time or
distance, for driving (with or without live traffic), walking, or
cycling, returned as GeoJSON polygons or linestrings. No subcommand:
Expand Down
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -251,10 +251,11 @@ mapbox styles <operation>
mapbox tilesets <operation>
```

`mapbox directions` and `mapbox isochrone` are the exceptions: each API has
a single operation, so there's a bare command with no subcommand at all,
the same shape `mapbox usage` already has, see
[docs/commands.md](./docs/commands.md) for their own parameters.
`mapbox directions`, `mapbox isochrone`, `mapbox map-match`, and
`mapbox matrix` are the exceptions: each API has a single operation, so
there's a bare command with no subcommand at all, the same shape
`mapbox usage` already has, see [docs/commands.md](./docs/commands.md)
for their own parameters.

A command group is not the same thing as a spec file: which one an operation
belongs to is decided per operation. So `sprites` and `tilesets` are each
Expand Down
280 changes: 280 additions & 0 deletions custom-openapi/map-match/openapi/map-match.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,280 @@
openapi: "3.0.0"
# `parse_spec` turns `info.description` below into this service's clap
# `long_about`, so it also reaches `mapbox map-match --help`, `--schema`
# and `generate-skills` output. Keep it to API prose only — the provenance
# below is for whoever edits this file, not for a CLI user:
#
# Hand-authored down to the parameters documented at
# docs.mapbox.com/api/navigation/map-matching. See `custom-openapi/README.md`
# for how a file like this is wired in, and `directions.yaml`'s header for
# why `profile` needs `ARG_NAME_OVERRIDES` in `src/spec.rs` — the same
# reason applies here. Excludes POST, for the same reason `directions.yaml`
# does: this spec format has no way to say "GET or POST, caller's choice"
# for one operationId. The API's own POST is for a request too long for a
# URL (~8100 bytes) — a real gap for a very long trace, not a design choice.
info:
title: "Mapbox Map Matching API"
description: >-
Snaps a noisy GPS trace to the road network and returns the route it
most likely followed, for driving (with or without live traffic),
walking, or cycling.
version: "0.0.0"
servers:
- url: https://api.mapbox.com
description: Map Matching API
paths:
/matching/v5/{profile}/{coordinates}.json:
get:
operationId: match
summary: Match a GPS trace to the road network.
description: >-
Returns one or more matched routes (more than one where the trace is
ambiguous enough to split), each with a `confidence` the API assigns
itself, plus one tracepoint per input coordinate — `null` for a
coordinate too far from any candidate to match at all.
parameters:
- name: "profile"
in: path
required: true
# Not an `enum`: the four documented values are what's public, but
# not what's exhaustive — some customers (OEM agreements, mainly)
# have additional profiles never published to docs.mapbox.com.
# An `enum` here becomes a clap `PossibleValuesParser` that
# rejects anything else client-side, which would break this CLI
# for exactly the accounts that most need a routing profile
# named beyond `driving`/`walking`/`cycling`. Same fix as
# `directions.yaml`'s `profile`.
description: >-
The routing profile — `mapbox/driving-traffic` (accounts for
live traffic), `mapbox/driving`, `mapbox/walking`, or
`mapbox/cycling` are documented, but not necessarily
exhaustive: some accounts have additional profiles of their
own. Sent exactly as typed; the API is the authority on
whether a value is valid, not this description.
schema:
type: string
minLength: 1
example: "mapbox/driving"
- name: "coordinates"
in: path
required: true
description: >-
2-100 trace points, semicolon-separated, each
`{longitude},{latitude}` — or an OpenLR-encoded string of up to
50 points, in which case use `--openlr-spec`/`--openlr-format`
to say which flavor.
schema:
type: string
minLength: 1
example: "-122.42,37.78;-122.421,37.781;-122.422,37.782"
- name: "access_token"
in: query
required: true
description: "Mapbox API Access Token"
schema:
type: string
minLength: 1
# Prose rather than an `enum`: this is a comma-separated list, and
# the command builder turns a spec `enum` into a clap
# `PossibleValuesParser`, which accepts one value and would refuse
# `distance,duration`. Same reasoning as `directions.yaml`'s
# `annotations`.
- name: "annotations"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The docs limit some values to certain profiles, but the descriptions here do not say so: congestion/congestion_numeric work only with mapbox/driving-traffic, maxspeed only with driving and driving-traffic, and --linear-references (line 223) only with driving and driving-traffic. I checked: congestion on mapbox/driving returns all "unknown", and --linear-references on mapbox/walking returns a 422 that does not mention the profile. Please add these limits to the descriptions and docs/commands.md.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed against docs.mapbox.com and added all three limits to the description and docs/commands.md.

in: query
required: false
description: >-
Segment-level metadata to add to each leg, comma-separated.
Requires `--overview full`. Options are `distance`, `duration`,
`speed`, `congestion`, `congestion_numeric` (both
`mapbox/driving-traffic` only), `maxspeed` (`mapbox/driving`
and `mapbox/driving-traffic` only).
schema:
type: string
example: "duration,distance"
- name: "approaches"
in: query
required: false
description: >-
Which side of the road to approach each waypoint from,
semicolon-separated — `unrestricted` or `curb` per coordinate.
Requires `--steps`.
schema:
type: string
- name: "geometries"
in: query
required: false
description: "The route geometry's format. Defaults to `polyline`."
schema:
type: string
enum: ["geojson", "polyline", "polyline6"]
- name: "overview"
in: query
required: false
description: >-
How much geometry detail the response carries. Defaults to
`simplified`.
schema:
type: string
enum: ["full", "simplified", "false"]
- name: "radiuses"
in: query
required: false
description: >-
Maximum distance in meters, 0-50, a coordinate may snap to the
road network, semicolon-separated, one per coordinate. Defaults
to 5.
schema:
type: string
- name: "steps"
in: query
required: false
description: >-
Return turn-by-turn instructions. Several other parameters
(`approaches`, `banner_instructions`, `language`,
`roundabout_exits`, `voice_instructions`) only take effect when
this is set.
schema:
type: boolean
- name: "banner_instructions"
in: query
required: false
description: "Return banner objects for display. Requires `--steps`."
schema:
type: boolean
- name: "language"
in: query
required: false
description: >-
The language turn-by-turn instructions are written in. Defaults
to `en`. Requires `--steps`.
schema:
type: string
example: "en"
- name: "roundabout_exits"
in: query
required: false
description: >-
Emit a separate instruction for entering and exiting a
roundabout, rather than one instruction for the whole
maneuver. Requires `--steps`.
schema:
type: boolean
- name: "voice_instructions"
in: query
required: false
description: >-
Return SSML-marked-up voice guidance text. Requires `--steps`.
schema:
type: boolean
- name: "voice_units"
in: query
required: false
description: >-
Units for voice instructions. Requires `--steps` and
`--voice-instructions`.
schema:
type: string
enum: ["imperial", "british_imperial", "metric"]
- name: "tidy"
in: query
required: false
description: >-
Remove clusters and resample the trace before matching — useful
for a trace recorded at an inconsistent sample rate.
schema:
type: boolean
- name: "timestamps"
in: query
required: false
description: >-
A Unix timestamp per coordinate, semicolon-separated and
ascending — when the trace was actually recorded, rather than
assumed from even spacing.
schema:
type: string
- name: "waypoint_names"
in: query
required: false
description: >-
A name per waypoint, semicolon-separated, used in that
waypoint's arrival instruction instead of the road name. Up to
500 characters total. Requires `--steps`.
schema:
type: string
- name: "waypoints"
in: query
required: false
description: >-
Zero-based indices into `coordinates` marking which ones get
their own arrival instruction, semicolon-separated — must
include `0` and the last index. Most useful with `--steps`,
which it does not require.
schema:
type: string
example: "0;2"
# Prose rather than an `enum`, for the reason given on `annotations`
# above.
- name: "ignore"
in: query
required: false
description: >-
Restrictions to ignore while matching, comma-separated.
Options are `access`, `oneways`, `restrictions`.
`mapbox/driving` only.
schema:
type: string
- name: "linear_references"
in: query
required: false
description: >-
Return an OpenLR reference (base64) per matched leg, alongside
the ordinary geometry. `mapbox/driving` and
`mapbox/driving-traffic` only.
schema:
type: boolean
- name: "openlr_spec"
in: query
required: false
description: >-
Which OpenLR specification `coordinates` is encoded with, when
it is an OpenLR string rather than a coordinate list. Defaults
to `tomtom`.
schema:
type: string
enum: ["tomtom", "here"]
- name: "openlr_format"
in: query
required: false
description: >-
The OpenLR binary format `coordinates` is encoded in, when it
is an OpenLR string. Only `tomtom` exists today.
schema:
type: string
enum: ["tomtom"]
- name: "depart_at"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: the docs do not limit depart_at to mapbox/driving-traffic, and the API takes only three formats, not any ISO 8601. For example, 2030-01-01T08:00:00 returns 422. Maybe say "Departure time from the first coordinate" and list YYYY-MM-DDThh:mm, YYYY-MM-DDThh:mm:ssZ and YYYY-MM-DDThh:mm:ss±hh:mm.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed, named the three actual formats and dropped the profile restriction, confirmed against docs.mapbox.com.

in: query
required: false
description: >-
Departure time from the first coordinate, one of
`YYYY-MM-DDThh:mm`, `YYYY-MM-DDThh:mm:ssZ` or
`YYYY-MM-DDThh:mm:ss±hh:mm` — not open ISO 8601, the API
rejects other valid ISO 8601 shapes.
schema:
type: string
responses:
"200":
description: >-
A JSON object with a `code`, a `matchings` array (each with
`confidence`, `distance`, `duration`, `geometry`, and `legs`),
and a `tracepoints` array — one entry per input coordinate,
`null` for one too far from any candidate to match.
"401":
description: Unauthorized
"403":
description: Forbidden
"404":
description: Not Found — an invalid profile.
"422":
description: >-
Unprocessable Entity — invalid input, or more coordinates than
the profile allows (100 for a coordinate list, 50 for OpenLR).
Loading
Loading