Przejdź do treści
WezwijDoktora
wezwijdoktora

API

openapi.json

Dokumentacja

WezwijDoktora Partner API

Integracja serwer–serwer: zgłoszenie (Intake), nie zlecenie. Poniżej przebieg integracji, przykłady wywołań, kody odpowiedzi i struktury JSON.

Bezpieczeństwo

WezwijDoktora Partner API jest wyłącznie serwer–serwer. CORS jest wyłączony, a ta dokumentacja nie wykonuje zapytań w przeglądarce. Wywołuj API ze swojego backendu — nie wklejaj klucza do narzędzi online.

Jak to działa

WezwijDoktora Partner API to interfejs HTTP do integracji serwer–serwer. Wywołujesz je z własnego backendu. Integracja w przeglądarce pacjenta i widget w iframe nie są obsługiwane — CORS jest wyłączony.

POST /v1/intakes nie składa zlecenia i nie zakłada konta pacjenta. Tworzy zgłoszenie (Intake) do oddzwonienia. Operator WezwijDoktora kontaktuje się z pacjentem, uzupełnia dane i dopiero wtedy składa zamówienie — według tych samych zasad co zlecenie złożone ręcznie.

Typowy przebieg: 1) klucz API, 2) GET /v1/me, 3) POST /v1/coverage/lookup dla adresu, 4) gdy miejsce jest obsługiwane — POST /v1/intakes z tym samym miejscem i slugiem grupy, 5) GET /v1/intakes/{id} do statusu końcowego: converted (z publicznym numerem zlecenia) albo discarded (zgłoszenie odrzucone, bez order).

  • Bazowy URL: https://staging-api.wezwijdoktora.pl.
  • Wersja w ścieżce: /v1. JSON, UTF-8. Maksymalny rozmiar ciała: 16 KB.
  • Identyfikatory publiczne: slug grupy (np. lekarz-dla-doroslych), slug regionu (GET /v1/regions), TERC gminy (7 znaków), powiat = pierwsze 4 znaki TERC. API nie zwraca UUID regionu, usługi, specjalisty ani zlecenia.
  • Ta dokumentacja nie wykonuje zapytań w przeglądarce. Klucza nie wklejaj do narzędzi online — wołaj API ze swojego serwera.
  • Maszynowy kontrakt: GET /v1/openapi.json.

Szybki start

Ustaw BASE i TOKEN. TOKEN to pełny klucz API (format wd_<8 hex>_<secret>), pokazywany wyłącznie przy wydaniu. Nie zapisuj go w logach.

Przykłady używają curl -sS (cisza, błędy sieci). jq jest opcjonalny. Gdzie wstawiać slug, identyfikator, nagłówki i pola JSON — sekcja Parametry wywołań.

curl
export BASE=https://staging-api.wezwijdoktora.pl
export TOKEN='wd_ab12cd34_…'

# Stan usługi (bez klucza)
curl -sS "$BASE/health"

# Tożsamość
curl -sS "$BASE/v1/me" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Accept: application/json"

# Coverage punktu (Warszawa)
curl -sS "$BASE/v1/coverage/lookup" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{"coordinates":{"lat":52.2297,"lng":21.0122}}'

# Intake — Idempotency-Key jest wymagany
curl -sS -D - "$BASE/v1/intakes" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: lead-99821" \
  -H "Accept: application/json" \
  -d '{"serviceGroupSlug":"lekarz-dla-dzieci","location":{"coordinates":{"lat":50.0614,"lng":19.9366},"address":"Kraków"},"externalRef":"lead-99821"}'

Parametry wywołań

Parametry v1 trafiają do fragmentu URL (ścieżka), nagłówka HTTP albo ciała JSON. Jedyny parametr query string w v1 to opcjonalny groupSlug w GET /v1/catalog/{regionSlug}. Klucza API nigdy nie umieszczaj w adresie.

W przykładach zamieniasz tylko wartości (slug, identyfikator, współrzędne, Idempotency-Key). Nazwy pól muszą być dokładnie takie jak w kontrakcie — nieznane pola w JSON kończą się 400 VALIDATION.

  • GET bez ciała. Nie dodawaj ciała do /v1/me, /v1/coverage/areas, katalogu ani GET /v1/intakes/{id}.
  • POST: obowiązkowy Content-Type: application/json. lat i lng to liczby JSON (52.2297), nie stringi ("52.2297").
  • Każdy nagłówek to osobne -H. Idempotency-Key jest nagłówkiem, nie polem JSON.
  • lookup i intake: w ciele musi być coordinates albo googlePlaceId (albo oba). address jest etykietą, nie geokoderem.
Gdzie wstawiać parametry
W wywołaniuCo to jestW v1
w URL zamiast {slug} / {id}Parametr ścieżkiGET /v1/service-groups/{slug}, GET /v1/intakes/{id}
-H 'Nazwa: wartość'NagłówekAuthorization, Content-Type, Accept, Idempotency-Key, opcjonalnie X-Request-Id
-d '{ ... }' albo -d @plik.jsonCiało JSONTylko POST /v1/coverage/lookup i POST /v1/intakes
?groupSlug=lekarz-dla-doroslychQuery stringTylko opcjonalny filtr katalogu; query string nie zastępuje parametrów ścieżki ani ciała POST
curl
export BASE=https://staging-api.wezwijdoktora.pl
export TOKEN='wd_ab12cd34_…'

# 1) Ścieżka — wartość w URL (nie po ?)
export SLUG=lekarz-dla-dzieci
curl -sS "$BASE/v1/service-groups/$SLUG" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Accept: application/json"

export INTAKE_ID=7c2e4b10-9a1c-4f2d-8e11-0b3a6c8d9e01
curl -sS "$BASE/v1/intakes/$INTAKE_ID" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Accept: application/json"

