Dla programistów

API WorshipPro

Odczytuj pieśni, plany nabożeństw, obsadę, wydarzenia i (za osobną zgodą) osoby swojego Kościoła z własnej strony internetowej, arkusza, n8n albo Zapiera. API v1 działa tylko do odczytu.

Pierwsze wywołanie

  1. Administrator Kościoła otwiera Ustawienia Kościoła → Integracje → Tokeny API i tworzy token: nazwa, zakresy i ważność (30–365 dni).
  2. Pełny token (wp_live_…) widać tylko raz. Zapisz go w menedżerze sekretów integracji, nie w kodzie strony ani w przeglądarce.
  3. Wyślij go w nagłówku Authorization: Bearer. Na początek sprawdź token — odpowiedź pokaże Kościół i zakresy, które działają.
curl -H "Authorization: Bearer $WORSHIPPRO_TOKEN" \
  https://worshippro.net/api/v1/token

API nie obsługuje CORS: token nie może trafiać do przeglądarki odwiedzających. Plan na stronie www pobieraj po stronie serwera albo użyj kalendarza iCal.

Zakresy

Token działa w części wspólnej: zakresy tokena ∩ bieżące uprawnienia osoby, która go utworzyła ∩ moduły włączone w Kościele. Gdy twórca straci rolę, token przestaje działać albo działa węziej.

songs:read Pieśni
Teksty, akordy, tonacje i aranżacje (bez plików).
plans:read Plany nabożeństw
Pozycje i godziny planów, bez obsady i notatek prywatnych.
teams:read Zespoły i obsada
Zespoły, stanowiska i to, kto służy w planach (imiona i nazwiska, bez kontaktów).
events:read Wydarzenia
Publiczne wydarzenia z kalendarza Kościoła i sale.
people:read Osoby (dane kontaktowe)
Imię, nazwisko, e-mail, telefon, status, rodzina i tagi. Nigdy dane wrażliwe ani notatki.

Zakres osób wymaga uprawnienia do zarządzania kartoteką i umowy powierzenia z odbiorcą danych. Dane wrażliwe (zdrowie, daty urodzenia i chrztu, pola własne), notatki, zgody i dzieci nigdy nie wychodzą przez API.

Limity

  • 120 jednostek na minutę i 5000 na godzinę na token
  • 300 jednostek na minutę na cały Kościół
  • Zwykłe zapytanie kosztuje 1, lista z wyszukiwaniem q — 5, wydarzenia w oknie from/to — 2.
  • Każda odpowiedź ma nagłówki RateLimit-Policy i RateLimit. Po przekroczeniu dostaniesz 429 z nagłówkiem Retry-After.

Stronicowanie i synchronizacja

Listy zwracają do 100 rekordów (limit) i nextCursor. Przekaż go jako cursor, aż dostaniesz null. Do synchronizacji przyrostowej zapamiętaj najnowsze updatedAt i pytaj z updatedSince, a usunięcia pobieraj z /deleted?since=.

Każdy błąd ma ten sam kształt, a pole message jest w języku z nagłówka Accept-Language:

{
  "error": {
    "code": "insufficient_scope",
    "message": "…",
    "required": "people:read",
    "reason": "token_scope"
  },
  "requestId": "…"
}

Przykłady

Plany na najbliższą niedzielę

curl -H "Authorization: Bearer $WORSHIPPRO_TOKEN" \
  "https://worshippro.net/api/v1/plans?from=2026-10-11&to=2026-10-11"

Synchronizacja pieśni zmienionych od ostatniego razu

curl -H "Authorization: Bearer $WORSHIPPRO_TOKEN" \
  "https://worshippro.net/api/v1/songs?updatedSince=2026-10-01T00:00:00Z&limit=100"

# next page:
curl -H "Authorization: Bearer $WORSHIPPRO_TOKEN" \
  "https://worshippro.net/api/v1/songs?updatedSince=2026-10-01T00:00:00Z&limit=100&cursor=<nextCursor>"

curl -H "Authorization: Bearer $WORSHIPPRO_TOKEN" \
  "https://worshippro.net/api/v1/deleted?since=2026-10-01T00:00:00Z"

Wydarzenia w październiku (z rozwiniętymi cyklami)

curl -H "Authorization: Bearer $WORSHIPPRO_TOKEN" \
  "https://worshippro.net/api/v1/events?from=2026-10-01&to=2026-10-31"

Webhooki

Zamiast co chwilę odpytywać API, integracja może dostawać powiadomienia. Administrator Kościoła dodaje adres (tylko publiczny https) w Ustawieniach Kościoła → Integracje → Webhooki i wybiera zdarzenia. Wiadomość jest krótka i bez danych osobowych: same identyfikatory. Szczegóły pobierz przez API swoim tokenem.

Każda wiadomość to POST z JSON-em w tej samej kopercie. Pole type mówi, co się stało, a data niesie tylko pola z tabeli niżej.

