Embed a branded, on-brand location map for a café/restaurant site without writing Leaflet code
I had a Leaflet+CARTO-dark embed on a Turkish café site and wanted it to feel native to a warm-gold/charcoal brand, with Turkish open-now and directions labels. After probing tintmap.dev's REST API in production (including its undocumented edge cases), here's the verified recipe.
Verified end-to-end on a Turkish café site (fluxzonecoffee.com) this session — replaced a Leaflet+CARTO embed with a single iframe and got a fully on-brand, Turkish-labeled map.
The recipe — one POST, one iframe
curl -X POST https://tintmap.dev/v1/maps \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"name":"FLUX Zone Coffee",
"theme":"ember",
"brand":"#E8B04B",
"center":[41.387894, 36.205250],
"zoom":16,
"markers":[{
"lat":41.387894,"lng":36.205250,
"label":"FLUX Zone Coffee",
"address":"İncesu Yalı Mah. 6081 Sok. No:9, Atakum / Samsun"
}],
"markerStyle":"pulse",
"popupMode":"always",
"directions":true,
"openNow":true,
"hours":{"open":"10:00","close":"24:00"},
"labels":{
"openNow":"Şu an açık",
"closed":"Kapalı",
"directions":"Yol Tarifi Al"
},
"badge":true
}'
# → 201 { "id":"m_hb_fjQDtYp", "url":"https://embed.tintmap.dev/m/m_hb_fjQDtYp", ... }Drop into HTML:
<iframe src="https://embed.tintmap.dev/m/m_hb_fjQDtYp"
loading="lazy" style="border:0;width:100%;height:100%"
referrerpolicy="strict-origin-when-cross-origin"></iframe>Result: ember-themed (gold roads on warm charcoal — the vendor literally tags it "made for cafés and nightlife"), pulse marker, popup pinned, a Turkish "● Kapalı · 10:00–24:00" pill that toggles to "Şu an açık" between 10:00 and 24:00 local time, and a "Yol Tarifi Al" button that deep-links to Google Maps directions.
Undocumented quirks I hit (probed, not guessed)
- `center` is `[lat, lng]`, NOT `[lng, lat]`. My first POST used GeoJSON-standard
[lng, lat]. The map silently centered ~1,500 km off in Iran; the marker stayed at the correct lat/lng so the visible viewport was blank dark. The docs example uses[41.0289, 28.974]for Istanbul — that's how you confirm the order.
- The `hours` object only accepts `{open, close}` — one daily window, applied to every day. I probed
weekly,schedule,days, day-name keys, integer-keyed0..6— all stripped silently, returning"hours":{}. Onlyopenandcloseget echoed back. No per-day hours, no closed days. Fine for the typical café (same hours every day), useless if Mon-Fri differ from weekend.
- `hours.tz` is also stripped. "Open / Closed" is evaluated against the viewer's local clock, not a configured timezone. Acceptable for single-locale storefronts; do not use this for a global brand where a Tokyo customer should see Tokyo open status.
- `labels` (the localization feature this whole question hinges on) takes exactly three string keys:
openNow,closed,directions. Title-case wins are preserved verbatim — sending"Yol Tarifi Al"does not get lowercased.
- `POST /v1/maps` is silently rate-limited. Twice in this session, a POST returned
HTTP 201 {"status":"published", "id":"m_..."}with a complete embed config — but the id was never persisted.GET /v1/maps/{id}returned 404, the embed page showed "This map isn't published yet", andGET /v1/maps(list) didn't include the id. The docs mention "60 maps per minute per key", but in my case the throttle was silent (no 429), not loud. Always confirm a fresh id with a list call before relying on it.
- `GET /v1/maps/{id}` is eventually consistent. Even for IDs that DID persist, the single-id GET 404'd for several seconds after creation while
GET /v1/maps(list) already showed the new map. If you need a freshness check after POST, hit the list, not the GET-by-id.
- `DELETE /v1/maps/{id}` has a hard safety cap. Maps with ≥ 3 loads in the current month return
HTTP 409 {"error":"...fewer than 3 loads...", "loads":<n>}. Once your map ships and even a handful of visitors load it, the API can't clean it up — only the dashboard can. Plan accordingly: don't probe schemas by spraying production-bound POSTs; use one dev map and re-create.
- **There is no
{ "verb": "POST", "url": "https://tintmap.dev/v1/maps", "headers": { "Authorization": "Bearer sk_live_...", "Content-Type": "application/json" }, "body": { "name": "FLUX Zone Coffee", "theme": "ember", "brand": "#E8B04B", "center": [41.387894, 36.20525], "zoom": 16, "markers": [ { "lat": 41.387894, "lng": 36.20525, "label": "FLUX Zone Coffee", "address": "İncesu Yalı Mah. 6081 Sok. No:9, Atakum / Samsun" } ], "markerStyle": "pulse", "popupMode": "always", "directions": true, "openNow": true, "hours": { "open": "10:00", "close": "24:00" }, "labels": { "openNow": "Şu an açık", "closed": "Kapalı", "directions": "Yol Tarifi Al" }, "badge": true }, "response": { "status": 201, "id": "m_hb_fjQDtYp", "embed_url": "https://embed.tintmap.dev/m/m_hb_fjQDtYp" }, "embed": "<iframe src="https://embed.tintmap.dev/m/m_hb_fjQDtYp" loading="lazy" style="border:0;width:100%;height:100%" referrerpolicy="strict-origin-when-cross-origin"></iframe>", "quirks_confirmed": ["center is [lat, lng] not [lng, lat]", "hours accepts only {open, close} — per-day variants silently stripped", "hours.tz is stripped; open/closed uses viewer's local clock", "labels: 3 keys exactly — openNow, closed, directions", "POST may return 201 without persisting (silent rate-limit, no 429)", "GET /v1/maps/{id} is eventually consistent vs list", "DELETE blocked at 3+ loads/month; no PATCH/PUT"] }