# 2) Nagłówki — każdy parametr to osobne -H
curl -sS "$BASE/v1/me" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Accept: application/json" \
  -H "X-Request-Id: partner-call-001"

# 3) Ciało inline — pola JSON to parametry żądania
curl -sS "$BASE/v1/coverage/lookup" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{"coordinates":{"lat":52.2297,"lng":21.0122},"address":"Warszawa"}'

# 4) Ciało z pliku (wygodne przy wielu polach)
# plik lookup.json: {"coordinates":{"lat":50.0614,"lng":19.9366},"address":"Kraków"}
curl -sS "$BASE/v1/coverage/lookup" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d @lookup.json

# 5) Heredoc — ten sam JSON, bez pliku
curl -sS "$BASE/v1/intakes" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: lead-99821" \
  -H "Accept: application/json" \
  -d @- <<'EOF'
{
  "externalRef": "lead-99821",
  "serviceGroupSlug": "lekarz-dla-dzieci",
  "location": {
    "address": "ul. Przykładowa 2, Kraków",
    "coordinates": { "lat": 50.0614, "lng": 19.9366 }
  },
  "caller": { "phone": "+48500100200", "firstName": "Anna" }
}
EOF
Python (requests)
import os
import requests

base = os.environ["BASE"]  # https://staging-api.wezwijdoktora.pl
token = os.environ["TOKEN"]
headers = {
    "Authorization": f"Bearer {token}",
    "Accept": "application/json",
}

# Ciało: słownik → JSON (lat/lng jako float, nie str)
lookup = requests.post(
    f"{base}/v1/coverage/lookup",
    headers=headers,
    json={"coordinates": {"lat": 52.2297, "lng": 21.0122}, "address": "Warszawa"},
    timeout=15,
)
print(lookup.status_code, lookup.json())

# Ścieżka: w f-stringu, nie w params=
slug = "lekarz-dla-dzieci"
group = requests.get(f"{base}/v1/service-groups/{slug}", headers=headers, timeout=15)
print(group.status_code, group.json())
Node (fetch)
const base = process.env.BASE; // https://staging-api.wezwijdoktora.pl
const token = process.env.TOKEN;
const headers = {
  Authorization: `Bearer ${token}`,
  Accept: "application/json",
};

const lookup = await fetch(`${base}/v1/coverage/lookup`, {
  method: "POST",
  headers: { ...headers, "Content-Type": "application/json" },
  body: JSON.stringify({
    coordinates: { lat: 52.2297, lng: 21.0122 },
    address: "Warszawa",
  }),
});
console.log(lookup.status, await lookup.json());

const slug = "lekarz-dla-dzieci";
const group = await fetch(`${base}/v1/service-groups/${slug}`, { headers });
console.log(group.status, await group.json());

Autoryzacja

