Skip to content
Closed
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
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,16 @@ that may never merge. They are not releases and are not listed here.

## Unreleased

- `mapbox places get`/`batch`, full place detail — hours, phone, website,
photos, address, coordinates, activity data — by the `mapbox_id` a
Search Box API result already returned. Hand-authored into
`custom-openapi/` for the same reason this session's other additions
were: no upstream spec exists yet. `batch` takes `--data
'{"ids": [...]}'`, up to 100 ids in one call, the same shape `styles
create` already uses for a body with no sensible per-field flag. Both
operations verified against production with real ids from
`search forward`.

- `mapbox ev-charge-finder search`/`get`/`list-operators`, EV charging
stations near a point — searchable by connector type, operator, charging
power, availability, amenities and payment method — plus one station's
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ mapbox geocoder *
mapbox isochrone *
mapbox map-matching *
mapbox matrix *
mapbox places *
mapbox search *
mapbox sprites *
mapbox static *
Expand Down
107 changes: 107 additions & 0 deletions custom-openapi/places/openapi/places.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
openapi: "3.0.0"
# `parse_spec` turns `info.description` below into this service's clap
# `long_about`, so it also reaches `mapbox places --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/search/places. See `custom-openapi/README.md` for
# how a file like this is wired in.
info:
title: "Mapbox Places API"
description: >-
Full detail for a place — hours, phone, website, photos, address,
coordinates, activity data — by the `mapbox_id` a Search Box API result
already returned. This API has no search or suggest of its own; it only
resolves ids something else found.
version: "0.0.0"
servers:
- url: https://api.mapbox.com
description: Places API
paths:
/places/v1/details/retrieve/{mapbox_id}:
get:
operationId: get
summary: Full detail for one place.
description: >-
`mapbox_id` comes from a Search Box API result (`search forward`/
`reverse`/`category`) — this API does not look places up by name
or location itself.
parameters:
- name: "mapbox_id"
in: path
required: true
description: "The place's Mapbox ID, from a Search Box API result."
schema:
type: string
minLength: 1
- name: "access_token"
in: query
required: true
description: "Mapbox API Access Token"
schema:
type: string
minLength: 1
responses:
"200":
description: >-
A place record: `name`, `full_address`, `primary_category`/
`categories`, `coordinates` (with `routable_points`),
structured `address`, `score` (`closed`/`reality`/
`popularity`, each 0-1), and where available `brand`,
`opening_hours`, `phone`, `photos`, `website`, `building`, and
`telemetry` (hourly activity by day of week).
"401":
description: Unauthorized
"404":
description: Not Found — no place with that Mapbox ID.
"422":
description: Unprocessable Entity — `mapbox_id` isn't validly formed.
"429":
description: >-
Too Many Requests — the per-second rate limit, or the Public
Preview's monthly quota (1000 records/account), was exceeded.

