Quickstart
W 5 minut wpychasz pierwszego lekarza i slot, który widać publicznie na profilu.
1. Wygeneruj API key
Zaloguj się jako clinic_admin na pandoktorek.pl →
Klinika → API Keys → Nowy klucz. Wybierz scopes:
doctors:write— push lekarzyservices:write— push usługslots:write— push slotówbookings:read— pull rezerwacji (opcjonalne, gdy nie używasz webhooków)
Klucz ma format pk_live_XXXXXXXX_<secret>. Plaintext widzisz tylko raz —
zapisz w secrets manager / env. Dalej pk_live_XXXXXXXX to publiczny prefix
(do identyfikacji w audit log), <secret> zhashowany argon2 w bazie.
2. Push pierwszego lekarza
curl -X POST https://api.pandoktorek.pl/api/v1/clinic/doctors \
-H "Authorization: Bearer pk_live_XXXXXXXX_<secret>" \
-H "Content-Type: application/json" \
-d '{
"doctors": [
{
"external_id": "mydr-12345",
"first_name": "Anna",
"last_name": "Kowalczyk",
"email": "anna.kowalczyk@klinika.pl",
"phone": "+48501234567",
"pwz": "1234567",
"specializations": ["dermatologia", "wenerologia"],
"is_telehealth_enabled": true,
"accepts_kids": true
}
]
}'
Response 200:
{
"created": 1,
"updated": 0,
"errors": []
}
external_id to twój identyfikator (z MyDr / CRM). Re-push tego samego ID =
update (idempotent), nie duplikat.
3. Push usługi
curl -X POST https://api.pandoktorek.pl/api/v1/clinic/services \
-H "Authorization: Bearer pk_live_XXXXXXXX_<secret>" \
-H "Content-Type: application/json" \
-d '{
"services": [
{
"external_id": "svc-konsultacja",
"name": "Konsultacja dermatologiczna",
"duration_minutes": 30,
"price_cents": 25000,
"currency": "PLN",
"is_active": true,
"is_nfz": false
}
]
}'
price_cents w groszach (G-FIN-001 — kwoty zawsze integer, nigdy float).
4. Push slotu
curl -X POST https://api.pandoktorek.pl/api/v1/clinic/slots \
-H "Authorization: Bearer pk_live_XXXXXXXX_<secret>" \
-H "Content-Type: application/json" \
-d '{
"slots": [
{
"external_id": "slot-2026-05-10-1000",
"doctor_external_id": "mydr-12345",
"start_at": "2026-05-10T10:00:00+02:00",
"end_at": "2026-05-10T10:30:00+02:00",
"services_allowed": ["svc-konsultacja"]
}
]
}'
Slot pojawi się publicznie na profilu lekarza w ciągu ~5 sekund (Meili sync
async). services_allowed opcjonalne — jak nie podasz, slot dostępny dla
wszystkich active services lekarza.
5. Subskrybuj webhook
W panelu klinki: Webhooks → Nowa subskrypcja.
- URL:
https://twój-system.pl/webhooks/pandoktorek - Events:
booking.created,booking.cancelled,booking.completed - Secret: zostanie wygenerowany — zapisz!
Pacjent rezerwuje slot → twój system dostaje POST z payloadem +
X-Pandoktorek-Signature: sha256=<hex>. Zweryfikuj HMAC, fan-out do MyDr,
acknowledge 200.
→ Webhooks signature verification
Kompletny przykład integracji
Skrypt cron co 5 min: pull slotów z MyDr → push do Pandoktorka:
import os, requests
from datetime import datetime, timedelta
API_KEY = os.environ["PANDOKTOREK_API_KEY"]
BASE = "https://api.pandoktorek.pl/api/v1"
def push_slots(slots):
r = requests.post(
f"{BASE}/clinic/slots",
headers={"Authorization": f"Bearer {API_KEY}"},
json={"slots": slots},
timeout=10,
)
r.raise_for_status()
return r.json()
slots_from_mydr = mydr.list_slots(from_date=datetime.now())
result = push_slots([
{
"external_id": s.id,
"doctor_external_id": s.doctor_id,
"start_at": s.start.isoformat(),
"end_at": s.end.isoformat(),
}
for s in slots_from_mydr
])
print(f"Updated {result['updated']}, created {result['created']}")
:::tip Bulk
POST /api/v1/clinic/slots przyjmuje do 2000 slotów na request. Lekarze
i usługi — do 500. Większe paczki dziel na batche.
:::
Dalej
- Auth (API key) → — pełen opis flow + scopes + rotation
- Webhooks → — wszystkie eventy + retry policy
- Errors → — kody błędów i jak je obsługiwać