Wszystkie ścieżki /v1/* poza /v1/openapi.json wymagają nagłówka Authorization: Bearer. GET /health i GET /docs są publiczne.

Klucz ma postać wd_ + 8 znaków szesnastkowych + _ + secret (base64url). Środowisko (test albo live) nie jest częścią stringu — jest powiązane z kluczem. Klucz testowy działa tylko w środowisku testowym, klucz produkcyjny — tylko w produkcyjnym.

Nieprawidłowy kształt, nieznany lub unieważniony klucz, nieaktywny partner albo klucz z innego środowiska zwracają zawsze 401 z tym samym komunikatem. Odpowiedź nie zdradza, która weryfikacja nie przeszła.

  • Nagłówek Authorization: maksymalnie 256 znaków (dłuższy = 401).
  • Tożsamość partnera wynika wyłącznie z klucza, nigdy z ciała żądania.
  • Ważny klucz daje dostęp do coverage, katalogu i zgłoszeń. v1 nie używa osobnych uprawnień (scopes).
curl
curl -sS https://staging-api.wezwijdoktora.pl/v1/me \
  -H "Authorization: Bearer wd_<prefix8>_<secret>" \
  -H "Accept: application/json"

Błędy i kody

Każdy błąd 4xx/5xx (poza /health) ma ten sam kształt. Pole details jest opcjonalne (np. gminaTerc przy OUT_OF_COVERAGE, retryAfterSeconds przy 429).

Nagłówek X-Request-Id jest na każdej odpowiedzi z /v1. Możesz go przysłać (A–Z a–z 0–9 . _ : -, max 128 znaków); w przeciwnym razie serwer wygeneruje UUID.

Kody error.code ↔ HTTP
HTTPerror.codeKiedy
400VALIDATIONNieprawidłowe ciało lub nagłówek: brak Content-Type: application/json, brak miejsca, zły telefon, zły Idempotency-Key, punkt poza Polską, nieznane pola, nieprawidłowy JSON
401UNAUTHORIZEDBrak lub nieprawidłowy Bearer, unieważniony klucz, nieaktywny partner, klucz z innego środowiska
403FORBIDDENZarezerwowane — v1 nie zwraca
404NO_GMINAPunkt nie należy do żadnej gminy
404NOT_FOUNDNieznane zgłoszenie (także cudze — zawsze 404, nigdy 403), nieznany slug grupy albo nieznany slug regionu
409IDEMPOTENCY_CONFLICTTen sam Idempotency-Key lub externalRef z innym ciałem
413PAYLOAD_TOO_LARGECiało większe niż 16 384 bajtów
422OUT_OF_COVERAGEGmina jest, ale usługa lub cena niedostępna w tym punkcie
422UNKNOWN_SERVICE_GROUPSlug nie jest opublikowaną grupą wizyt domowych
429RATE_LIMITPrzekroczony limit. Retry-After oraz details.retryAfterSeconds
500INTERNALNieobsłużony błąd serwera — bez wycieku szczegółów
503MISCONFIGUREDUsługa chwilowo niedostępna z powodu błędu konfiguracji
503GOOGLE_UNAVAILABLEgooglePlaceId, a geokodowanie Google jest niedostępne
Przykład błędu (każdy 4xx/5xx z /v1)
{
  "error": {
    "code": "VALIDATION",
    "message": "Podaj coordinates albo googlePlaceId.",
    "details": {}
  }
}

Limity i nagłówki

Limity są liczone w oknie jednej minuty, osobno na partnera. Nieudane uwierzytelnienie (401) też zużywa limit — wielokrotne próby z nieprawidłowym kluczem nie są darmowe.

Adres IP bierzemy z zaufanych nagłówków proxy. Nagłówka X-Forwarded-For od klienta nie honorujemy.

  • 429: error.code=RATE_LIMIT, komunikat „Limit zapytań został przekroczony.” (albo „Zbyt wiele prób.” przy nieudanym Bearer), details.retryAfterSeconds, nagłówek Retry-After.
  • X-Request-Id na każdej odpowiedzi /v1. Możesz przysłać własny (A–Z a–z 0–9 . _ : -, max 128 znaków).
  • Accept: application/json. POST: Content-Type: application/json.
  • Idempotency-Key tylko na POST /v1/intakes (wymagany).
Limity
ZakresLimit / minUwagi
Partner (globalny)rateLimitPerMinute (domyślnie 60)Aktualna wartość w GET /v1/me
POST /v1/intakes10Niezależnie od limitu globalnego
GET /v1/coverage/areas10Niezależnie od limitu globalnego
GET /v1/catalog/{regionSlug}10Niezależnie od limitu globalnego
Nieudane uwierzytelnienie20Na adres IP

Lokalizacja

Dla lookup i intake wymagane jest coordinates albo googlePlaceId (co najmniej jedno). Pole address to etykieta dla operatora — nie geokodujemy gołego tekstu.

Gdy podasz googlePlaceId, współrzędne pochodzą z Google Places i zastępują coordinates z żądania. Jeśli geokodowanie jest niedostępne, żądanie kończy się 503 GOOGLE_UNAVAILABLE.

Same coordinates (bez placeId) są akceptowane w granicach Polski: szerokość 49.0–55.1, długość 14.0–24.3. Odrzucamy nieprawidłowe liczby i punkt (0, 0).

  • 404 NO_GMINA: punkt w Polsce, ale bez rozpoznanej gminy.
  • 200 lookup z serviceable: false: gmina jest, brak dostępnych wizyt domowych — pokaż użytkownikowi, że nie obsługujemy tego adresu.
  • POST /v1/intakes przy braku coverage → 422 OUT_OF_COVERAGE (nie 200).

Idempotencja

POST /v1/intakes wymaga nagłówka Idempotency-Key: 8–128 znaków z alfabetu A–Z a–z 0–9 . _ : - (na przykład UUID albo identyfikator leada).

Ten sam klucz i to samo ciało zwraca istniejące zgłoszenie (200) — aktualny stan, nawet jeśli status zdążył się zmienić na converted. Ten sam klucz i inne ciało — 409 IDEMPOTENCY_CONFLICT.

externalRef jest unikalny per partner. Ten sam ref i inne ciało — 409. Ponowienie żądania nie tworzy drugiego zgłoszenia.

Metody

Każda metoda ma opis, przykład wywołania, strukturę sukcesu i kody błędów z ciałem JSON.

GET

/health

Publiczne

Stan usługi

Czy usługa odpowiada. Bez uwierzytelnienia i bez sprawdzania bazy. Nadaje się do monitorowania dostępności.

Nie używaj tego endpointu do sprawdzania klucza ani coverage.

Wywołanie

curl
curl -sS https://staging-api.wezwijdoktora.pl/health

Odpowiedzi sukcesu

200Usługa odpowiada

Jedyny sukces. Brak informacji o bazie.

JSON odpowiedzi
{
  "status": "ok",
  "app": "api"
}
  • Gdy usługa nie działa, połączenie kończy się błędem sieci albo 502 od proxy — bez JSON-owego błędu Partner API.
GET

/v1/openapi.json

Publiczne

Specyfikacja OpenAPI 3.1

Maszynowy kontrakt OpenAPI 3.1. Ta strona HTML jest pełniejsza — specyfikacja opisuje ścieżki i kody odpowiedzi.

Wywołanie

curl
curl -sS https://staging-api.wezwijdoktora.pl/v1/openapi.json

Odpowiedzi sukcesu

200Dokument OpenAPI

Obiekt openapi: 3.1.0, paths, securitySchemes.partnerBearer.

JSON odpowiedzi
{
  "openapi": "3.1.0",
  "info": { "title": "WezwijDoktora Partner API", "version": "1.0.0" },
  "paths": { "/v1/me": { "get": { "summary": "Tożsamość partnera" } } }
}
GET

/v1/me

Bearer

Tożsamość partnera

Zwraca partnera powiązanego z kluczem: nazwę, środowisko, prefix klucza, numer do wyświetlenia pacjentowi i aktualny limit.

contactPhone to numer, który WezwijDoktora ustawia partnerowi — pokaż go przyciskiem Zadzwoń. Na starcie integracji sprawdź też environment i rateLimitPerMinute, zanim wołasz coverage.

Nagłówki

PoleTypOpis
AuthorizationwymaganeBearer wd_…Pełny klucz API.

Wywołanie

curl
curl -sS https://staging-api.wezwijdoktora.pl/v1/me \
  -H "Authorization: Bearer $TOKEN" \
  -H "Accept: application/json"

Odpowiedzi sukcesu

200Partner

keyPrefix to publiczny przedrostek (wd_ + 8 hex), nie secret. contactPhone może być null, dopóki numer nie zostanie przypisany.

JSON odpowiedzi
{
  "slug": "przyklad-ubezpieczyciel",
  "name": "Przykład Ubezpieczyciel",
  "environment": "live",
  "keyPrefix": "wd_ab12cd34",
  "contactPhone": "+48585005555",
  "rateLimitPerMinute": 60
}

Błędy

401UNAUTHORIZED

Brak tokenu, nieprawidłowy lub unieważniony klucz, nieaktywny partner albo klucz z innego środowiska.

JSON błędu
{
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Nieprawidłowy token."
  }
}
429RATE_LIMIT

Przekroczony limit w oknie minuty (w tym nieudane uwierzytelnienie).

JSON błędu
{
  "error": {
    "code": "RATE_LIMIT",
    "message": "Limit zapytań został przekroczony.",
    "details": { "retryAfterSeconds": 42 }
  }
}
503MISCONFIGURED

Usługa chwilowo niedostępna z powodu błędu konfiguracji.

JSON błędu
{
  "error": {
    "code": "MISCONFIGURED",
    "message": "Konfiguracja Partner API jest niekompletna."
  }
}
500INTERNAL

Nieobsłużony wyjątek — bez wycieku szczegółów.

JSON błędu
{
  "error": {
    "code": "INTERNAL",
    "message": "Nie udało się obsłużyć żądania."
  }
}
GET

/v1/coverage/areas

Bearer

Mapa gmin w coverage

Gminy, w których realizujemy wizyty domowe (co najmniej jedna grupa z ceną).

Centroid (lat/lng) każdej gminy — bez geometrii. Wynik jest cache'owany do 5 minut. Limit 10 żądań na minutę na partnera, niezależnie od limitu globalnego.

Wywołanie

curl
curl -sS https://staging-api.wezwijdoktora.pl/v1/coverage/areas \
  -H "Authorization: Bearer $TOKEN" \
  -H "Accept: application/json"

Odpowiedzi sukcesu

200Lista gmin

Bez UUID regionu. powiatTerc to pierwsze 4 znaki TERC. v1 nie zwraca osobnej listy powiatów.

JSON odpowiedzi
{
  "generatedAt": "2026-08-29T12:00:00.000Z",
  "gminas": [
    {
      "terc": "1465011",
      "name": "Warszawa",
      "powiatTerc": "1465",
      "lat": 52.2297,
      "lng": 21.0122,
      "serviceGroupSlugs": ["lekarz-dla-doroslych", "lekarz-dla-dzieci"]
    }
  ]
}

Błędy

401UNAUTHORIZED

Brak tokenu, nieprawidłowy lub unieważniony klucz, nieaktywny partner albo klucz z innego środowiska.

JSON błędu
{
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Nieprawidłowy token."
  }
}
429RATE_LIMIT

Przekroczony limit w oknie minuty (w tym nieudane uwierzytelnienie).

JSON błędu
{
  "error": {
    "code": "RATE_LIMIT",
    "message": "Limit zapytań został przekroczony.",
    "details": { "retryAfterSeconds": 42 }
  }
}
503MISCONFIGURED

Usługa chwilowo niedostępna z powodu błędu konfiguracji.

JSON błędu
{
  "error": {
    "code": "MISCONFIGURED",
    "message": "Konfiguracja Partner API jest niekompletna."
  }
}
500INTERNAL

Nieobsłużony wyjątek — bez wycieku szczegółów.

JSON błędu
{
  "error": {
    "code": "INTERNAL",
    "message": "Nie udało się obsłużyć żądania."
  }
}
  • Gminy bez dostępnej ceny wizyty domowej są pomijane.
POST

/v1/coverage/lookup

Bearer

Coverage punktu

Czy w tym miejscu realizujemy wizyty i jakie grupy oraz ceny obowiązują. Nie tworzy zgłoszenia.

W odpowiedzi nie ma regionId ani UUID usług. Pole address z ciała wraca jako location.formattedAddress (etykieta), nie jako wynik geokodera.

Nagłówki

PoleTypOpis
Content-Typewymaganeapplication/jsonWymagane przy ciele.

Ciało żądania

PoleTypOpis
coordinates.lat / lngnumberWGS84. Wymagane, jeśli nie ma googlePlaceId. Liczby skończone, w granicach Polski.
googlePlaceIdstringPlace ID Google. Gdy podane, współrzędne pochodzą z Google. Maks. 256 znaków.
addressstringOpcjonalna etykieta (maks. 500 znaków). Nie służy do ustalenia gminy.

Przykład ciała

JSON
{
  "coordinates": { "lat": 52.2297, "lng": 21.0122 },
  "address": "ul. Marszałkowska 1, Warszawa"
}

Wywołanie

curl
curl -sS https://staging-api.wezwijdoktora.pl/v1/coverage/lookup \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{"coordinates":{"lat":52.2297,"lng":21.0122},"address":"Warszawa"}'

# Albo Place ID Google
curl -sS https://staging-api.wezwijdoktora.pl/v1/coverage/lookup \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"googlePlaceId":"ChIJ0RhONcBEGkcR8HdfDLOxwDI"}'

Odpowiedzi sukcesu

200Obsługiwane

serviceable=true, gdy choć jedna grupa ma serviceable i priceAvailable. zone: basic | extended | none.

JSON odpowiedzi
{
  "location": {
    "gminaTerc": "1465011",
    "gminaName": "Warszawa",
    "powiatTerc": "1465",
    "voivodeshipTerc": "14",
    "zone": "basic",
    "formattedAddress": "Warszawa",
    "coordinates": { "lat": 52.2297, "lng": 21.0122 }
  },
  "serviceable": true,
  "services": [
    {
      "serviceGroupSlug": "lekarz-dla-doroslych",
      "name": "Lekarz dla dorosłych",
      "serviceable": true,
      "priceAvailable": true,
      "pricesPln": {
        "zone1Weekday": 350,
        "zone1WeekendHoliday": 450,
        "zone2Weekday": 400,
        "zone2WeekendHoliday": 500
      }
    }
  ]
}
200Gmina jest, usług brak

To nie jest błąd HTTP. Pokaż użytkownikowi, że nie obsługujemy tego adresu.

JSON odpowiedzi
{
  "location": {
    "gminaTerc": "1465011",
    "gminaName": "Warszawa",
    "powiatTerc": "1465",
    "voivodeshipTerc": "14",
    "zone": "none",
    "formattedAddress": null,
    "coordinates": { "lat": 52.2297, "lng": 21.0122 }
  },
  "serviceable": false,
  "services": []
}

Błędy

400VALIDATION

Brak Content-Type: application/json, brak coordinates i googlePlaceId, nieznane pola, NaN, punkt poza Polską albo nieprawidłowy placeId.

413PAYLOAD_TOO_LARGE

Ciało większe niż 16 384 bajty UTF-8.

404NO_GMINA

Punkt nie należy do żadnej gminy.

JSON błędu
{
  "error": {
    "code": "NO_GMINA",
    "message": "Nie udało się rozpoznać gminy dla tej lokalizacji."
  }
}
503GOOGLE_UNAVAILABLE

googlePlaceId, a geokodowanie Google jest niedostępne.

401UNAUTHORIZED

Brak tokenu, nieprawidłowy lub unieważniony klucz, nieaktywny partner albo klucz z innego środowiska.

JSON błędu
{
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Nieprawidłowy token."
  }
}
429RATE_LIMIT

Przekroczony limit w oknie minuty (w tym nieudane uwierzytelnienie).

JSON błędu
{
  "error": {
    "code": "RATE_LIMIT",
    "message": "Limit zapytań został przekroczony.",
    "details": { "retryAfterSeconds": 42 }
  }
}
503MISCONFIGURED

Usługa chwilowo niedostępna z powodu błędu konfiguracji.

JSON błędu
{
  "error": {
    "code": "MISCONFIGURED",
    "message": "Konfiguracja Partner API jest niekompletna."
  }
}
500INTERNAL

Nieobsłużony wyjątek — bez wycieku szczegółów.

JSON błędu
{
  "error": {
    "code": "INTERNAL",
    "message": "Nie udało się obsłużyć żądania."
  }
}
GET

/v1/service-groups

Bearer

Katalog grup

Opublikowane grupy wizyt domowych. Teleporady nie wchodzą w v1.

Bez UUID grupy. specialistRole: doctor, nurse albo null.

Wywołanie

curl
curl -sS https://staging-api.wezwijdoktora.pl/v1/service-groups \
  -H "Authorization: Bearer $TOKEN" \
  -H "Accept: application/json"

Odpowiedzi sukcesu

200Tablica grup

Kolejność jak w cenniku.

JSON odpowiedzi
[
  {
    "slug": "lekarz-dla-doroslych",
    "name": "Lekarz dla dorosłych",
    "patientCohort": "adult",
    "specialistRole": "doctor"
  },
  {
    "slug": "lekarz-dla-dzieci",
    "name": "Lekarz dla dzieci",
    "patientCohort": "child",
    "specialistRole": "doctor"
  }
]

Błędy

401UNAUTHORIZED

Brak tokenu, nieprawidłowy lub unieważniony klucz, nieaktywny partner albo klucz z innego środowiska.

JSON błędu
{
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Nieprawidłowy token."
  }
}
429RATE_LIMIT

Przekroczony limit w oknie minuty (w tym nieudane uwierzytelnienie).

JSON błędu
{
  "error": {
    "code": "RATE_LIMIT",
    "message": "Limit zapytań został przekroczony.",
    "details": { "retryAfterSeconds": 42 }
  }
}
503MISCONFIGURED

Usługa chwilowo niedostępna z powodu błędu konfiguracji.

JSON błędu
{
  "error": {
    "code": "MISCONFIGURED",
    "message": "Konfiguracja Partner API jest niekompletna."
  }
}
500INTERNAL

Nieobsłużony wyjątek — bez wycieku szczegółów.

JSON błędu
{
  "error": {
    "code": "INTERNAL",
    "message": "Nie udało się obsłużyć żądania."
  }
}
GET

/v1/service-groups/{slug}

Bearer

Grupa i usługi

Szczegóły jednej grupy oraz jej usługi. Nadal same slugi, bez UUID.

Nieznany slug, teleporada albo grupa ukryta → 404 (nie 403).

Parametry ścieżki

PoleTypOpis
slugwymaganestringSlug z GET /v1/service-groups, np. lekarz-dla-dzieci.

Wywołanie

curl
curl -sS https://staging-api.wezwijdoktora.pl/v1/service-groups/lekarz-dla-dzieci \
  -H "Authorization: Bearer $TOKEN" \
  -H "Accept: application/json"

Odpowiedzi sukcesu

200Grupa

kind to typ pozycji cennika (wizyta / dodatek itd.).

JSON odpowiedzi
{
  "slug": "lekarz-dla-dzieci",
  "name": "Lekarz dla dzieci",
  "patientCohort": "child",
  "specialistRole": "doctor",
  "services": [
    { "slug": "wizyta-lekarza-dzieci", "name": "Wizyta lekarza", "kind": "visit" }
  ]
}

Błędy

404NOT_FOUND

Brak grupy wizyt domowych o tym slugu.

JSON błędu
{
  "error": {
    "code": "NOT_FOUND",
    "message": "Nie znaleziono grupy usług."
  }
}
401UNAUTHORIZED

Brak tokenu, nieprawidłowy lub unieważniony klucz, nieaktywny partner albo klucz z innego środowiska.

JSON błędu
{
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Nieprawidłowy token."
  }
}
429RATE_LIMIT

Przekroczony limit w oknie minuty (w tym nieudane uwierzytelnienie).

JSON błędu
{
  "error": {
    "code": "RATE_LIMIT",
    "message": "Limit zapytań został przekroczony.",
    "details": { "retryAfterSeconds": 42 }
  }
}
503MISCONFIGURED

Usługa chwilowo niedostępna z powodu błędu konfiguracji.

JSON błędu
{
  "error": {
    "code": "MISCONFIGURED",
    "message": "Konfiguracja Partner API jest niekompletna."
  }
}
500INTERNAL

Nieobsłużony wyjątek — bez wycieku szczegółów.

JSON błędu
{
  "error": {
    "code": "INTERNAL",
    "message": "Nie udało się obsłużyć żądania."
  }
}
GET

/v1/regions

Bearer

Regiony cennika

Lista regionów, w których jest opublikowana cena wizyty domowej.

Identyfikator publiczny to slug, nie UUID. Lookup nadal nie zwraca regionId.

Wywołanie

curl
curl -sS https://staging-api.wezwijdoktora.pl/v1/regions \
  -H "Authorization: Bearer $TOKEN" \
  -H "Accept: application/json"

Odpowiedzi sukcesu

200Lista regionów

Kolejność alfabetyczna po nazwie.

JSON odpowiedzi
{
  "regions": [
    { "slug": "trojmiasto", "name": "Trójmiasto" },
    { "slug": "warszawa", "name": "Warszawa" }
  ]
}

Błędy

401UNAUTHORIZED

Brak tokenu, nieprawidłowy lub unieważniony klucz, nieaktywny partner albo klucz z innego środowiska.

JSON błędu
{
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Nieprawidłowy token."
  }
}
429RATE_LIMIT

Przekroczony limit w oknie minuty (w tym nieudane uwierzytelnienie).

JSON błędu
{
  "error": {
    "code": "RATE_LIMIT",
    "message": "Limit zapytań został przekroczony.",
    "details": { "retryAfterSeconds": 42 }
  }
}
503MISCONFIGURED

Usługa chwilowo niedostępna z powodu błędu konfiguracji.

JSON błędu
{
  "error": {
    "code": "MISCONFIGURED",
    "message": "Konfiguracja Partner API jest niekompletna."
  }
}
500INTERNAL

Nieobsłużony wyjątek — bez wycieku szczegółów.

JSON błędu
{
  "error": {
    "code": "INTERNAL",
    "message": "Nie udało się obsłużyć żądania."
  }
}
GET

/v1/catalog/{regionSlug}

Bearer

Katalog usług i cen w regionie

Specjalizacje (grupy wizyt domowych) z usługami i macierzą cen: strefa 1/2 × dzień / weekend i święta.

Opcjonalny groupSlug zawęża wynik do jednej grupy — najpierw GET /v1/service-groups, potem region i ten katalog.

serviceable odnosi się do reprezentatywnej gminy rdzeniowej regionu (czy jest tam aktywny specjalista tej roli). Ceny są per usługa w regionie. Bez UUID.

Poprawny składniowo, ale nieznany groupSlug zwraca 200 z pustym groups. Region bez przypisanej gminy także zwraca 200 z pustym groups. Nieznany regionSlug zwraca 404.

Parametry ścieżki

PoleTypOpis
regionSlugwymaganestringSlug z GET /v1/regions, np. trojmiasto.

Parametry zapytania

PoleTypOpis
groupSlugstringSlug grupy z GET /v1/service-groups. Gdy podany, groups ma co najwyżej jeden element.

Wywołanie

curl
curl -sS "https://staging-api.wezwijdoktora.pl/v1/catalog/trojmiasto?groupSlug=lekarz-dla-doroslych" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Accept: application/json"

Odpowiedzi sukcesu

200Katalog

pricesPln jest null, gdy usługa nie ma pełnej macierzy stref.

JSON odpowiedzi
{
  "region": { "slug": "trojmiasto", "name": "Trójmiasto" },
  "groups": [
    {
      "slug": "lekarz-dla-doroslych",
      "name": "Lekarz dla dorosłych",
      "patientCohort": "adult",
      "specialistRole": "doctor",
      "services": [
        {
          "slug": "wizyta-lekarza-dorosli",
          "name": "Wizyta lekarza",
          "kind": "visit",
          "serviceable": true,
          "priceAvailable": true,
          "pricesPln": {
            "zone1Weekday": 350,
            "zone1WeekendHoliday": 450,
            "zone2Weekday": 400,
            "zone2WeekendHoliday": 500
          }
        }
      ]
    }
  ]
}

Błędy

400VALIDATION

groupSlug ma nieprawidłowy format.

JSON błędu
{
  "error": {
    "code": "VALIDATION",
    "message": "Nieprawidłowy groupSlug."
  }
}
404NOT_FOUND

Nieznany albo nieprawidłowy slug regionu.

JSON błędu
{
  "error": {
    "code": "NOT_FOUND",
    "message": "Nie znaleziono regionu."
  }
}
401UNAUTHORIZED

Brak tokenu, nieprawidłowy lub unieważniony klucz, nieaktywny partner albo klucz z innego środowiska.

JSON błędu
{
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Nieprawidłowy token."
  }
}
429RATE_LIMIT

Przekroczony limit w oknie minuty (w tym nieudane uwierzytelnienie).

JSON błędu
{
  "error": {
    "code": "RATE_LIMIT",
    "message": "Limit zapytań został przekroczony.",
    "details": { "retryAfterSeconds": 42 }
  }
}
503MISCONFIGURED

Usługa chwilowo niedostępna z powodu błędu konfiguracji.

JSON błędu
{
  "error": {
    "code": "MISCONFIGURED",
    "message": "Konfiguracja Partner API jest niekompletna."
  }
}
500INTERNAL

Nieobsłużony wyjątek — bez wycieku szczegółów.

JSON błędu
{
  "error": {
    "code": "INTERNAL",
    "message": "Nie udało się obsłużyć żądania."
  }
}
  • Limit 10 żądań na minutę na partnera, niezależnie od limitu globalnego.
POST

/v1/intakes

Bearer

Utwórz zgłoszenie

Tworzy zgłoszenie w puli operatora i zadanie oddzwonienia (priorytet wysoki). Nie zakłada konta pacjenta i nie składa zlecenia.

Lokalizacja: te same reguły co lookup. serviceGroupSlug musi być grupą wizyt domowych dostępną w tym punkcie.

Ciało nie ustawia tożsamości partnera ani statusu zgłoszenia. Nieznane pola → 400 VALIDATION. note to główne dolegliwości (notatka kliniczna). patientAgeYears to wiek pacjenta w latach.

Nagłówki

PoleTypOpis
Idempotency-Keywymaganestring8–128 znaków [A-Za-z0-9._:-]. Wymagany.
Content-Typewymaganeapplication/jsonJSON.

Ciało żądania

PoleTypOpis
serviceGroupSlugwymaganestringSlug z katalogu, maks. 80 znaków.
locationwymaganeobjectcoordinates i/lub googlePlaceId; address opcjonalnie (etykieta).
externalRefstringTwój identyfikator leada, 1–128. Unikalny per partner.
caller.phonestringOpcjonalny polski numer komórkowy: E.164 (+48500100200), 0048… albo 9 cyfr. API normalizuje go do E.164.
caller.firstName / lastNamestringOpcjonalne, maks. 80 znaków.
patientAgeYearsintegerWiek pacjenta w latach, 0–120.
notestringGłówne dolegliwości, maks. 2000 znaków. Trafia do operatora jako notatka kliniczna.
preferredVisitDateYYYY-MM-DDPreferowany dzień wizyty. Wymagany gdy visitAsSoonAsPossible=false.
visitAsSoonAsPossiblebooleanDomyślnie true gdy brak daty. true = jak najszybciej (bez slotu).
preferredVisitSlotobjectOpcjonalny slot: label, startMinute, endMinute (0–1439). Przy jak najszybciej ignorowany.

Przykład ciała

JSON
{
  "externalRef": "lead-99821",
  "serviceGroupSlug": "lekarz-dla-dzieci",
  "location": {
    "address": "ul. Przykładowa 2, Kraków",
    "coordinates": { "lat": 50.0614, "lng": 19.9366 }
  },
  "caller": {
    "phone": "+48500100200",
    "firstName": "Anna",
    "lastName": "Nowak"
  },
  "patientAgeYears": 4,
  "note": "Gorączka od wieczora",
  "preferredVisitDate": "2026-08-30"
}

Wywołanie

curl
curl -sS https://staging-api.wezwijdoktora.pl/v1/intakes \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: lead-99821" \
  -H "Accept: application/json" \
  -d '{
    "externalRef": "lead-99821",
    "serviceGroupSlug": "lekarz-dla-dzieci",
    "location": {
      "address": "ul. Przykładowa 2, Kraków",
      "coordinates": { "lat": 50.0614, "lng": 19.9366 }
    },
    "caller": { "phone": "+48500100200", "firstName": "Anna" }
  }'

Odpowiedzi sukcesu

201Utworzono

Nowe zgłoszenie, status=new. id to UUID zgłoszenia. API nie zwraca UUID zlecenia.

JSON odpowiedzi
{
  "id": "7c2e4b10-9a1c-4f2d-8e11-0b3a6c8d9e01",
  "status": "new",
  "externalRef": "lead-99821",
  "serviceGroupSlug": "lekarz-dla-dzieci",
  "location": {
    "gminaTerc": "1261011",
    "powiatTerc": "1261",
    "zone": "basic",
    "formattedAddress": "ul. Przykładowa 2, Kraków"
  }
}
200Ponowienie

Ten sam Idempotency-Key (albo externalRef) i to samo ciało. Zwracamy aktualny stan zgłoszenia — nie zamrożoną kopię z momentu utworzenia.

JSON odpowiedzi
{
  "id": "7c2e4b10-9a1c-4f2d-8e11-0b3a6c8d9e01",
  "status": "new",
  "externalRef": "lead-99821",
  "serviceGroupSlug": "lekarz-dla-dzieci",
  "location": {
    "gminaTerc": "1261011",
    "powiatTerc": "1261",
    "zone": "basic",
    "formattedAddress": "ul. Przykładowa 2, Kraków"
  }
}

Błędy

400VALIDATION

Brak albo zły Content-Type, brak Idempotency-Key, nieprawidłowy alfabet klucza, nieprawidłowy JSON, brak miejsca, nieprawidłowy telefon albo nieznane pola.

404NO_GMINA

Punkt bez gminy (jak przy lookup).

409IDEMPOTENCY_CONFLICT

Klucz lub externalRef już użyty z innym ciałem żądania. message wskazuje, czy konflikt dotyczy Idempotency-Key, czy externalRef.

JSON błędu
{
  "error": {
    "code": "IDEMPOTENCY_CONFLICT",
    "message": "Ten Idempotency-Key był użyty z innym ciałem żądania."
  }
}
413PAYLOAD_TOO_LARGE

Ciało większe niż 16 KB.

422UNKNOWN_SERVICE_GROUP

Slug nie jest opublikowaną grupą wizyt domowych.

422OUT_OF_COVERAGE

Brak coverage adresu („Ten adres jest poza obszarem usług.”) albo wybranej grupy („Ta usługa nie jest dostępna w tej lokalizacji.”). details.gminaTerc, gdy znana.

JSON błędu
{
  "error": {
    "code": "OUT_OF_COVERAGE",
    "message": "Ten adres jest poza obszarem usług.",
    "details": { "gminaTerc": "1465011" }
  }
}
503GOOGLE_UNAVAILABLE

googlePlaceId, a geokodowanie Google jest niedostępne.

401UNAUTHORIZED

Brak tokenu, nieprawidłowy lub unieważniony klucz, nieaktywny partner albo klucz z innego środowiska.

JSON błędu
{
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Nieprawidłowy token."
  }
}
429RATE_LIMIT

Przekroczony limit w oknie minuty (w tym nieudane uwierzytelnienie).

JSON błędu
{
  "error": {
    "code": "RATE_LIMIT",
    "message": "Limit zapytań został przekroczony.",
    "details": { "retryAfterSeconds": 42 }
  }
}
503MISCONFIGURED

Usługa chwilowo niedostępna z powodu błędu konfiguracji.

JSON błędu
{
  "error": {
    "code": "MISCONFIGURED",
    "message": "Konfiguracja Partner API jest niekompletna."
  }
}
500INTERNAL

Nieobsłużony wyjątek — bez wycieku szczegółów.

JSON błędu
{
  "error": {
    "code": "INTERNAL",
    "message": "Nie udało się obsłużyć żądania."
  }
}
  • Telefon nie jest wymagany — operator oddzwoni, jeśli go podasz.
  • Limit 10 POST /v1/intakes na partnera na minutę (plus limit globalny).
GET

/v1/intakes/{id}

Bearer

Status zgłoszenia

Zwraca wyłącznie zgłoszenia Twojego partnera. Obcy identyfikator, zgłoszenie spoza API albo nie-UUID zawsze kończy się 404 z tym samym komunikatem (nigdy 403).

status: new | in_progress | converted | discarded. Pole order.publicNumber pojawia się wyłącznie przy converted — publiczny numer zlecenia WezwijDoktora (# + 10 znaków szesnastkowych), bez UUID zlecenia.

Parametry ścieżki

PoleTypOpis
idwymaganeuuidid z odpowiedzi POST /v1/intakes.

Wywołanie

curl
curl -sS https://staging-api.wezwijdoktora.pl/v1/intakes/7c2e4b10-9a1c-4f2d-8e11-0b3a6c8d9e01 \
  -H "Authorization: Bearer $TOKEN" \
  -H "Accept: application/json"

Odpowiedzi sukcesu

200Nowe / w toku

Bez order, dopóki operator nie złoży zlecenia.

JSON odpowiedzi
{
  "id": "7c2e4b10-9a1c-4f2d-8e11-0b3a6c8d9e01",
  "status": "new",
  "externalRef": "lead-99821",
  "serviceGroupSlug": "lekarz-dla-dzieci",
  "location": {
    "gminaTerc": "1261011",
    "powiatTerc": "1261",
    "zone": "basic",
    "formattedAddress": "ul. Przykładowa 2, Kraków"
  }
}
200Po konwersji

publicNumber do pokazania u siebie (np. „numer zlecenia WezwijDoktora”).

JSON odpowiedzi
{
  "id": "7c2e4b10-9a1c-4f2d-8e11-0b3a6c8d9e01",
  "status": "converted",
  "externalRef": "lead-99821",
  "serviceGroupSlug": "lekarz-dla-dzieci",
  "location": {
    "gminaTerc": "1261011",
    "powiatTerc": "1261",
    "zone": "basic",
    "formattedAddress": "ul. Przykładowa 2, Kraków"
  },
  "order": {
    "publicNumber": "#45FFEBD6EA"
  }
}

Błędy

404NOT_FOUND

Brak zgłoszenia dla tego partnera albo nieprawidłowy id.

JSON błędu
{
  "error": {
    "code": "NOT_FOUND",
    "message": "Nie znaleziono zgłoszenia."
  }
}
401UNAUTHORIZED

Brak tokenu, nieprawidłowy lub unieważniony klucz, nieaktywny partner albo klucz z innego środowiska.

JSON błędu
{
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Nieprawidłowy token."
  }
}
429RATE_LIMIT

Przekroczony limit w oknie minuty (w tym nieudane uwierzytelnienie).

JSON błędu
{
  "error": {
    "code": "RATE_LIMIT",
    "message": "Limit zapytań został przekroczony.",
    "details": { "retryAfterSeconds": 42 }
  }
}
503MISCONFIGURED

Usługa chwilowo niedostępna z powodu błędu konfiguracji.

JSON błędu
{
  "error": {
    "code": "MISCONFIGURED",
    "message": "Konfiguracja Partner API jest niekompletna."
  }
}
500INTERNAL

Nieobsłużony wyjątek — bez wycieku szczegółów.

JSON błędu
{
  "error": {
    "code": "INTERNAL",
    "message": "Nie udało się obsłużyć żądania."
  }
}
  • v1 nie udostępnia listy zgłoszeń ani aktualizacji. Webhook — poza v1; odpytuj GET po id.