/places/v1/details/retrieve:
post:
operationId: batch
summary: Full detail for up to 100 places in one call.
description: >-
Hydrates a whole list of Search Box API results in one round trip
instead of one `get` per id. `--data` carries `{"ids": [...]}` —
up to 100 `mapbox_id` strings.
parameters:
- name: "access_token"
in: query
required: true
description: "Mapbox API Access Token"
schema:
type: string
minLength: 1
requestBody:
required: true
content:
application/json:
schema:
type: object
responses:
"200":
description: >-
Every id resolved: `{"results": [<place record>, ...]}`, same
shape as `get`'s own response, one entry per id.
"206":
description: >-
Partial Content — some ids didn't resolve. Same body as 200,
plus `missing` (ids with no such place) and/or `unprocessed`
(ids that couldn't be processed) alongside `results`.
"400":
description: >-
Bad Request — `ids` isn't a non-empty array of at most 100
entries.
"401":
description: Unauthorized
"429":
description: >-
Too Many Requests — the per-second rate limit (batch is
charged by id count) or the Public Preview's monthly quota was
exceeded.
161 changes: 150 additions & 11 deletions docs/commands.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Implemented commands

Every command the CLI ships: four auth commands, 40 API operations across 14
Every command the CLI ships: four auth commands, 42 API operations across 15
command groups, the tilesets-cli proxy, `completion` and `generate-skills`. Each is
shown in both of its renderings. Which one you get is decided by `--output`, whose default
(`auto`) reads stdout: a terminal gets the left column, a pipe or redirect
Expand All @@ -10,10 +10,11 @@ gets the right one. See
Account names, style ids and tokens in the examples are replaced; everything
else is as the API sent it.

**33 of the 40 were run against the live API and show what came back:**
**35 of the 42 were run against the live API and show what came back:**
`directions route`, `isochrone contours`, `map-matching match`, `matrix
compute`, `feedback list` and `feedback get` on 2026-09-24, once those
command groups existed at all, and the rest earlier — `fonts list`,
compute`, `feedback list`, `feedback get`, `places get` and `places batch`
on 2026-09-24/25, once those command groups existed at all, and the rest
earlier — `fonts list`,
`fonts upload` and `fonts delete` on 2026-09-08 once
`fonts:list`/`fonts:write` became registrable, the remainder before that.
The write operations were exercised as round trips on throwaway objects —
Expand All @@ -33,13 +34,16 @@ commands and the flags they take — is held to `mapbox --schema` on every
can be checked cannot fall behind the binary.

The remaining 7 give the response shape from the spec or the docs instead
of a live capture. Four are `search`'s — read-only and safe to run, but the
credentials used to write this page have no Search Box API access, so
every call answers 401 rather than a result. The other three are
`ev-charge-finder`'s: that API is Private Preview, and this account isn't
enrolled — confirmed directly (a plain `curl` gets `401 invalid access
token` there and `200` on every other service with the same token), not
assumed.
of a live capture. Three are `ev-charge-finder`'s: that API is Private
Preview, and this account isn't enrolled — confirmed directly (a plain
`curl` gets `401 invalid access token` there and `200` on every other
service with the same token), not assumed. The other four are `search`'s,
marked as no-access when this page was first written — no longer true,
discovered while writing `places get`'s example above, which needed a real
`search forward` result to test against and got one. `search`'s own four
sections below haven't been re-captured with this pass, since that's a
different command group's page to touch; a worthwhile follow-up, not done
here.

Each **Parameters** section lists only what is specific to its command. The
globals every API command takes are
Expand Down Expand Up @@ -105,6 +109,9 @@ nests, and is typed `mapbox styles draft get`.

**[Matrix](#matrix)** — [matrix.compute](#mapbox-matrix-compute)

**[Places](#places)** — [places.get](#mapbox-places-get) ·
[places.batch](#mapbox-places-batch)

**[Search](#search)** — [search.forward](#mapbox-search-forward) ·
[search.reverse](#mapbox-search-reverse) ·
[search.category](#mapbox-search-category) ·
Expand Down Expand Up @@ -1837,6 +1844,138 @@ Neither output mode has a bespoke rendering for this response, same as
`-o text` pretty-printed and `-o json` on one line. Dropped each waypoint's
own snap `distance` for length; the real response carries it too.

---
## Places

Full detail for a place — hours, phone, website, photos, address,
coordinates, activity data — by the `mapbox_id` a Search Box API result
already returned. Curated by hand down to the parameters documented at
docs.mapbox.com/api/search/places — see `custom-openapi/README.md` for why
this command group doesn't come from the vendored specs the way most
others do.

**This API has no search or suggest of its own.** It only resolves ids
`search forward`/`reverse`/`category` already returned — the detail-view
follow-up to a search result, not a way to find places by name or location.

### `mapbox places get`

Full detail for one place.

#### Parameters

`<mapbox-id>` (positional) is required — from a Search Box API result.

#### Examples

```sh
mapbox places get dXJuOm1ieHBvaTpmYTE5Y2NhMC0yZmQ3LTQwMzgtYTEzNy02MzFmNGEwZDI5ODA
```

#### Outputs

Captured live, a real place found via `search forward --q "Ferry Building
San Francisco"`:

<table>
<tr><th width="50%">Terminal — <code>-o text</code></th><th width="50%">Agent — <code>-o json</code></th></tr>
<tr><td>

```json
{
"mapbox_id": "dXJuOm1ieHBvaTpmYTE5Y2NhMC0yZmQ3LTQwMzgtYTEzNy02MzFmNGEwZDI5ODA",
"name": "Ferry Building",
"full_address": "San Francisco, California, 94105, United States",
"primary_category": "food",
"categories": ["cafe", "food", "food_and_drink"],
"status": "active",
"permanently_closed": false,
"opening_hours": "Sa 08:00-14:00",
"phone": "+14152373318",
"website": "http://crumbleandwhisk.com/",
"score": { "closed": 0, "reality": 0.973, "popularity": 0.275 },
"coordinates": {
"latitude": 37.79557765,
"longitude": -122.39332918,
"source": "poi",
"routable_points": [
{ "name": "driving", "latitude": 37.795594, "longitude": -122.393338 }
]
},
"address": {
"city": "San Francisco",
"neighborhood": "Financial District",
"postcode": "94105",
"region": "California",
"region_code_full": "US-CA",
"country": "United States",
"country_code": "US"
}
}
```

</td><td>

```json
{"mapbox_id":"dXJuOm1ieHBvaTpmYTE5Y2NhMC0yZmQ3LTQwMzgtYTEzNy02MzFmNGEwZDI5ODA","name":"Ferry Building","full_address":"San Francisco, California, 94105, United States","primary_category":"food","categories":["cafe","food","food_and_drink"],"status":"active","permanently_closed":false,"opening_hours":"Sa 08:00-14:00","phone":"+14152373318","website":"http://crumbleandwhisk.com/","score":{"closed":0,"reality":0.973,"popularity":0.275},"coordinates":{"latitude":37.79557765,"longitude":-122.39332918,"source":"poi","routable_points":[{"name":"driving","latitude":37.795594,"longitude":-122.393338}]},"address":{"city":"San Francisco","neighborhood":"Financial District","postcode":"94105","region":"California","region_code_full":"US-CA","country":"United States","country_code":"US"}}
```

</td></tr>
</table>

Dropped `attributes` (14 boolean amenity flags — wheelchair access, payment
types, and the like), `created_at`/`updated_at`, and most `address` fields
that were `null` for this place, for length; the real response carries
them too. `brand` is `null` here since this isn't a chain location.

### `mapbox places batch`

Full detail for up to 100 places in one call — hydrates a whole list of
search results in one round trip instead of one `get` per id.

#### Parameters

`--data`/`-d` carries `{"ids": [...]}`, up to 100 `mapbox_id` strings.

#### Examples

```sh
mapbox places batch -d '{"ids": ["dXJuOm1ieHBvaTpmYTE5Y2NhMC0yZmQ3LTQwMzgtYTEzNy02MzFmNGEwZDI5ODA", "dXJuOm1ieHBvaTo4N2YzMmY2YS00MjkwLTQzNmItYWQyMi1hMzBhMzcxNWVmNzM"]}'
```

#### Outputs

Captured live, the same Ferry Building above plus a second real place:

<table>
<tr><th width="50%">Terminal — <code>-o text</code></th><th width="50%">Agent — <code>-o json</code></th></tr>
<tr><td>

```json
{
"results": [
{ "mapbox_id": "…fa19cca0…", "name": "Ferry Building" },
{ "mapbox_id": "…87f32f6a…", "name": "Golden Gate Bridge" }
]
}
```

</td><td>

```json
{"results":[{"mapbox_id":"…fa19cca0…","name":"Ferry Building"},{"mapbox_id":"…87f32f6a…","name":"Golden Gate Bridge"}]}
```

</td></tr>
</table>

Each entry in `results` is the full record `get` returns, trimmed to
`mapbox_id`/`name` here for length. Not captured live: `206` with
`missing`/`unprocessed` alongside `results` — the documented shape for a
batch where some ids didn't resolve. Both ids used to write this page were
real and resolved, so triggering it would have meant fabricating a
plausibly-shaped but fake id, which defeats the point of a live capture.

---

## Search
Expand Down
1 change: 1 addition & 0 deletions src/remedy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ const SERVICE_DOCS: &[(&str, &str)] = &[
"https://docs.mapbox.com/api/navigation/map-matching/",
),
("matrix", "https://docs.mapbox.com/api/navigation/matrix/"),
("places", "https://docs.mapbox.com/api/search/places/"),
("search", "https://docs.mapbox.com/api/search/search-box/"),
// Static Images and Static Tiles merged into one `static` command group
// (#116); neither upstream page covers both, so this points at Static
Expand Down
4 changes: 4 additions & 0 deletions src/spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,10 @@ pub const CUSTOM_SPEC_ENTRIES: &[SpecEntry] = &[
name: "ev-charge-finder",
yaml: include_str!("../custom-openapi/ev-charge-finder/openapi/ev-charge-finder.yaml"),
},
SpecEntry {
name: "places",
yaml: include_str!("../custom-openapi/places/openapi/places.yaml"),
},
];

/// The list the CLI actually generates commands from: [`MAPBOX_SPEC_ENTRIES`],
Expand Down
2 changes: 2 additions & 0 deletions tests/fixtures/api_command_surface.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ mapbox geocoder reverse | aliases: (none)
mapbox isochrone contours | aliases: (none)
mapbox map-matching match | aliases: (none)
mapbox matrix compute | aliases: (none)
mapbox places batch | aliases: (none)
mapbox places get | aliases: (none)
mapbox search category | aliases: (none)
mapbox search forward | aliases: (none)
mapbox search list-category | aliases: (none)
Expand Down
Loading