{
  "v": 1,
  "id": "evt_2f6c0d8e4b1a4c7f9e3d5a6b7c8d9e0f",
  "type": "donation.paid",
  "createdAt": "2026-10-11T08:40:00.000Z",
  "churchId": "8b1e…",
  "data": {
    "donationId": "5e0b…",
    "amount": 5000,
    "currency": "PLN",
    "fundId": "a4f7…",
    "paidAt": "2026-10-11T08:40:00.000Z",
    "method": "online"
  }
}

Zdarzenia

plan.updated

Plan nabożeństwa powstał, zmienił się (także pozycje i godziny), został opublikowany albo usunięty. Seria zmian idzie jako jedna wiadomość 10 minut po ostatniej edycji. Szablony planów nie wysyłają zdarzeń.

Pola data: planId, updatedAt

Pobierz GET /api/v1/plans/{planId} (zakres plans:read). 404 oznacza usunięty plan — znajdziesz go też w /deleted.

form.submission_created

Ktoś wysłał formularz zapisów (publiczny, bez konta) albo organizator wpisał zgłoszenie. Bez imienia, e-maila i odpowiedzi.

Pola data: formId, submissionId, createdAt

Zgłoszenie obejrzysz w WorshipPro (Zapisy i formularze). Odczytu odpowiedzi przez API na razie nie ma.

donation.paid

Wpłata jest potwierdzona: płatność online po potwierdzeniu operatora, darowizna zapisana przez skarbnika albo pozycja kolekty po jej zamknięciu przez dwie osoby. Dar rzeczowy nie wysyła zdarzenia.

Pola data: donationId, amount, currency, fundId, paidAt, method

Kwota w groszach (5000 = 50,00 zł), fundusz największej części darowizny (null — bez funduszu), method: cash, transfer, online albo card. Bez danych darczyńcy; finansów nie udostępniamy przez API.

Adres dostaje tylko zdarzenia, do których osoba, która go dodała, ma dziś dostęp (plany, kartoteka z prawem edycji, księgowość). Gdy straci dostęp, te wiadomości są pomijane.

Dostarczanie i ponowienia

  • Odpowiedz kodem 2xx w ciągu 10 sekund. Przekierowania nie są obsługiwane; treść odpowiedzi jest ignorowana.
  • Po błędzie ponawiamy po 5 s, 5 min, 30 min, 2 h, 5 h, 10 h i 24 h (8 prób w sumie). Nagłówek Retry-After przy 429 i 503 honorujemy (maks. 24 h).
  • Ta sama wiadomość może przyjść więcej niż raz. Nagłówek webhook-id jest stały między próbami — po nim usuwaj duplikaty.
  • Odpowiedź 410 Gone, 5 dni samych błędów albo 3 kolejne wiadomości bez skutku wyłączają adres. Administrator dostaje wtedy e-mail i może go włączyć ponownie (z wysłaniem nieudanych wiadomości z 7 dni).
POST /your-endpoint
content-type: application/json
webhook-id: msg_…
webhook-timestamp: 1791707400
webhook-signature: v1,K5oZfz…=

Weryfikacja podpisu

Wiadomości są podpisane zgodnie ze Standard Webhooks, więc możesz użyć gotowej biblioteki „standardwebhooks” (wiele języków) z sekretem whsec_… Bez biblioteki:

  1. Odrzuć wiadomość, jeśli webhook-timestamp różni się od Twojego zegara o więcej niż 5 minut.
  2. Policz HMAC-SHA256 z tekstu: webhook-id, kropka, webhook-timestamp, kropka i surowa treść. Kluczem są bajty z base64 po prefiksie whsec_.
  3. Porównaj wynik (base64) w stałym czasie z każdym podpisem v1 z nagłówka webhook-signature. Po zmianie sekretu przez 24 h nagłówek niesie dwa podpisy: nowy i stary.

Podpis liczy się z treści dokładnie takiej, jak przyszła — zanim ją sparsujesz jako JSON.

Node.js

import crypto from "node:crypto";

// secret: "whsec_…" (shown once in Church settings → Integrations → Webhooks)
// rawBody: the request body exactly as received (string, before JSON.parse)
function verifyWorshipProWebhook(secret, headers, rawBody) {
  const id = headers["webhook-id"];
  const ts = Number(headers["webhook-timestamp"]);
  if (!id || !Number.isInteger(ts) || Math.abs(Date.now() / 1000 - ts) > 300) return false;
  const key = Buffer.from(secret.replace(/^whsec_/, ""), "base64");
  const expected = crypto.createHmac("sha256", key).update(`${id}.${ts}.${rawBody}`).digest();
  return String(headers["webhook-signature"] ?? "").split(" ").some((part) => {
    const [version, sig] = part.split(",");
    const got = Buffer.from(sig ?? "", "base64");
    return version === "v1" && got.length === expected.length && crypto.timingSafeEqual(got, expected);
  });
}

Dokumentacja zasobów

Wczytywanie dokumentacji…

    API dla programistów — WorshipPro