Przejdź do głównej zawartości

POST /api/v1/clinic/doctors

Bulk upsert lekarzy. Idempotent po (clinic_id, external_id). created = nowe mappings; updated = istniejące mappings z odświeżonym snapshotem User.

Auth: Bearer pk_live_* z scope doctors:write (więcej).

Request​

POST /api/v1/clinic/doctors HTTP/1.1
Host: api.pandoktorek.pl
Authorization: Bearer pk_live_XXXXXXXX_<secret>
Content-Type: application/json

{
"doctors": [ /* DoctorIngestItem, max 500 */ ]
}

DoctorIngestItem​

PoleTypWymaganeOpis
external_idstring (1-120)✅Twój ID z CRM. Stabilny — nie zmienia się dla tego samego lekarza
first_namestring (1-100)✅Imię
last_namestring (1-100)✅Nazwisko
emailemail✅Lekarz dostanie magic-link claim email (DEC-009)
phonestring (regex ^\+?\d{9,15}$)—E.164 lub krajowy
pwzstring (regex ^\d{7}$)—Numer Prawa Wykonywania Zawodu (PL)
specializationsstring[]—Np. ["dermatologia", "wenerologia"]
is_telehealth_enabledbool—Czy lekarz robi telekonsultacje
accepts_kidsbool—Czy przyjmuje dzieci

:::info Email — własność lekarza Email NIE jest nadpisywany przy update — lekarz mógł zmienić email po claim. Zmiana wymaga /auth/request-verification z poziomu lekarza. :::

Response 200​

{
"created": 2,
"updated": 1,
"errors": []
}

created — nowe clinic_doctor_mappings rows. Każdy nowy lekarz dostaje email magic-link z prośbą o claim profilu (DEC-009).

updated — istniejące mappings; User snapshot (first/last name, phone, pwz, specializations, flags) został odświeżony. Lekarz NIE dostaje nowego emaila.

errors — partial failures (np. duplikat pwz w paczce). Pole obecne tylko gdy len > 0.

Response 422 — walidacja​

{
"detail": [
{
"loc": ["body", "doctors", 0, "pwz"],
"msg": "string does not match regex \"^\\d{7}$\"",
"type": "value_error.str.regex"
}
]
}

→ Errors

Pełen przykład​

curl -X POST https://api.pandoktorek.pl/api/v1/clinic/doctors \
-H "Authorization: Bearer pk_live_XXXXXXXX_<secret>" \
-H "Content-Type: application/json" \
-d @- <<'EOF'
{
"doctors": [
{
"external_id": "mydr-12345",
"first_name": "Anna",
"last_name": "Kowalczyk",
"email": "anna.kowalczyk@klinika.pl",
"phone": "+48501234567",
"pwz": "1234567",
"specializations": ["dermatologia"],
"is_telehealth_enabled": true,
"accepts_kids": false
},
{
"external_id": "mydr-67890",
"first_name": "Jan",
"last_name": "Nowak",
"email": "jan.nowak@klinika.pl",
"specializations": ["kardiologia"],
"accepts_kids": true
}
]
}
EOF

Mapping table​

Pandoktorek trzyma mapping clinic_doctor_mappings:

| clinic_id | external_id | doctor_user_id |
|-----------|-------------|----------------|
| clinic_A | mydr-12345 | uuid-... |
| clinic_A | mydr-67890 | uuid-... |

Re-push z innego clinic'u z tym samym external_id = osobny mapping (różne clinic_id → różne lekarze logicznie, mimo że pwz mógłby być ten sam).

Doctor profile editing​

Po claim'ie lekarz może edytować publiczny profil (bio, photo, degree) przez /doktor/profil. Pola medyczne (specializations, pwz) — push'owane przez ciebie — lekarz NIE może edytować (bo source-of-truth w klinice).

mode=external_managed (DEC-012): klinika zarządza w MyDr → cały sync jednokierunkowy. mode=standalone: klinika edytuje też w panelu Pandoktorka, ale ten endpoint nadal działa (wygrywa ostatni write).

Limity​

  • Max 500 doctors per request (paczki)
  • Max 120 znaków external_id
  • Max 100 znaków first/last name
  • Rate limit: 10 000 requests/dobę per API key