The API is served under https://osm-boundaries.com/api/v1. Every endpoint is documented one by one in the API reference. This page covers what holds for all of them.

Index


Authentication

Send your API key in the X-OSMB-Api-Key header. You will find it on your profile page, and it changes whenever you re-authenticate with OpenStreetMap.

curl --header 'X-OSMB-Api-Key: <your-key>' \
  'https://osm-boundaries.com/api/v1/test/ping'

The key can also be passed as an apiKey query parameter. That exists for the download endpoints, which a browser follows as ordinary links and therefore cannot send a header with. Prefer the header everywhere else: query strings end up in logs and in browser history.

Responses

Every response is the same shape, whether the request succeeded or not.

{
  "data": "pong",
  "error": null,
  "rateLimit": { "used": 1, "max": 10, "waitFor": null }
}
  • data is whatever the endpoint produces, and is null when the request failed.
  • error is null when the request succeeded, and otherwise carries a message.
  • rateLimit describes the limit closest to being reached. See Rate Limits.
  • credits says what the call cost and what you have left, and is only there when the call was charged for. See Credits.
  • meta says where a page sits in the whole - limit, offset, the count on this page and the total there are - and is only there when the endpoint answers in pages.

The download endpoints are the exception: they answer with redirects and with the file itself, so there is no envelope to put anything in.

Errors

The HTTP status says what went wrong, and error.message says it in words.

StatusMeaning
400A parameter is missing, or is not valid.
401No API key was sent, or it is not a valid one.
403The key is valid, but your plan does not cover what you asked for.
404No such endpoint.
429You are being rate-limited. See below.
500Our fault. If it persists, please tell us.

Errors from the download endpoints arrive as a text file named osmb-error.txt, with the status 200, so that a browser saving a file ends up with something readable rather than with nothing. Scripts calling those endpoints should treat a response that is not gzipped as an error.

Rate Limits

Each endpoint has its own limits, and most have several over different windows. Every response reports the one closest to being reached: used of max requests in the current window.

Exceeding a limit gives you 429, with rateLimit.waitFor and the X-OSMB-RateLimit-Clears-In header both saying how many seconds until the bucket has room again. Wait that long rather than retrying immediately; retries that arrive early are themselves counted.

Credits

Most endpoints cost credits, and the reference says how many each one costs. Your credits come from your plan: a fixed quota every 24 hours, plus any additional credits you hold, and the quota is spent before the additional credits are.

Every response tells you where you stand.

"credits": { "cost": 1, "remaining": { "daily": 9976, "additional": 10000 } }
  • cost is what this call took. A free endpoint has no credits at all.
  • remaining.daily is what is left of the quota, which refills over the following 24 hours.
  • remaining.additional is what is left of your additional credits, which do not expire.

You are only charged for work we did. A request that fails costs nothing, whatever it failed on. A request we answer from cache costs the same as any other, since it still reached us; one answered by our CDN before it reaches us is free.

Running out gives you 402 and an error.message saying so. Downloading is charged separately and is described below.

Downloading

A download is not built while you wait. Requesting one redirects you to an endpoint that waits for it, which redirects either to the finished file or back to itself, for as long as the build takes. So the only thing your client has to do is follow redirects, without a limit on how many.

curl --remote-name --remote-header-name --location --max-redirs -1 \
  --header 'X-OSMB-Api-Key: <your-key>' \
  'https://osm-boundaries.com/api/v1/download?db=osm20240205&osmIds=-102740&format=GeoJSON'

The download form on the map writes that command out for you, with whatever options you have selected, which is the quickest way to get the parameters right.

A download costs credits, one per boundary in it. /api/v1/exports counts them for a request you have not made yet, and tells you whether your balance covers it.