{"info":{"title":"ServiceBox — Nöbetçi Eczane API","version":"1.0.0","description":"On-duty and regular pharmacies for all 81 Turkish provinces and roughly 960 districts. Each pharmacy record carries its name, address, phone (E.164), location and, for on-duty pharmacies, the shift window it is covering (ISO 8601 with offset). Collections answer `{ items, next_cursor, total }`; page with `limit` (1–200, default 50) and `cursor`. Every answer carries `X-SBX-Response-Style: 1`. The dataset refreshes up to three times a day; use the ETag header to revalidate cheaply instead of re-fetching unchanged data. Requests with `activelyOnDuty` are the exception: they are answered live, with `Cache-Control: no-store` and no ETag."},"paths":{"/v1/pharmacy/cities":{"get":{"tags":["Reference"],"summary":"List cities","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CityList"},"example":{"items":[{"id":"ISTANBUL","name":"ISTANBUL","onDutyCount":498,"pharmacyCount":4120},{"id":"ANKARA","name":"ANKARA","onDutyCount":213,"pharmacyCount":1842}],"total":81,"next_cursor":null}}},"headers":{"ETag":{"$ref":"#/components/headers/ETag"}},"description":"Cities with pharmacy counts."},"304":{"$ref":"#/components/responses/NotModified"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"429":{"$ref":"#/components/responses/TooManyRequests"},"502":{"$ref":"#/components/responses/BadGateway"},"503":{"$ref":"#/components/responses/ServiceUnavailable"},"504":{"$ref":"#/components/responses/GatewayTimeout"}},"parameters":[{"$ref":"#/components/parameters/IfNoneMatch"}],"description":"All 81 provinces with pharmacy and on-duty counts, sorted by pharmacy count descending. A city's `id` is its name, which is what `city=` accepts. Not paged: the whole list in one answer.","operationId":"listCities","x-sbx-credits":0}},"/v1/pharmacy/districts":{"get":{"tags":["Reference"],"summary":"List districts","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DistrictList"},"example":{"items":[{"id":"ÇANKAYA","name":"ÇANKAYA","cityId":"ANKARA","onDutyCount":38,"pharmacyCount":312},{"id":"KEÇİÖREN","name":"KEÇİÖREN","cityId":"ANKARA","onDutyCount":22,"pharmacyCount":198}],"total":25,"next_cursor":null}}},"headers":{"ETag":{"$ref":"#/components/headers/ETag"}},"description":"Districts with pharmacy counts."},"304":{"$ref":"#/components/responses/NotModified"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"429":{"$ref":"#/components/responses/TooManyRequests"},"502":{"$ref":"#/components/responses/BadGateway"},"503":{"$ref":"#/components/responses/ServiceUnavailable"},"504":{"$ref":"#/components/responses/GatewayTimeout"}},"parameters":[{"in":"query","name":"city","schema":{"type":"string","maxLength":120},"description":"Restrict to districts of this city (case- and accent-insensitive). Omit to list all districts nationwide."},{"$ref":"#/components/parameters/IfNoneMatch"}],"description":"Districts (roughly 960 nationwide) with pharmacy and on-duty counts, optionally filtered to one city. A district's `id` is its name; `cityId` is its city's. Not paged: the whole list in one answer.","operationId":"listDistricts","x-sbx-credits":0}},"/v1/pharmacy/pharmacies":{"get":{"tags":["Pharmacies"],"summary":"Search pharmacies","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PharmacyPage"},"example":{"items":[{"id":"10432","city":"ANKARA","name":"MERKEZ ECZANESİ","type":null,"phone":"+903124441122","onDuty":false,"address":"Kızılay Mah. Atatürk Bulvarı No:12","district":"ÇANKAYA","location":{"lat":39.9208,"lon":32.8541},"dutyEndsAt":null,"dutyStartsAt":null}],"total":1842,"next_cursor":"eyJvIjoxLCJxIjoiM2E5ZjBjMWQifQ"}}},"headers":{"ETag":{"$ref":"#/components/headers/ETag"}},"description":"Pharmacies matching the filters."},"304":{"$ref":"#/components/responses/NotModified"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"429":{"$ref":"#/components/responses/TooManyRequests"},"502":{"$ref":"#/components/responses/BadGateway"},"503":{"$ref":"#/components/responses/ServiceUnavailable"},"504":{"$ref":"#/components/responses/GatewayTimeout"}},"parameters":[{"$ref":"#/components/parameters/City"},{"$ref":"#/components/parameters/District"},{"$ref":"#/components/parameters/Name"},{"$ref":"#/components/parameters/Q"},{"$ref":"#/components/parameters/Duty"},{"$ref":"#/components/parameters/ActivelyOnDuty"},{"in":"query","name":"sort","schema":{"enum":["id","name","city"],"type":"string","default":"id"},"description":"Sort order for the result set."},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"},{"$ref":"#/components/parameters/IfNoneMatch"}],"description":"All pharmacies (on-duty and regular) matching the given filters.","operationId":"searchPharmacies","x-sbx-credits":1}},"/v1/pharmacy/pharmacies/{id}":{"get":{"tags":["Pharmacies"],"summary":"Get a pharmacy by id","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Pharmacy"},"example":{"id":"10432","city":"ANKARA","name":"MERKEZ ECZANESİ","type":null,"phone":"+903124441122","onDuty":false,"address":"Kızılay Mah. Atatürk Bulvarı No:12","district":"ÇANKAYA","location":{"lat":39.9208,"lon":32.8541},"dutyEndsAt":null,"dutyStartsAt":null}}},"headers":{"ETag":{"$ref":"#/components/headers/ETag"}},"description":"The requested pharmacy."},"304":{"$ref":"#/components/responses/NotModified"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"502":{"$ref":"#/components/responses/BadGateway"},"503":{"$ref":"#/components/responses/ServiceUnavailable"},"504":{"$ref":"#/components/responses/GatewayTimeout"}},"parameters":[{"in":"path","name":"id","schema":{"type":"integer","minimum":1},"required":true,"description":"Positive integer pharmacy id."},{"$ref":"#/components/parameters/IfNoneMatch"}],"description":"A single pharmacy by its numeric id.","operationId":"getPharmacy","x-sbx-credits":1}},"/v1/pharmacy/pharmacies/nearby":{"get":{"tags":["Pharmacies"],"summary":"Find nearby pharmacies","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NearbyPharmacyPage"},"example":{"meta":{"center":{"lat":39.9208,"lon":32.8541},"radiusKm":5},"items":[{"id":"10432","city":"ANKARA","name":"MERKEZ ECZANESİ","type":null,"phone":"+903124441122","onDuty":true,"address":"Kızılay Mah. Atatürk Bulvarı No:12","district":"ÇANKAYA","location":{"lat":39.9208,"lon":32.8541},"distanceKm":0,"dutyEndsAt":"2026-09-22T08:00:00+03:00","dutyStartsAt":"2026-09-21T08:00:00+03:00"}],"total":1,"next_cursor":null}}},"headers":{"ETag":{"$ref":"#/components/headers/ETag"}},"description":"Pharmacies within the given radius, nearest first."},"304":{"$ref":"#/components/responses/NotModified"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"429":{"$ref":"#/components/responses/TooManyRequests"},"502":{"$ref":"#/components/responses/BadGateway"},"503":{"$ref":"#/components/responses/ServiceUnavailable"},"504":{"$ref":"#/components/responses/GatewayTimeout"}},"parameters":[{"in":"query","name":"lat","schema":{"type":"number","maximum":90,"minimum":-90},"required":true,"description":"Latitude of the search center (WGS84)."},{"in":"query","name":"lon","schema":{"type":"number","maximum":180,"minimum":-180},"required":true,"description":"Longitude of the search center (WGS84)."},{"in":"query","name":"radiusKm","schema":{"type":"number","default":5,"maximum":500,"minimum":0.1},"description":"Search radius in kilometers."},{"$ref":"#/components/parameters/City"},{"$ref":"#/components/parameters/District"},{"$ref":"#/components/parameters/Name"},{"$ref":"#/components/parameters/Q"},{"$ref":"#/components/parameters/Duty"},{"$ref":"#/components/parameters/ActivelyOnDuty"},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"},{"$ref":"#/components/parameters/IfNoneMatch"}],"description":"Pharmacies within a radius of a coordinate, nearest first and annotated with `distanceKm`. Pages through at most the 500 nearest: at 500 `next_cursor` is null.","operationId":"findNearbyPharmacies","x-sbx-credits":2}},"/v1/pharmacy/pharmacies/on-duty":{"get":{"tags":["Pharmacies"],"summary":"List on-duty pharmacies","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PharmacyPage"},"example":{"items":[{"id":"10432","city":"ANKARA","name":"MERKEZ ECZANESİ","type":null,"phone":"+903124441122","onDuty":true,"address":"Kızılay Mah. Atatürk Bulvarı No:12","district":"ÇANKAYA","location":{"lat":39.9208,"lon":32.8541},"dutyEndsAt":"2026-09-22T08:00:00+03:00","dutyStartsAt":"2026-09-21T08:00:00+03:00"},{"id":"20177","city":"ANKARA","name":"YENİ HAYAT ECZANESİ","type":null,"phone":"+903124559981","onDuty":true,"address":"Etlik Mah. Fatih Cad. No:45","district":"KEÇİÖREN","location":{"lat":39.9821,"lon":32.8672},"dutyEndsAt":"2026-09-22T08:00:00+03:00","dutyStartsAt":"2026-09-21T08:00:00+03:00"}],"total":213,"next_cursor":"eyJvIjoyLCJxIjoiM2E5ZjBjMWQifQ"}}},"headers":{"ETag":{"$ref":"#/components/headers/ETag"}},"description":"On-duty pharmacies matching the filters, sorted by city."},"304":{"$ref":"#/components/responses/NotModified"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"429":{"$ref":"#/components/responses/TooManyRequests"},"502":{"$ref":"#/components/responses/BadGateway"},"503":{"$ref":"#/components/responses/ServiceUnavailable"},"504":{"$ref":"#/components/responses/GatewayTimeout"}},"parameters":[{"$ref":"#/components/parameters/City"},{"$ref":"#/components/parameters/District"},{"$ref":"#/components/parameters/Name"},{"$ref":"#/components/parameters/Q"},{"$ref":"#/components/parameters/ActivelyOnDuty"},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"},{"$ref":"#/components/parameters/IfNoneMatch"}],"description":"Pharmacies currently on duty, sorted by city. Always returns on-duty pharmacies only — the shared `duty` filter does not apply here.","operationId":"listDutyPharmacies","x-sbx-credits":1}}},"openapi":"3.1.0","servers":[{"url":"https://api.servicebox.io"}],"security":[{"bearerAuth":[]},{"apiKeyQuery":[]}],"components":{"headers":{"ETag":{"schema":{"type":"string"},"description":"Opaque entity tag of this representation (ServiceBox's own, `W/\"…-t1\"`). Send it back in `If-None-Match` on the same URL to revalidate."}},"schemas":{"City":{"type":"object","required":["id","name","pharmacyCount","onDutyCount"],"properties":{"id":{"type":"string","description":"The city's name; what `city=` accepts."},"name":{"type":"string","description":"Province name, uppercase."},"onDutyCount":{"type":"integer","description":"Pharmacies on duty in this city."},"pharmacyCount":{"type":"integer","description":"Pharmacies in this city."}}},"Problem":{"type":"object","required":["type","title","status","detail"],"properties":{"type":{"type":"string","format":"uri","description":"A URI identifying the problem type."},"title":{"type":"string","description":"Short, human-readable summary of the problem type."},"detail":{"type":"string","description":"Human-readable explanation specific to this occurrence."},"status":{"type":"integer","description":"HTTP status code."},"upstream_status":{"type":"integer","description":"The upstream's HTTP status, on problems caused by an upstream answer."}},"description":"RFC 9457 problem detail."},"CityList":{"type":"object","required":["items","next_cursor","total"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/City"}},"total":{"type":"integer","description":"Number of cities."},"next_cursor":{"type":["string","null"],"description":"Always null: not paged."}}},"District":{"type":"object","required":["id","name","cityId","pharmacyCount","onDutyCount"],"properties":{"id":{"type":"string","description":"The district's name; what `district=` accepts."},"name":{"type":"string","description":"District name."},"cityId":{"type":"string","description":"The id of the district's city."},"onDutyCount":{"type":"integer","description":"Pharmacies on duty in this district."},"pharmacyCount":{"type":"integer","description":"Pharmacies in this district."}}},"Location":{"type":["object","null"],"required":["lat","lon"],"properties":{"lat":{"type":"number","description":"Latitude."},"lon":{"type":"number","description":"Longitude."}},"description":"WGS84 coordinates, or null when unknown."},"Pharmacy":{"type":"object","required":["id","name","city","district","address","phone","location","onDuty","dutyStartsAt","dutyEndsAt","type"],"properties":{"id":{"type":"string","description":"Pharmacy id."},"city":{"type":"string","description":"Province name, uppercase."},"name":{"type":"string","description":"Pharmacy name."},"type":{"type":["string","null"],"description":"Pharmacy type/category, when known."},"phone":{"type":["string","null"],"description":"Phone number in E.164 (`+90…`), or null when unknown."},"onDuty":{"type":"boolean","description":"Whether this pharmacy is on the duty roster; not necessarily active now (see `activelyOnDuty`)."},"address":{"type":["string","null"],"description":"Street address, or null when unknown."},"district":{"type":"string","description":"District name."},"location":{"$ref":"#/components/schemas/Location"},"dutyEndsAt":{"type":["string","null"],"format":"date-time","description":"End of the duty shift (ISO 8601 with offset), or null when not on duty."},"dutyStartsAt":{"type":["string","null"],"format":"date-time","description":"Start of the duty shift (ISO 8601 with offset), or null when not on duty."}}},"DistrictList":{"type":"object","required":["items","next_cursor","total"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/District"}},"total":{"type":"integer","description":"Number of districts."},"next_cursor":{"type":["string","null"],"description":"Always null: not paged."}}},"PharmacyPage":{"type":"object","required":["items","next_cursor","total"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Pharmacy"}},"total":{"type":"integer","description":"Number of pharmacies matching the filters."},"next_cursor":{"type":["string","null"],"description":"Pass it as `cursor` for the next page; null on the last page."}}},"NearbyPharmacy":{"allOf":[{"$ref":"#/components/schemas/Pharmacy"},{"type":"object","required":["distanceKm"],"properties":{"distanceKm":{"type":"number","description":"Distance from the search center, in kilometers."}}}]},"NearbyPharmacyPage":{"type":"object","required":["items","next_cursor","total","meta"],"properties":{"meta":{"type":"object","required":["center","radiusKm"],"properties":{"center":{"type":"object","allOf":[{"$ref":"#/components/schemas/Location"}],"description":"The search center."},"radiusKm":{"type":"number","description":"The search radius, in kilometers."}}},"items":{"type":"array","items":{"$ref":"#/components/schemas/NearbyPharmacy"}},"total":{"type":"integer","description":"Number of pharmacies within the radius."},"next_cursor":{"type":["string","null"],"description":"Pass it as `cursor` for the next page; null on the last page, and at the 500 nearest."}}}},"responses":{"NotFound":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://servicebox.io/problems/not_found","title":"Not Found","detail":"No pharmacy with id 999999999","status":404,"upstream_status":404}}},"description":"No pharmacy with that id."},"BadGateway":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"examples":{"upstream_auth":{"value":{"type":"https://servicebox.io/problems/upstream_auth","title":"Bad Gateway","detail":"The upstream refused ServiceBox's own credential; this is not about your API key. Retry later.","status":502,"upstream_status":401}},"upstream_error":{"value":{"type":"https://servicebox.io/problems/upstream_error","title":"Bad Gateway","detail":"The upstream failed (500)","status":502,"upstream_status":500}},"upstream_shape":{"value":{"type":"https://servicebox.io/problems/upstream_shape","title":"Bad Gateway","detail":"The upstream's answer did not match its documented shape; you were not charged. Retry later.","status":502}}}}},"description":"`upstream_error`: the upstream data source failed. `upstream_auth`: the upstream refused ServiceBox's own credential; not your key. `upstream_shape`: the upstream's answer did not match its documented shape; not charged."},"BadRequest":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://servicebox.io/problems/bad_request","title":"Bad Request","detail":"`limit` must be an integer from 1 to 200","status":400}}},"description":"Invalid query parameter, including a bad `limit` or `cursor`, or an `offset` (page with `cursor`). Not charged when the gateway refuses it."},"NotModified":{"headers":{"ETag":{"$ref":"#/components/headers/ETag"}},"description":"The data has not changed since the ETag in `If-None-Match`. No body."},"Unauthorized":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://servicebox.io/problems/unauthorized","title":"Unauthorized","detail":"Missing or invalid API key/bearer token","status":401}}},"description":"Missing or invalid credentials."},"GatewayTimeout":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://servicebox.io/problems/upstream_timeout","title":"Gateway Timeout","detail":"Upstream request timed out","status":504}}},"description":"The upstream data source timed out."},"PaymentRequired":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://servicebox.io/problems/payment_required","title":"Payment Required","detail":"Insufficient credits for this request","status":402}}},"description":"Insufficient credits."},"TooManyRequests":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://servicebox.io/problems/rate_limited","title":"Too Many Requests","detail":"Rate limit exceeded, retry after backing off","status":429}}},"description":"Rate limit exceeded."},"ServiceUnavailable":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://servicebox.io/problems/service_unavailable","title":"Service Unavailable","detail":"Dataset is not ready yet","status":503}}},"description":"The dataset is not ready yet."}},"parameters":{"Q":{"in":"query","name":"q","schema":{"type":"string","maxLength":120},"description":"Alias for `name`."},"City":{"in":"query","name":"city","schema":{"type":"string","maxLength":120},"description":"Filter by city name (case- and accent-insensitive). Up to 120 characters."},"Duty":{"in":"query","name":"duty","schema":{"type":"boolean"},"description":"Filter to on-duty (`true`) or off-duty (`false`) pharmacies. Omit to return both."},"Name":{"in":"query","name":"name","schema":{"type":"string","maxLength":120},"description":"Turkish-aware substring match on pharmacy name. Up to 120 characters. `q` is an alias for this parameter."},"Limit":{"in":"query","name":"limit","schema":{"type":"integer","default":50,"maximum":200,"minimum":1},"description":"Maximum number of items on this page."},"Cursor":{"in":"query","name":"cursor","schema":{"type":"string"},"description":"Opaque; the `next_cursor` of the previous page. Keep every other parameter unchanged, or the call is a 400."},"District":{"in":"query","name":"district","schema":{"type":"string","maxLength":120},"description":"Filter by district name (case- and accent-insensitive). Up to 120 characters."},"IfNoneMatch":{"in":"header","name":"If-None-Match","schema":{"type":"string"},"description":"ETag from a previous response to the same URL. When it still matches, the answer is 304 with no body."},"ActivelyOnDuty":{"in":"query","name":"activelyOnDuty","schema":{"type":"boolean"},"description":"`true` = duty shift active now (Europe/Istanbul, start inclusive, end exclusive); `false` = not active now. Such answers carry `Cache-Control: no-store`, no `ETag`, and are never answered `304`. `false` does not mean closed."}},"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"},"apiKeyQuery":{"in":"query","name":"apikey","type":"apiKey"}}}}