Base URLs
Section titled “Base URLs”| Environment | URL | Keys |
|---|---|---|
| Test | https://api.staging.mongrl.com |
sk_test_…, pk_test_… |
| Live | https://api.mongrl.com |
sk_live_…, pk_live_… |
All requests and responses are JSON (application/json), except photo uploads (the image’s bytes). See Authentication for keys and sessions.
Errors
Section titled “Errors”Errors are RFC 9457 problems, sent as application/problem+json:
{ "title": "Unprocessable Entity", "status": 422, "detail": "the listing isn't ready to go on sale", "errors": [ { "location": "body.price", "message": "a price is needed", "value": null }, { "location": "body.images", "message": "add at least 3 photos" } ]}- Show
detailto people. It’s written to be read. errors[].locationpoints at the field:body.<field>,query.<name>orpath.<name>. Map it onto your form.- Validation errors list every problem at once, not just the first.
| Status | Meaning |
|---|---|
400 |
The request is malformed (bad JSON, a bad Idempotency-Key). |
401 |
No key, a key that doesn’t work, or a user session that has ended. |
403 |
The key or user may not do this (e.g. a blocked user). |
404 |
Not found, or not yours. Other marketplaces’ and users’ things are always 404. |
409 |
Not possible in the current state: sold, already in use, a transition that isn’t available. |
422 |
The input is wrong. See errors. |
429 |
Too many attempts. Wait for Retry-After seconds. |
503 |
A dependency (such as payments) isn’t available. Try again later. |
Money is always an object with an integer amount in minor units and an ISO 4217 currency:
{ "amount": 125000, "currency": "SEK" }That’s 1 250,00 kr. Never use floats for money. Totals and line items on orders are plain integers in the order’s currency.
Ids and dates
Section titled “Ids and dates”- Ids are UUIDs (
"8f3c2a1e-…"). Treat them as opaque strings. - Times are RFC 3339 in UTC (
"2026-10-19T14:05:00Z"). Dates without a time areYYYY-MM-DD.
Paging
Section titled “Paging”Two styles, depending on the list:
| Lists | Style |
|---|---|
| Listings, favourites, a seller’s listings, catalogue terms | Cursor: pass next_cursor back as cursor. No next_cursor means the last page. |
| Orders, conversations | Offset: limit and offset. A page shorter than limit is the last. |
| Messages in a conversation | After: after=<message id> returns only newer messages, oldest first. |
limit is at most 100 (200 for catalogue terms and messages). Search also returns total, the number of matches.
Idempotency
Section titled “Idempotency”Send Idempotency-Key on any POST, PUT, PATCH or DELETE you might retry, above all placing an order. Use a fresh UUID per user action.
- A retry with the same key and the same request doesn’t run again: it replays the first response, with
Idempotent-Replayed: true. - The same key with a different request is
422; while the first request still runs it’s409. - Server errors (
5xx) aren’t stored, so retrying them runs the request again. - Keys last 24 hours and belong to your key (and user), so they never collide with anyone else’s.
Rate limits
Section titled “Rate limits”Limits protect people, not the API’s capacity:
- Sign-in: 10 wrong passwords in 15 minutes locks the account for the rest of that window.
- Emailed links (sign-in, password reset, confirmation): 5 an hour per address.
Over a limit you get 429 with Retry-After.
Languages
Section titled “Languages”The marketplace’s languages are in GET /v1/marketplace → locales (BCP 47, the first is the default). Pass locale where an endpoint takes one (categories, catalogue terms); a user’s locale decides the language of their emails.
Versioning
Section titled “Versioning”Everything is under /v1. Within v1, changes only add things: new endpoints, new optional request fields, new response fields, new enum values. Write clients that ignore fields they don’t know. Anything that would break a client gets a new version.
The spec
Section titled “The spec”The OpenAPI 3.1 spec (YAML) is generated from the API’s code and published with it, so it always matches the API. It covers everything a storefront can call; the console’s own endpoints aren’t in it.