Przypominamy.com SMS API v2.3.0
Polskie REST API do wysyłki SMS z własnym kluczem, saldem, kontaktami, czarną listą, śledzonymi linkami, odbiorem odpowiedzi (2-way, na życzenie) i historią wysyłek
REST API do programowej wysyłki SMS w Polsce i za granicą. Jeden endpoint do wysyłki (pojedynczej, masowej i do grupy kontaktów), historia wiadomości, saldo, wybór nadpisu, książka kontaktów z personalizacją, czarna lista z linkiem opt-out, śledzone linki {{link:…}} z licznikiem kliknięć, odbiór odpowiedzi (2-way, na życzenie) i webhooki ze statusem doręczenia podpisane HMAC.
Dla kogo: firmy, które chcą wysyłać SMS-y z własnego systemu - przypomnienia o wizytach, potwierdzenia zamówień, kody 2FA, powiadomienia transakcyjne.
Autoryzacja
Klucz API generujesz w panelu (https://app.przypominamy.com/keys). Klucz ma postać pk_live_… (lub pk_test_… na koncie testowym) i jest pokazywany raz. Przekazuj go w nagłówku:
Authorization: Bearer pk_live_…
Klucz można w każdej chwili odwołać i wydać nowy w panelu.
Zakresy klucza (scopes)
Przy tworzeniu klucza w panelu wybierasz zakresy: send (wysyłka SMS/MMS/głos i anulowanie zaplanowanych), read (historia, raporty, konto, nadpisy, czarna lista, kontakty i grupy, odpowiedzi 2-way, śledzone linki - odczyt), manage (ustawienia konta, webhook, zapis czarnej listy, kontaktów i grup). Klucze wydane przed wprowadzeniem zakresów mają wszystkie trzy. Wywołanie bez wymaganego zakresu zwraca HTTP 403 forbidden z komunikatem wskazującym brakujący zakres. Aktualne zakresy klucza widzisz w polu scopes w GET /v1/account.
Saldo i cennik
Konto działa w modelu prepaid: każda wysyłka obciąża saldo w groszach według ceny za część SMS ustalonej dla Twojego konta (price_per_part_grosze w GET /v1/account). Przy braku środków API zwraca HTTP 402 i nic nie jest wysyłane. Na życzenie ustawiamy limit kredytowy (saldo może zejść poniżej zera) i rozliczamy fakturą.
Liczba części liczona jest jak u operatorów: 160 znaków dla alfabetu GSM-7 (153 przy wiadomościach wieloczęściowych), 70 znaków (67) gdy treść zawiera polskie znaki lub inne znaki spoza GSM-7.
Rate limit
120 żądań na minutę per konto. Po przekroczeniu HTTP 429 z nagłówkiem Retry-After. Do wysyłki masowej użyj tablicy to (do 500 numerów w jednym żądaniu) zamiast wielu pojedynczych wywołań.
Idempotencja
Dodaj nagłówek Idempotency-Key (dowolny ciąg do 128 znaków). Powtórzenie żądania z tym samym kluczem i tą samą treścią w ciągu 24 h zwraca pierwotną odpowiedź (nagłówek Idempotent-Replayed: true) bez ponownej wysyłki i obciążenia. Ten sam klucz z inną treścią zwraca HTTP 409.
Godziny wysyłki i ważność wiadomości
send_window ("HH:MM-HH:MM", czas polski) w żądaniu albo jako domyślne ustawienie konta (PATCH /v1/account) przesuwa wysyłkę spoza okna na najbliższy początek okna (dziś lub jutro); koniec okna jest wyłączny. Taka wiadomość ma status scheduled i można ją anulować. expires_at (ISO 8601, 15 min – 72 h po czasie wysyłki) mówi, po jakim czasie dostawca ma przestać próbować doręczyć - np. termin wizyty, po którym przypomnienie nie ma sensu.
Kontakty, grupy i personalizacja
POST /v1/contacts zapisuje odbiorców (imię, nazwisko, e-mail, do 20 pól własnych, grupy). W polu to wysyłki możesz podać "group:<id lub nazwa>" - również w tablicy razem ze zwykłymi numerami. Placeholdery {{imie}}, {{nazwisko}}, {{email}} i {{<pole_własne>}} w text są podstawiane per odbiorca (maks. 4 różne placeholdery w jednej treści, 3 gdy używasz też {{opt_out}}); zwrócone wiadomości mają już spersonalizowany text.
Czarna lista i opt-out
Numery z czarnej listy (POST /v1/blacklist lub kliknięcie linku wypisu) nie idą do dostawcy: dostają status rejected, koszt 0 i błąd „Numer na czarnej liście (opt-out)”, nie liczą się do accepted. Placeholder {{opt_out}} (alias {{wypisz}}) w treści SMS zamienia się w krótki, osobisty link api.przypominamy.com/o/<token>; odbiorca po kliknięciu widzi stronę potwierdzenia, a jego numer trafia na czarną listę Twojego konta. W SMS-ach marketingowych taki link jest wymagany.
Śledzone linki
Wstaw {{link:https://…}} w text (do 2 różnych adresów w jednej wiadomości). Każdy odbiorca dostaje własny krótki link api.przypominamy.com/l/<8 znaków>, który przekierowuje (302) na Twój adres i zlicza kliknięcia. Zwrócony text zawiera już podstawione linki; GET /v1/messages/{id} ma tablicę links[], GET /v1/links zestawienie (kto kliknął, ile razy, kiedy), a webhook link.clicked przychodzi przy pierwszym kliknięciu każdego linku. Bez dopłaty. Budżet placeholderów: łącznie do 4 na wiadomość dla {{opt_out}}, linków i pól z kontaktów.
Odbiór odpowiedzi (2-way) - na życzenie
Odbiór odpowiedzi uruchamiamy na życzenie, po włączeniu numeru odbiorczego dla Twojego konta (napisz na [email protected]). Do tego czasu inbound_number w GET /v1/account i GET /v1/inbound jest null, a lista odpowiedzi pusta - endpointy istnieją i możesz je zintegrować już dziś. Po uruchomieniu odbiorcy odpisują na numer odbiorczy, a odpowiedź trafia do Twojego konta, gdy zaczyna się od Twojego słowa kluczowego (inbound_prefix, 2–10 liter lub cyfr, unikalne, PATCH /v1/account; słowo jest usuwane z treści) albo - bez słowa - gdy to Ty jako ostatni pisałeś na numer nadawcy w ciągu 30 dni (reply_to = id tej wysyłki). Odpowiedzi czytasz przez GET /v1/inbound (filtry from, since, unread, mark_read) i dostajesz webhookiem message.received. STOP, WYPISZ lub NIE od dopasowanego nadawcy dopisuje numer do czarnej listy (opt_out) - w webhooku opt_out: true. Odbiór na współdzielonym numerze jest bezpłatny; dedykowany numer odbiorczy - wycena indywidualna.
Webhooki
Po ustawieniu adresu przez PUT /v1/account/webhook wysyłamy POST application/json przy każdej zmianie statusu wiadomości (message.sent|delivered|undelivered|failed|expired), przy odpowiedzi odbiorcy (message.received, data.inbound + data.opt_out) i przy pierwszym kliknięciu śledzonego linku (link.clicked, data.link + data.clicked_at). Każde wywołanie jest podpisane:
X-Przypominamy-Signature: t=<unix>,v1=<hex>
v1 = HMAC-SHA256(webhook_secret, "<t>.<surowe body>"). Odrzucaj wywołania, w których |now - t| > 300 sekund. Próby: 3 (0 s, 2 s, 10 s).
Przykład weryfikacji w Node.js:
const crypto = require('crypto');
const header = req.headers['x-przypominamy-signature']; // "t=1757230000,v1=abc…"
const t = header.match(/t=(\d+)/)[1];
const sig = header.match(/v1=([0-9a-f]+)/)[1];
const expected = crypto.createHmac('sha256', WEBHOOK_SECRET).update(`${t}.${rawBody}`).digest('hex');
if (!crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))) return res.status(403).end();
if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return res.status(403).end();
Błędy
Wszystkie błędy mają postać { "error": { "code": "…", "message": "…", "param": "…" }, "request_id": "req_…" }. Każda odpowiedź ma nagłówek X-Request-Id - podaj go w zgłoszeniu do supportu.
Linki
- Strona API: https://przypominamy.com/api
- Dokumentacja czytelna: https://przypominamy.com/api/docs
- Serwer MCP dla asystentów AI (Claude, ChatGPT, Cursor, n8n) - to samo API i ten sam klucz przez Model Context Protocol: https://przypominamy.com/mcp
- Kontakt: [email protected]
Bezpieczny start
Po aktywacji konta utwórz nowy klucz pk_live_ w panelu. Stary pk_test_ nie uruchamia płatnych wysyłek na aktywnym koncie (403 forbidden). Saldo i stawki są netto; 50 zł netto doładowania = 61,50 zł brutto z 23% VAT. Raporty doręczenia w panelu i API działają niezależnie od własnego webhooka klienta. Błędny format numeru powoduje 400 invalid_request przed wysyłką. GSM-7 liczy znaki rozszerzone podwójnie, UTF-16 znaki spoza BMP jako dwie jednostki.
SMS zagraniczne
Domyślnie 2× krajowa cena konta za część netto; priority ponownie mnoży cenę przez 2. Pole international_sms w GET /v1/account podaje domyślną cenę. Kraje UE są aktywne, pozostałe kierunki wymagają potwierdzenia dostępności. MMS i głos zagraniczny wymagają osobnej wyceny.
Autoryzacja
Nagłówek Authorization: Bearer pk_live_… (lub pk_test_… na koncie testowym). Klucz tworzysz w panelu app.przypominamy.com.
Serwer MCP (asystenci AI)
To samo API dla Claude, Codex, Cursora i n8n przez Model Context Protocol: endpoint https://mcp.przypominamy.com/mcp (Streamable HTTP), ten sam nagłówek Authorization: Bearer pk_…, bez OAuth. Narzędzia (25) send_sms (także z template_id + params, priority i śledzonym linkiem {link:…}), send_voice, cancel_message, get_message, list_messages, list_replies (odpowiedzi 2-way), list_links (kliknięcia), count_sms_parts, list_templates, save_template, check_number (HLR), get_account, list_senders, set_default_sender, set_send_window, set_inbound_keyword, list_blacklist, add_to_blacklist, remove_from_blacklist, list_contacts, upsert_contacts, delete_contact, list_groups, add_to_group, get_report; podzbiory /mcp/sms, /mcp/account, /mcp/reports, /mcp/contacts. Narzędzia podlegają zakresom klucza (send / read / manage) tak samo jak REST. Konfiguracje klientów, przykładowe polecenia i zasady bezpieczeństwa: przypominamy.com/mcp.
GET /v1/health
Status API
Odpowiedzi
HTTP 200 - API działa
{
"status": "ok",
"service": "przypominamy.com API",
"version": "2.0"
}
POST /v1/messages
Wyślij SMS (jeden lub wielu odbiorców)
Wysyła SMS do jednego numeru (to jako string) lub do wielu (to jako tablica do 500 numerów, duplikaty usuwane). Koszt = liczba odbiorców × liczba części × cena za część. Saldo jest sprawdzane przed wysyłką. Wymaga zakresu send.
Numery przyjmujemy w formacie E.164 (+48600100200), bez plusa (48600100200) lub jako 9 cyfr (traktowane jako polskie).
Grupy i personalizacja: to może być "group:<id lub nazwa grupy>" albo tablicą mieszającą numery i grupy (łącznie do 500 odbiorców po rozwinięciu; pusta lub nieznana grupa = 400/404). Gdy w to jest grupa, placeholdery {{imie}}, {{nazwisko}}, {{email}} i {{<pole_własne>}} w text są podstawiane z kontaktów per odbiorca (także dla numerów podanych wprost, jeśli są w książce); brakująca wartość = pusty ciąg. Zwrócone wiadomości mają spersonalizowany text.
Opt-out: {{opt_out}} (alias {{wypisz}}) w treści zamienia się w osobisty link wypisu api.przypominamy.com/o/<token>. Odbiorcy z czarnej listy dostają status rejected, koszt 0 i nie są liczeni w accepted.
Godziny i ważność: send_window przesuwa wysyłkę spoza okna na najbliższy jego początek (status scheduled), expires_at ogranicza czas prób doręczenia. Te same opcje działają w POST /v1/mms i POST /v1/voice.
Szablony: zamiast text podaj template_id (szablon typu sms z GET /v1/templates) i params z wartościami {{klucz}}; pozostałe placeholdery są podstawiane z kontaktów albo pustym ciągiem. Ten sam mechanizm działa w POST /v1/mms (szablon mms) i POST /v1/voice (szablon vms).
Priorytet: priority: true kieruje SMS do osobnej, szybkiej kolejki u operatora (kody OTP, alerty) - cena za część × 2. Tylko SMS.
Śledzone linki: {{link:https://…}} w treści (do 2 różnych adresów) zamienia się per odbiorca w krótki link api.przypominamy.com/l/<token> z licznikiem kliknięć; zwrócony text ma już podstawiony link, GET /v1/messages/{id} zwraca links[], a przy pierwszym kliknięciu przychodzi webhook link.clicked. Bez dopłaty. {{opt_out}}, linki i pola z kontaktów dzielą wspólny budżet 4 placeholderów na wiadomość.
Parametry
| Nazwa | Typ | Opis |
|---|---|---|
Idempotency-Key header | string | Rezerwuje operację przed wysyłką. Ten sam klucz i treść odtwarzają zakończony wynik przez 24 h. Inna treść lub operacja w toku/nierozstrzygnięta: 409 idempotency_conflict. Nie ponawiaj z nowym kluczem po timeoutcie. Nierozstrzygnięte operacje wymagają uzgodnienia statusu i nie wygasają automatycznie. |
Treść żądania (JSON)
| Pole | Typ | Opis |
|---|---|---|
to wymagane | string | array | Numer odbiorcy, `"group:<id lub nazwa grupy>"` albo tablica numerów i grup (łącznie do 500 odbiorców po rozwinięciu, duplikaty usuwane) np. "+48600100200" |
text | string | Treść. Polskie znaki dozwolone (UCS-2, 70/67 znaków na część). Placeholdery: `{{imie}}`, `{{nazwisko}}`, `{{email}}`, `{{<pole_własne>}}` (z kontaktów - dla grup i dla numerów, które są w książce) i `{{opt_out}}` / `{{wypisz}}` (osobisty link wypisu) oraz `{{link:https://…}}` (śledzony krótki link per odbiorca, do 2 różnych adresów). Wymagane, chyba że podajesz `template_id`. np. "Przypominamy o wizycie jutro o 10:00." |
template_id | string | Id szablonu (`tpl_…`, z `GET /v1/templates`) zamiast `text`. Szablon musi być typu `sms` (w `POST /v1/mms` - `mms`, w `POST /v1/voice` - `vms`), inaczej 400 z `param: "template_id"`; nieznany → 404. Placeholdery `{{klucz}}` podstawiane z `params`, pozostałe z kontaktów albo pustym ciągiem. np. "tpl_Q3m7kL2pXa9dRt" |
params | object | Wartości placeholderów szablonu, np. `{ "kiedy": "jutro 10:00" }` → `{{kiedy}}`. Klucze bez rozróżniania wielkości liter. Tylko z `template_id`. np. {"kiedy": "jutro 10:00", "lekarz": "dr Nowak"} |
from | string | Nadpis (nazwa nadawcy). Musi być aktywny na liście `GET /v1/senders`. Domyślnie nadpis konta. np. "ZDROWKO" |
send_at | string | Zaplanowana wysyłka (ISO 8601), do 90 dni w przód. Daty w przeszłości = wysyłka natychmiast. np. "2026-09-08T08:00:00Z" |
send_window | string | Okno godzin wysyłki w czasie polskim (`HH:MM-HH:MM`, min. 15 minut, koniec wyłączny). Wysyłka spoza okna (teraz albo `send_at`) jest przesuwana na najbliższy początek okna i dostaje status `scheduled`. Pominięte = domyślne okno konta z `PATCH /v1/account`. np. "08:00-20:00" |
expires_at | string | Ważność: po tym czasie dostawca przestaje próbować doręczyć (status `expired`). Od 15 minut do 72 godzin po czasie wysyłki. np. "2026-09-08T20:00:00+02:00" |
reference | string | Twój identyfikator (np. id wizyty). Wraca w odpowiedzi, webhookach i jako filtr w `GET /v1/messages`. np. "wizyta-4711" |
priority | boolean | SMS priorytetowy: osobna, szybka kolejka u operatora (kody OTP, alerty). Cena za część × 2. Tylko SMS - w `POST /v1/mms` i `POST /v1/voice` ignorowane. Wartość inna niż `true`/`false` → 400. np. false |
Jeden odbiorca
{
"to": "+48600100200",
"text": "Przypominamy o wizycie jutro o 10:00.",
"from": "ZDROWKO",
"reference": "wizyta-4711"
}
Wielu odbiorców, ta sama treść
{
"to": [
"+48600100200",
"+48600100201"
],
"text": "Promocja -20% do niedzieli. Kod: SMS20"
}
Wysyłka odroczona
{
"to": "+48600100200",
"text": "Wizyta dziś o 14:00.",
"send_at": "2026-09-08T08:00:00Z"
}
Do grupy kontaktów z personalizacją
{
"to": "group:VIP",
"text": "Cześć {{imie}}, przypominamy o wizycie {{wizyta}}."
}
Marketing z linkiem opt-out, oknem godzin i ważnością
{
"to": [
"+48600100200",
"group:Newsletter"
],
"text": "Promocja -20% do niedzieli. Kod: SMS20. Wypisz sie: {{opt_out}}",
"send_window": "08:00-20:00",
"expires_at": "2026-09-08T20:00:00+02:00"
}
Z szablonu i parametrów
{
"to": "+48600100200",
"template_id": "tpl_Q3m7kL2pXa9dRt",
"params": {
"imie": "Anno",
"kiedy": "jutro 10:00",
"lekarz": "dr Nowak"
},
"reference": "wizyta-4711"
}
Kod OTP priorytetem (podwójna stawka)
{
"to": "+48600100200",
"text": "Twoj kod: 4321. Wazny 5 minut.",
"priority": true
}
Śledzony link z licznikiem kliknięć
{
"to": [
"+48600100200",
"+48600100201"
],
"text": "Potwierdz wizyte: {{link:https://firma.pl/wizyta?id=7}} Odpowiedz TAK albo NIE.",
"reference": "wizyta-4711"
}
Odpowiedzi
HTTP 201 - Wiadomość przyjęta. Dla `to` jako string zwracany jest pojedynczy obiekt Message; dla tablicy - obiekt zbiorczy.
pojedynczy
{
"id": "msg_qY08hZ2mmDXAazdRTytS",
"type": "sms",
"status": "queued",
"to": "+48600100200",
"from": "ZDROWKO",
"text": "Przypominamy o wizycie jutro o 10:00.",
"subject": null,
"parts": 1,
"cost_grosze": 9,
"priority": false,
"reference": "wizyta-4711",
"send_at": null,
"expires_at": null,
"delivered_at": null,
"error": null,
"created_at": "2026-09-07T07:11:04.000Z",
"updated_at": "2026-09-07T07:11:04.000Z"
}
masowy
{
"count": 2,
"accepted": 2,
"total_cost_grosze": 18,
"messages": [
{
"id": "msg_a…",
"type": "sms",
"status": "queued",
"to": "+48600100200",
"from": "ZDROWKO",
"text": "…",
"subject": null,
"parts": 1,
"cost_grosze": 9,
"priority": false,
"reference": null,
"send_at": null,
"expires_at": null,
"delivered_at": null,
"error": null,
"created_at": "…",
"updated_at": "…"
},
{
"id": "msg_b…",
"type": "sms",
"status": "queued",
"to": "+48600100201",
"from": "ZDROWKO",
"text": "…",
"subject": null,
"parts": 1,
"cost_grosze": 9,
"priority": false,
"reference": null,
"send_at": null,
"expires_at": null,
"delivered_at": null,
"error": null,
"created_at": "…",
"updated_at": "…"
}
]
}
Grupa z personalizacją i jednym numerem na czarnej liście
{
"count": 2,
"accepted": 1,
"total_cost_grosze": 9,
"messages": [
{
"id": "msg_a…",
"type": "sms",
"status": "queued",
"to": "+48600100200",
"from": "ZDROWKO",
"text": "Cześć Anna, przypominamy o wizycie 10.09 14:00.",
"subject": null,
"parts": 1,
"cost_grosze": 9,
"priority": false,
"reference": null,
"send_at": null,
"expires_at": null,
"delivered_at": null,
"error": null,
"created_at": "…",
"updated_at": "…"
},
{
"id": "msg_b…",
"type": "sms",
"status": "rejected",
"to": "+48600100201",
"from": "ZDROWKO",
"text": "Cześć Piotr, przypominamy o wizycie .",
"subject": null,
"parts": 1,
"cost_grosze": 0,
"priority": false,
"reference": null,
"send_at": null,
"expires_at": null,
"delivered_at": null,
"error": "Numer na czarnej liście (opt-out)",
"created_at": "…",
"updated_at": "…"
}
]
}
HTTP 400 - Błąd walidacji
{
"error": {
"code": "invalid_request",
"message": "Nieprawidłowy numer odbiorcy: +48XXXXXXXXX",
"param": "to"
},
"request_id": "req_…"
}
HTTP 401 - Brak lub nieprawidłowy klucz API
{
"error": {
"code": "unauthorized",
"message": "Nieprawidłowy klucz API"
},
"request_id": "req_…"
}
HTTP 402 - Niewystarczające środki (prepaid) albo nieopłacone zestawienie miesięczne (postpaid) - nic nie zostało wysłane
Za mało środków na saldzie
{
"error": {
"code": "insufficient_funds",
"message": "Niewystarczające środki. Szacowany koszt: 0.18 PLN, dostępne: 0.05 PLN"
},
"request_id": "req_…"
}
Konto postpaid z zaległym zestawieniem
{
"error": {
"code": "insufficient_funds",
"message": "Konto ma nieopłacone zestawienie miesięczne. Wysyłki wznowimy po zaksięgowaniu wpłaty."
},
"request_id": "req_…"
}
HTTP 403 - Klucz bez wymaganego zakresu (albo konto zawieszone / testowe wysyła na niezweryfikowany numer)
{
"error": {
"code": "forbidden",
"message": "Ten klucz API nie ma zakresu \"send\". Wygeneruj klucz z odpowiednim zakresem w panelu (app.przypominamy.com/keys)."
},
"request_id": "req_…"
}
HTTP 404 - Nieznana grupa w polu `to`
{
"error": {
"code": "not_found",
"message": "Nie znaleziono grupy: VIP",
"param": "groups"
},
"request_id": "req_…"
}
HTTP 409 - Idempotency-Key użyty z inną treścią albo operacja w toku lub nierozstrzygnięta
HTTP 422 - Odrzucone przez dostawcę SMS (numer, nadpis, długość)
HTTP 429 - Przekroczono limit żądań
HTTP 502 - Błąd lub brak odpowiedzi dostawcy SMS (502/504)
Przykład: curl
curl -X POST https://api.przypominamy.com/v1/messages \
-H "Authorization: Bearer $PRZYPOMINAMY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"to": "+48600100200", "text": "Przypominamy o wizycie jutro o 10:00.", "reference": "wizyta-4711"}'
Przykład: Python
import os, requests
resp = requests.post(
"https://api.przypominamy.com/v1/messages",
headers={"Authorization": f"Bearer {os.environ['PRZYPOMINAMY_API_KEY']}"},
json={"to": "+48600100200", "text": "Przypominamy o wizycie jutro o 10:00.", "reference": "wizyta-4711"},
timeout=10,
)
resp.raise_for_status()
print(resp.json()["id"], resp.json()["status"])
Przykład: Node.js
const res = await fetch('https://api.przypominamy.com/v1/messages', {
method: 'POST',
headers: { Authorization: `Bearer ${process.env.PRZYPOMINAMY_API_KEY}`, 'Content-Type': 'application/json' },
body: JSON.stringify({ to: '+48600100200', text: 'Przypominamy o wizycie jutro o 10:00.', reference: 'wizyta-4711' }),
});
const msg = await res.json();
console.log(msg.id, msg.status);
GET /v1/messages
Historia wiadomości
Paginowana lista wiadomości konta, od najnowszych. Do następnej strony użyj cursor z pola next_cursor.
Parametry
| Nazwa | Typ | Opis |
|---|---|---|
limit query | integer | |
status query | string | |
reference query | string | Dokładne dopasowanie pola `reference` |
to query | string | Numer odbiorcy |
cursor query | string | Wartość `next_cursor` z poprzedniej strony |
Odpowiedzi
HTTP 200 - Strona wyników
HTTP 401 - Brak lub nieprawidłowy klucz API
{
"error": {
"code": "unauthorized",
"message": "Nieprawidłowy klucz API"
},
"request_id": "req_…"
}
HTTP 429 - Przekroczono limit żądań
GET /v1/messages/{id}
Pobierz wiadomość
Parametry
| Nazwa | Typ | Opis |
|---|---|---|
id path wymagane | string |
Odpowiedzi
HTTP 200 - Wiadomość wraz ze śledzonymi linkami (`links[]`, pusta tablica, gdy w treści nie było `{{link:…}}`)
{
"id": "msg_qY08hZ2mmDXAazdRTytS",
"type": "sms",
"status": "delivered",
"to": "+48600100200",
"from": "ZDROWKO",
"text": "Potwierdz wizyte: api.przypominamy.com/l/k3Jd9sQz Odpowiedz TAK albo NIE.",
"subject": null,
"parts": 1,
"cost_grosze": 9,
"priority": false,
"reference": "wizyta-4711",
"send_at": null,
"expires_at": null,
"delivered_at": "2026-09-08T07:12:38.000Z",
"error": null,
"created_at": "2026-09-08T07:11:04.000Z",
"updated_at": "2026-09-08T07:12:40.000Z",
"links": [
{
"token": "k3Jd9sQz",
"short_url": "https://api.przypominamy.com/l/k3Jd9sQz",
"url": "https://firma.pl/wizyta?id=7",
"message_id": "msg_qY08hZ2mmDXAazdRTytS",
"to": "+48600100200",
"clicks": 1,
"first_click_at": "2026-09-08T07:15:02.000Z",
"last_click_at": "2026-09-08T07:15:02.000Z",
"created_at": "2026-09-08T07:11:04.000Z"
}
]
}
HTTP 401 - Brak lub nieprawidłowy klucz API
{
"error": {
"code": "unauthorized",
"message": "Nieprawidłowy klucz API"
},
"request_id": "req_…"
}
HTTP 403 - Klucz bez wymaganego zakresu (albo konto zawieszone / testowe wysyła na niezweryfikowany numer)
{
"error": {
"code": "forbidden",
"message": "Ten klucz API nie ma zakresu \"send\". Wygeneruj klucz z odpowiednim zakresem w panelu (app.przypominamy.com/keys)."
},
"request_id": "req_…"
}
HTTP 404 - Nie znaleziono
DELETE /v1/messages/{id}
Anuluj zaplanowaną wysyłkę
Anuluje wiadomość ze statusem scheduled co najmniej 30 s przed send_at (SMS, MMS i głos). Status zmienia się na cancelled, koszt wraca na saldo (wpis refund w historii salda), a na koncie testowym zwracany jest kredyt testowy. Ponowne anulowanie tej samej wiadomości zwraca 200 z tym samym rekordem. Wiadomości już wysłanej albo z terminem za mniej niż 30 s nie da się cofnąć - HTTP 409. Wymaga zakresu send.
Parametry
| Nazwa | Typ | Opis |
|---|---|---|
id path wymagane | string |
Odpowiedzi
HTTP 200 - Anulowano - rekord wiadomości ze statusem `cancelled`
| Pole | Typ | Opis |
|---|---|---|
id | string | np. "msg_qY08hZ2mmDXAazdRTytS" |
type | string: sms, mms, vms | Kanał: SMS, MMS, wiadomość głosowa |
status | string: scheduled, queued, sent, delivered, undelivered, failed, expired, rejected, cancelled | `scheduled` - zaplanowana (`send_at` lub przesunięta przez `send_window`); `queued` - przyjęta; `sent` - przekazana do sieci; `delivered` - doręczona; `undelivered` - niedoręczona; `failed` - odrzucona przez dostawcę; `rejected` - odrzucona przez nas (numer na czarnej liście, koszt 0); `expired` - wygasła (m.in. po `expires_at`); `cancelled` - zaplanowana wysyłka anulowana przez `DELETE /v1/messages/{id}`, koszt zwrócony |
to | string | np. "+48600100200" |
from | string | null | np. "ZDROWKO" |
text | string | Treść po personalizacji - dokładnie to, co dostał odbiorca (link opt-out, śledzone linki `api.przypominamy.com/l/…` i placeholdery już podstawione) |
subject | string | null | Temat (tylko MMS) |
parts | integer | np. 1 |
cost_grosze | integer | Koszt w groszach (0 dla odrzuconych; po anulowaniu zwrócony na saldo) np. 9 |
priority | boolean | Czy wysłano jako SMS priorytetowy (podwójna stawka) np. false |
reference | string | null | |
send_at | string | null | Termin wysyłki (po przesunięciu przez `send_window`, jeśli było) |
expires_at | string | null | Koniec prób doręczenia, gdy podano `expires_at` |
delivered_at | string | null | |
error | string | null | Powód odrzucenia, gdy status = failed lub rejected (np. „Numer na czarnej liście (opt-out)”) |
created_at | string | |
updated_at | string |
{
"id": "msg_qY08hZ2mmDXAazdRTytS",
"type": "sms",
"status": "cancelled",
"to": "+48600100200",
"from": "ZDROWKO",
"text": "Wizyta jutro o 10:00.",
"subject": null,
"parts": 1,
"cost_grosze": 9,
"priority": false,
"reference": null,
"send_at": "2026-09-08T06:00:00.000Z",
"expires_at": null,
"delivered_at": null,
"error": null,
"created_at": "2026-09-07T07:11:04.000Z",
"updated_at": "2026-09-07T09:20:11.000Z"
}
HTTP 401 - Brak lub nieprawidłowy klucz API
{
"error": {
"code": "unauthorized",
"message": "Nieprawidłowy klucz API"
},
"request_id": "req_…"
}
HTTP 403 - Klucz bez wymaganego zakresu (albo konto zawieszone / testowe wysyła na niezweryfikowany numer)
{
"error": {
"code": "forbidden",
"message": "Ten klucz API nie ma zakresu \"send\". Wygeneruj klucz z odpowiednim zakresem w panelu (app.przypominamy.com/keys)."
},
"request_id": "req_…"
}
HTTP 404 - Nie znaleziono
HTTP 409 - Nie można anulować (wiadomość nie jest zaplanowana albo termin za mniej niż 30 s)
{
"error": {
"code": "invalid_request",
"message": "Można anulować tylko zaplanowaną wysyłkę co najmniej 30 s przed terminem"
},
"request_id": "req_…"
}
HTTP 502 - Błąd lub brak odpowiedzi dostawcy SMS (502/504)
Przykład: curl
curl -X DELETE https://api.przypominamy.com/v1/messages/msg_qY08hZ2mmDXAazdRTytS \
-H "Authorization: Bearer $PRZYPOMINAMY_API_KEY"
GET /v1/templates
Lista szablonów
Szablony konta (te same, które widać w panelu), posortowane po nazwie, z listą placeholderów {{klucz}} znalezionych w treści. Wymaga zakresu read.
Odpowiedzi
HTTP 200 - Lista szablonów
{
"data": [
{
"id": "tpl_Q3m7kL2pXa9dRt",
"name": "Wizyta",
"type": "sms",
"body": "Cześć {{imie}}, wizyta {{kiedy}} u {{lekarz}}.",
"subject": null,
"placeholders": [
"imie",
"kiedy",
"lekarz"
],
"created_at": "2026-09-07T07:11:04.000Z",
"updated_at": "2026-09-07T07:11:04.000Z"
}
]
}
HTTP 401 - Brak lub nieprawidłowy klucz API
{
"error": {
"code": "unauthorized",
"message": "Nieprawidłowy klucz API"
},
"request_id": "req_…"
}
HTTP 403 - Klucz bez wymaganego zakresu (albo konto zawieszone / testowe wysyła na niezweryfikowany numer)
{
"error": {
"code": "forbidden",
"message": "Ten klucz API nie ma zakresu \"send\". Wygeneruj klucz z odpowiednim zakresem w panelu (app.przypominamy.com/keys)."
},
"request_id": "req_…"
}
Przykład: curl
curl https://api.przypominamy.com/v1/templates \
-H "Authorization: Bearer $PRZYPOMINAMY_API_KEY"
POST /v1/templates
Utwórz szablon
Zapisuje szablon z placeholderami {{klucz}} (klucz: litery, cyfry, podkreślenie). type domyślnie sms; dla mms w body podaj dokument SMIL, a temat w subject; vms to szablon wiadomości głosowej. Wymaga zakresu manage.
Treść żądania (JSON)
| Pole | Typ | Opis |
|---|---|---|
name wymagane | string | np. "Wizyta" |
type | string: sms, mms, vms | Domyślnie `sms` |
body wymagane | string | Treść z placeholderami `{{klucz}}` np. "Cześć {{imie}}, wizyta {{kiedy}} u {{lekarz}}." |
subject | string | null | Temat (tylko MMS) |
{
"name": "Wizyta",
"body": "Cześć {{imie}}, wizyta {{kiedy}} u {{lekarz}}."
}
Odpowiedzi
HTTP 201 - Utworzono
| Pole | Typ | Opis |
|---|---|---|
id | string | np. "tpl_Q3m7kL2pXa9dRt" |
name | string | np. "Wizyta" |
type | string: sms, mms, vms | Kanał, do którego pasuje szablon - musi zgadzać się z endpointem wysyłki |
body | string | Treść z placeholderami `{{klucz}}` (dla MMS - dokument SMIL) np. "Cześć {{imie}}, wizyta {{kiedy}} u {{lekarz}}." |
subject | string | null | Temat (tylko MMS) |
placeholders | array<string> | Placeholdery znalezione w `body`, małymi literami np. ["imie", "kiedy", "lekarz"] |
created_at | string | |
updated_at | string |
{
"id": "tpl_Q3m7kL2pXa9dRt",
"name": "Wizyta",
"type": "sms",
"body": "Cześć {{imie}}, wizyta {{kiedy}} u {{lekarz}}.",
"subject": null,
"placeholders": [
"imie",
"kiedy",
"lekarz"
],
"created_at": "2026-09-07T07:11:04.000Z",
"updated_at": "2026-09-07T07:11:04.000Z"
}
HTTP 400 - Błąd walidacji
{
"error": {
"code": "invalid_request",
"message": "Nieprawidłowy numer odbiorcy: +48XXXXXXXXX",
"param": "to"
},
"request_id": "req_…"
}
HTTP 401 - Brak lub nieprawidłowy klucz API
{
"error": {
"code": "unauthorized",
"message": "Nieprawidłowy klucz API"
},
"request_id": "req_…"
}
HTTP 403 - Klucz bez wymaganego zakresu (albo konto zawieszone / testowe wysyła na niezweryfikowany numer)
{
"error": {
"code": "forbidden",
"message": "Ten klucz API nie ma zakresu \"send\". Wygeneruj klucz z odpowiednim zakresem w panelu (app.przypominamy.com/keys)."
},
"request_id": "req_…"
}
Przykład: curl
curl -X POST https://api.przypominamy.com/v1/templates \
-H "Authorization: Bearer $PRZYPOMINAMY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "Wizyta", "body": "Cześć {{imie}}, wizyta {{kiedy}} u {{lekarz}}."}'
Przykład: Python
import requests
r = requests.post(
"https://api.przypominamy.com/v1/templates",
headers={"Authorization": f"Bearer {API_KEY}"},
json={"name": "Wizyta", "body": "Cześć {{imie}}, wizyta {{kiedy}} u {{lekarz}}."},
timeout=15,
)
tpl = r.json()
# wysyłka z szablonu
requests.post(
"https://api.przypominamy.com/v1/messages",
headers={"Authorization": f"Bearer {API_KEY}"},
json={"to": "+48600100200", "template_id": tpl["id"], "params": {"imie": "Anno", "kiedy": "jutro 10:00", "lekarz": "dr Nowak"}},
timeout=15,
)
GET /v1/templates/{id}
Pobierz szablon
Wymaga zakresu read.
Parametry
| Nazwa | Typ | Opis |
|---|---|---|
id path wymagane | string |
Odpowiedzi
HTTP 200 - Szablon
| Pole | Typ | Opis |
|---|---|---|
id | string | np. "tpl_Q3m7kL2pXa9dRt" |
name | string | np. "Wizyta" |
type | string: sms, mms, vms | Kanał, do którego pasuje szablon - musi zgadzać się z endpointem wysyłki |
body | string | Treść z placeholderami `{{klucz}}` (dla MMS - dokument SMIL) np. "Cześć {{imie}}, wizyta {{kiedy}} u {{lekarz}}." |
subject | string | null | Temat (tylko MMS) |
placeholders | array<string> | Placeholdery znalezione w `body`, małymi literami np. ["imie", "kiedy", "lekarz"] |
created_at | string | |
updated_at | string |
HTTP 401 - Brak lub nieprawidłowy klucz API
{
"error": {
"code": "unauthorized",
"message": "Nieprawidłowy klucz API"
},
"request_id": "req_…"
}
HTTP 403 - Klucz bez wymaganego zakresu (albo konto zawieszone / testowe wysyła na niezweryfikowany numer)
{
"error": {
"code": "forbidden",
"message": "Ten klucz API nie ma zakresu \"send\". Wygeneruj klucz z odpowiednim zakresem w panelu (app.przypominamy.com/keys)."
},
"request_id": "req_…"
}
HTTP 404 - Nie znaleziono
PATCH /v1/templates/{id}
Zmień szablon
Częściowa aktualizacja - podajesz tylko zmieniane pola (name, type, body, subject). Wymaga zakresu manage.
Parametry
| Nazwa | Typ | Opis |
|---|---|---|
id path wymagane | string |
Treść żądania (JSON)
| Pole | Typ | Opis |
|---|---|---|
name | string | |
type | string: sms, mms, vms | |
body | string | |
subject | string | null |
{
"name": "Wizyta 2"
}
Odpowiedzi
HTTP 200 - Zmieniono
| Pole | Typ | Opis |
|---|---|---|
id | string | np. "tpl_Q3m7kL2pXa9dRt" |
name | string | np. "Wizyta" |
type | string: sms, mms, vms | Kanał, do którego pasuje szablon - musi zgadzać się z endpointem wysyłki |
body | string | Treść z placeholderami `{{klucz}}` (dla MMS - dokument SMIL) np. "Cześć {{imie}}, wizyta {{kiedy}} u {{lekarz}}." |
subject | string | null | Temat (tylko MMS) |
placeholders | array<string> | Placeholdery znalezione w `body`, małymi literami np. ["imie", "kiedy", "lekarz"] |
created_at | string | |
updated_at | string |
HTTP 400 - Błąd walidacji
{
"error": {
"code": "invalid_request",
"message": "Nieprawidłowy numer odbiorcy: +48XXXXXXXXX",
"param": "to"
},
"request_id": "req_…"
}
HTTP 401 - Brak lub nieprawidłowy klucz API
{
"error": {
"code": "unauthorized",
"message": "Nieprawidłowy klucz API"
},
"request_id": "req_…"
}
HTTP 403 - Klucz bez wymaganego zakresu (albo konto zawieszone / testowe wysyła na niezweryfikowany numer)
{
"error": {
"code": "forbidden",
"message": "Ten klucz API nie ma zakresu \"send\". Wygeneruj klucz z odpowiednim zakresem w panelu (app.przypominamy.com/keys)."
},
"request_id": "req_…"
}
HTTP 404 - Nie znaleziono
DELETE /v1/templates/{id}
Usuń szablon
Usuwa szablon; wysłane wcześniej wiadomości zostają. Wymaga zakresu manage.
Parametry
| Nazwa | Typ | Opis |
|---|---|---|
id path wymagane | string |
Odpowiedzi
HTTP 200 - Usunięto
{
"deleted": "tpl_Q3m7kL2pXa9dRt"
}
HTTP 401 - Brak lub nieprawidłowy klucz API
{
"error": {
"code": "unauthorized",
"message": "Nieprawidłowy klucz API"
},
"request_id": "req_…"
}
HTTP 403 - Klucz bez wymaganego zakresu (albo konto zawieszone / testowe wysyła na niezweryfikowany numer)
{
"error": {
"code": "forbidden",
"message": "Ten klucz API nie ma zakresu \"send\". Wygeneruj klucz z odpowiednim zakresem w panelu (app.przypominamy.com/keys)."
},
"request_id": "req_…"
}
HTTP 404 - Nie znaleziono
GET /v1/numbers/{msisdn}/lookup
Sprawdź numer (HLR)
Pyta operatora, czy numer jest aktywny w sieci i w jakiej - bez wysyłania SMS-a. Przydatne przed kampanią (czyszczenie bazy z martwych numerów) i przy weryfikacji numeru w rejestracji.
Koszt: price_per_hlr_grosze z GET /v1/account (domyślnie 5 gr = 0,05 zł), pobierany z salda jak SMS. Ponowne sprawdzenie tego samego numeru w ciągu 24 h zwraca wynik z pamięci (cached: true, cost_grosze: 0) bez pytania operatora.
Konto testowe: tylko numery zweryfikowane w panelu (inaczej 403), bez opłaty. Przy braku środków 402. Wymaga zakresu send.
Parametry
| Nazwa | Typ | Opis |
|---|---|---|
msisdn path wymagane | string | Numer w E.164 (plus zakoduj jako `%2B` albo pomiń); 9 cyfr = numer polski |
Odpowiedzi
HTTP 200 - Wynik sprawdzenia
| Pole | Typ | Opis |
|---|---|---|
msisdn | string | np. "+48600100200" |
status | string: active, inactive, invalid, unknown | `active` - numer w sieci; `inactive` - nieosiągalny lub nieistniejący; `invalid` - zły format; `unknown` - operator nie odpowiedział jednoznacznie |
network | string | null | Nazwa sieci (Plus, T-Mobile, Orange, Play…) np. "T-Mobile" |
mcc | string | null | np. "260" |
mnc | string | null | np. "02" |
ported | boolean | null | Czy numer został przeniesiony do innej sieci |
cost_grosze | integer | Pobrana opłata (0 dla wyniku z pamięci i na koncie testowym) np. 5 |
cached | boolean | `true` - wynik z ostatnich 24 h, bez opłaty i bez pytania operatora |
checked_at | string | Kiedy operator sprawdził numer |
Numer aktywny, sprawdzony u operatora
{
"msisdn": "+48600100200",
"status": "active",
"network": "T-Mobile",
"mcc": "260",
"mnc": "02",
"ported": false,
"cost_grosze": 5,
"cached": false,
"checked_at": "2026-09-07T07:11:04.000Z"
}
Ten sam numer w ciągu 24 h - bez opłaty
{
"msisdn": "+48600100200",
"status": "active",
"network": "T-Mobile",
"mcc": "260",
"mnc": "02",
"ported": false,
"cost_grosze": 0,
"cached": true,
"checked_at": "2026-09-07T07:11:04.000Z"
}
Numer nieosiągalny
{
"msisdn": "+48600100201",
"status": "inactive",
"network": "Play",
"mcc": "260",
"mnc": "06",
"ported": null,
"cost_grosze": 5,
"cached": false,
"checked_at": "2026-09-07T07:11:04.000Z"
}
HTTP 400 - Błąd walidacji
{
"error": {
"code": "invalid_request",
"message": "Nieprawidłowy numer odbiorcy: +48XXXXXXXXX",
"param": "to"
},
"request_id": "req_…"
}
HTTP 401 - Brak lub nieprawidłowy klucz API
{
"error": {
"code": "unauthorized",
"message": "Nieprawidłowy klucz API"
},
"request_id": "req_…"
}
HTTP 402 - Niewystarczające środki na sprawdzenie
{
"error": {
"code": "insufficient_funds",
"message": "Niewystarczające środki na sprawdzenie numeru (0.05 PLN)"
},
"request_id": "req_…"
}
HTTP 403 - Klucz bez zakresu `send` albo konto testowe i niezweryfikowany numer
{
"error": {
"code": "forbidden",
"message": "Konto testowe może sprawdzać tylko zweryfikowane numery. Doładuj konto, żeby sprawdzać dowolne.",
"param": "msisdn"
},
"request_id": "req_…"
}
HTTP 502 - Błąd lub brak odpowiedzi dostawcy SMS (502/504)
Przykład: curl
curl https://api.przypominamy.com/v1/numbers/48600100200/lookup \
-H "Authorization: Bearer $PRZYPOMINAMY_API_KEY"
Przykład: Python
import requests
r = requests.get(
"https://api.przypominamy.com/v1/numbers/48600100200/lookup",
headers={"Authorization": f"Bearer {API_KEY}"},
timeout=15,
)
hlr = r.json()
print(hlr["status"], hlr["network"], "z pamięci" if hlr["cached"] else f"{hlr['cost_grosze']} gr")
Przykład: Node.js
const r = await fetch('https://api.przypominamy.com/v1/numbers/48600100200/lookup', {
headers: { Authorization: `Bearer ${process.env.PRZYPOMINAMY_API_KEY}` },
});
const hlr = await r.json();
if (hlr.status !== 'active') console.log('numer nieaktywny - pomiń w kampanii');
GET /v1/account
Saldo i ustawienia konta
Saldo, cennik (w tym price_per_hlr_grosze za sprawdzenie numeru), tryb konta, model rozliczenia (billing_mode: prepaid domyślnie, postpaid włączany na życzenie po weryfikacji firmy), domyślny nadpis, domyślne okno godzin wysyłki (send_window), numer odbiorczy do odpowiedzi 2-way (inbound_number; null, dopóki odbiór nie jest uruchomiony na życzenie dla konta), Twoje słowo kluczowe do odpowiedzi (inbound_prefix) i zakresy użytego klucza (scopes). Wymaga zakresu read.
Odpowiedzi
HTTP 200 - Konto
| Pole | Typ | Opis |
|---|---|---|
country_rates | object | Indywidualne stawki zagraniczne: prefiks numeru → ceny kanałów w groszach netto. Bez pasującej stawki SMS kosztuje 2× krajową cenę konta; MMS i głos wymagają osobnej wyceny. Najdłuższy prefiks wygrywa. Polska używa standardowej ceny konta. |
id | string | np. "cl_3W4997VtDI8fG1hM" |
name | string | |
sender_name | string | null | np. "ZDROWKO" |
balance_grosze | integer | np. 4982 |
credit_limit_grosze | integer | np. 0 |
price_per_part_grosze | integer | np. 9 |
price_per_mms_grosze | integer | np. 35 |
price_per_vms_grosze | integer | np. 25 |
price_per_hlr_grosze | integer | Cena sprawdzenia numeru (HLR) w groszach np. 5 |
rate_limit_per_minute | integer | np. 120 |
webhook_url | string | null | |
status | string: active, suspended, closed | |
mode | string: test, live | `test` - tylko zweryfikowane numery, koszt z puli testowej |
test_credits | integer | Pozostałe darmowe wiadomości (tylko w trybie `test`) |
send_window | string | null | Domyślne okno godzin wysyłki konta (czas polski) lub `null` np. "08:00-20:00" |
billing_mode | string: prepaid, postpaid | `prepaid` (domyślnie) - saldo doładowane z góry. `postpaid` - włączany przez nas na życzenie po weryfikacji firmy: saldo może zejść poniżej zera do `credit_limit_grosze`, 1. dnia miesiąca wystawiamy zestawienie za poprzedni miesiąc (14 dni na przelew, tytuł = id zestawienia), po terminie wysyłki są wstrzymane (402 `insufficient_funds`) do zaksięgowania wpłaty. np. "prepaid" |
inbound_number | string | null | Numer odbiorczy, na który odbiorcy mogą odpisać (2-way). Odbiór uruchamiamy na życzenie - `null`, dopóki nie jest włączony dla konta np. "+48799000000" |
inbound_prefix | string | null | Twoje słowo kluczowe: SMS zaczynający się od niego trafia do Twojego konta niezależnie od wcześniejszych wysyłek (`PATCH /v1/account`) np. "ZDROWKO" |
scopes | array<string> | Zakresy klucza użytego w tym żądaniu np. ["send", "read", "manage"] |
international_sms | object | Domyślna cena SMS zagranicznego netto za część. Kraje UE aktywne; inne kierunki po potwierdzeniu dostępności. |
{
"id": "cl_3W4997VtDI8fG1hM",
"name": "Przychodnia Zdrówko",
"sender_name": "ZDROWKO",
"balance_grosze": 4982,
"credit_limit_grosze": 0,
"price_per_part_grosze": 9,
"price_per_mms_grosze": 35,
"price_per_vms_grosze": 25,
"price_per_hlr_grosze": 5,
"rate_limit_per_minute": 120,
"webhook_url": null,
"status": "active",
"mode": "live",
"send_window": "08:00-20:00",
"billing_mode": "prepaid",
"inbound_number": "+48799000000",
"inbound_prefix": "ZDROWKO",
"scopes": [
"send",
"read",
"manage"
]
}
HTTP 401 - Brak lub nieprawidłowy klucz API
{
"error": {
"code": "unauthorized",
"message": "Nieprawidłowy klucz API"
},
"request_id": "req_…"
}
HTTP 403 - Klucz bez wymaganego zakresu (albo konto zawieszone / testowe wysyła na niezweryfikowany numer)
{
"error": {
"code": "forbidden",
"message": "Ten klucz API nie ma zakresu \"send\". Wygeneruj klucz z odpowiednim zakresem w panelu (app.przypominamy.com/keys)."
},
"request_id": "req_…"
}
PATCH /v1/account
Ustaw domyślny nadpis, godziny wysyłki lub słowo kluczowe odpowiedzi
Zmienia ustawienia konta; podaj co najmniej jedno pole. sender_name - domyślna nazwa nadawcy, musi być aktywna na liście z GET /v1/senders, inaczej HTTP 422; null przywraca domyślny nadpis operatora. send_window - domyślne okno godzin wysyłki w czasie polskim ("HH:MM-HH:MM", minimum 15 minut, koniec wyłączny); wysyłki bez własnego send_window spoza okna są przesuwane na najbliższy początek okna; null wyłącza. inbound_prefix - słowo kluczowe (2–10 liter lub cyfr, zapisywane wielkimi literami, unikalne w całej platformie - zajęte → HTTP 409), którym odbiorcy zaczynają SMS na numer odbiorczy, żeby trafił do Twojego konta niezależnie od wcześniejszych wysyłek (działa po uruchomieniu odbioru 2-way dla konta); null usuwa. Wymaga zakresu manage.
Treść żądania (JSON)
| Pole | Typ | Opis |
|---|---|---|
sender_name | string | null | Domyślny nadpis; `null` = nadpis operatora np. "ZDROWKO" |
send_window | string | null | Domyślne okno godzin wysyłki (czas polski); `null` = bez ograniczeń np. "08:00-20:00" |
inbound_prefix | string | null | Słowo kluczowe odpowiedzi na numer odbiorczy (2–10 liter/cyfr, bez rozróżniania wielkości); `null` = brak np. "ZDROWKO" |
Domyślny nadpis
{
"sender_name": "ZDROWKO"
}
Godziny wysyłki
{
"send_window": "08:00-20:00"
}
Słowo kluczowe do odpowiedzi
{
"inbound_prefix": "ZDROWKO"
}
Odpowiedzi
HTTP 200 - Zaktualizowano
{
"id": "cl_3W4997VtDI8fG1hM",
"sender_name": "ZDROWKO",
"send_window": "08:00-20:00",
"inbound_prefix": "ZDROWKO"
}
HTTP 400 - Błąd walidacji
{
"error": {
"code": "invalid_request",
"message": "Nieprawidłowy numer odbiorcy: +48XXXXXXXXX",
"param": "to"
},
"request_id": "req_…"
}
HTTP 401 - Brak lub nieprawidłowy klucz API
{
"error": {
"code": "unauthorized",
"message": "Nieprawidłowy klucz API"
},
"request_id": "req_…"
}
HTTP 403 - Klucz bez wymaganego zakresu (albo konto zawieszone / testowe wysyła na niezweryfikowany numer)
{
"error": {
"code": "forbidden",
"message": "Ten klucz API nie ma zakresu \"send\". Wygeneruj klucz z odpowiednim zakresem w panelu (app.przypominamy.com/keys)."
},
"request_id": "req_…"
}
HTTP 409 - Słowo kluczowe `inbound_prefix` zajęte przez inne konto
{
"error": {
"code": "invalid_request",
"message": "Ten prefiks jest już zajęty. Wybierz inny.",
"param": "inbound_prefix"
},
"request_id": "req_…"
}
HTTP 422 - Nadpis nieaktywny
GET /v1/senders
Dostępne nadpisy
Aktywne nazwy nadawcy, których możesz użyć w polu from lub jako domyślny nadpis. Nowy nadpis rejestrujemy na życzenie ([email protected]), weryfikacja u operatora trwa zwykle 1–2 dni robocze.
Odpowiedzi
HTTP 200 - Lista nadpisów
{
"data": [
{
"name": "PRZYPOMINAM",
"is_default": false
},
{
"name": "ZDROWKO",
"is_default": false
}
],
"current": "ZDROWKO"
}
HTTP 401 - Brak lub nieprawidłowy klucz API
{
"error": {
"code": "unauthorized",
"message": "Nieprawidłowy klucz API"
},
"request_id": "req_…"
}
HTTP 502 - Błąd lub brak odpowiedzi dostawcy SMS (502/504)
PUT /v1/account/webhook
Ustaw adres webhooka
Ustawia adres HTTPS, na który wysyłamy zdarzenia message.* (statusy doręczenia i message.received - odpowiedź odbiorcy) oraz link.clicked (pierwsze kliknięcie śledzonego linku). Odpowiedź zawiera webhook_secret do weryfikacji podpisu. rotate_secret: true generuje nowy sekret; url: null wyłącza webhooki.
Treść żądania (JSON)
| Pole | Typ | Opis |
|---|---|---|
url wymagane | string | null | np. "https://twojadomena.pl/webhooks/sms" |
rotate_secret | boolean |
Odpowiedzi
HTTP 200 - Zapisano
{
"webhook_url": "https://twojadomena.pl/webhooks/sms",
"webhook_secret": "whsec_…",
"signature_header": "X-Przypominamy-Signature"
}
HTTP 400 - Błąd walidacji
{
"error": {
"code": "invalid_request",
"message": "Nieprawidłowy numer odbiorcy: +48XXXXXXXXX",
"param": "to"
},
"request_id": "req_…"
}
HTTP 401 - Brak lub nieprawidłowy klucz API
{
"error": {
"code": "unauthorized",
"message": "Nieprawidłowy klucz API"
},
"request_id": "req_…"
}
HTTP 403 - Klucz bez wymaganego zakresu (albo konto zawieszone / testowe wysyła na niezweryfikowany numer)
{
"error": {
"code": "forbidden",
"message": "Ten klucz API nie ma zakresu \"send\". Wygeneruj klucz z odpowiednim zakresem w panelu (app.przypominamy.com/keys)."
},
"request_id": "req_…"
}
GET /v1/blacklist
Czarna lista
Aktywne wpisy czarnej listy konta (bez wygasłych), posortowane po numerze. Paginacja kursorem: next_cursor to ostatni numer strony. Wymaga zakresu read.
Parametry
| Nazwa | Typ | Opis |
|---|---|---|
limit query | integer | |
cursor query | string | Wartość `next_cursor` z poprzedniej strony (numer) |
Odpowiedzi
HTTP 200 - Strona wyników
{
"data": [
{
"msisdn": "+48600100200",
"reason": "opt_out",
"created_at": "2026-09-07T10:02:11.000Z",
"expires_at": null
},
{
"msisdn": "+48600100201",
"reason": "reklamacja",
"created_at": "2026-09-07T10:05:40.000Z",
"expires_at": "2026-12-31T23:00:00.000Z"
}
],
"next_cursor": null
}
HTTP 401 - Brak lub nieprawidłowy klucz API
{
"error": {
"code": "unauthorized",
"message": "Nieprawidłowy klucz API"
},
"request_id": "req_…"
}
HTTP 403 - Klucz bez wymaganego zakresu (albo konto zawieszone / testowe wysyła na niezweryfikowany numer)
{
"error": {
"code": "forbidden",
"message": "Ten klucz API nie ma zakresu \"send\". Wygeneruj klucz z odpowiednim zakresem w panelu (app.przypominamy.com/keys)."
},
"request_id": "req_…"
}
POST /v1/blacklist
Dodaj numery do czarnej listy
Blokuje jeden numer (msisdn) lub wiele (msisdns, do 1000). Istniejący wpis jest nadpisywany (nowy powód i data wygaśnięcia). Nieprawidłowe numery wracają w invalid i nie przerywają żądania. Wysyłka na zablokowany numer dostaje status rejected bez opłaty. Wymaga zakresu manage.
Treść żądania (JSON)
| Pole | Typ | Opis |
|---|---|---|
msisdn | string | Jeden numer (alternatywnie `msisdns`) np. "+48600100200" |
msisdns | array<string> | Lista numerów |
reason | string | Powód (domyślnie `manual`; link opt-out zapisuje `opt_out`) np. "reklamacja" |
expires_at | string | null | Koniec blokady (ISO 8601, w przyszłości); brak = bezterminowo |
Jeden numer bezterminowo
{
"msisdn": "+48600100200",
"reason": "reklamacja"
}
Lista numerów z datą wygaśnięcia
{
"msisdns": [
"+48600100200",
"+48600100201"
],
"reason": "kampania Q4",
"expires_at": "2026-12-31T23:00:00Z"
}
Odpowiedzi
HTTP 201 - Dodano
{
"added": 2,
"invalid": [],
"expires_at": "2026-12-31T23:00:00.000Z"
}
HTTP 400 - Błąd walidacji
{
"error": {
"code": "invalid_request",
"message": "Nieprawidłowy numer odbiorcy: +48XXXXXXXXX",
"param": "to"
},
"request_id": "req_…"
}
HTTP 401 - Brak lub nieprawidłowy klucz API
{
"error": {
"code": "unauthorized",
"message": "Nieprawidłowy klucz API"
},
"request_id": "req_…"
}
HTTP 403 - Klucz bez wymaganego zakresu (albo konto zawieszone / testowe wysyła na niezweryfikowany numer)
{
"error": {
"code": "forbidden",
"message": "Ten klucz API nie ma zakresu \"send\". Wygeneruj klucz z odpowiednim zakresem w panelu (app.przypominamy.com/keys)."
},
"request_id": "req_…"
}
Przykład: curl
curl -X POST https://api.przypominamy.com/v1/blacklist \
-H "Authorization: Bearer $PRZYPOMINAMY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"msisdns": ["+48600100200"], "reason": "reklamacja"}'
DELETE /v1/blacklist/{msisdn}
Usuń numer z czarnej listy
Odblokowuje numer. Jeśli odbiorca sam się wypisał linkiem opt-out, ponowne wysyłki marketingowe wymagają jego nowej zgody. Wymaga zakresu manage.
Parametry
| Nazwa | Typ | Opis |
|---|---|---|
msisdn path wymagane | string | Numer w E.164 (plus zakoduj jako `%2B` albo pomiń) |
Odpowiedzi
HTTP 200 - Usunięto
{
"removed": "+48600100200"
}
HTTP 400 - Błąd walidacji
{
"error": {
"code": "invalid_request",
"message": "Nieprawidłowy numer odbiorcy: +48XXXXXXXXX",
"param": "to"
},
"request_id": "req_…"
}
HTTP 401 - Brak lub nieprawidłowy klucz API
{
"error": {
"code": "unauthorized",
"message": "Nieprawidłowy klucz API"
},
"request_id": "req_…"
}
HTTP 403 - Klucz bez wymaganego zakresu (albo konto zawieszone / testowe wysyła na niezweryfikowany numer)
{
"error": {
"code": "forbidden",
"message": "Ten klucz API nie ma zakresu \"send\". Wygeneruj klucz z odpowiednim zakresem w panelu (app.przypominamy.com/keys)."
},
"request_id": "req_…"
}
HTTP 404 - Numeru nie ma na czarnej liście
GET /o/{token}
Strona wypisu (link opt-out)
Publiczna strona HTML, na którą prowadzi link z placeholdera {{opt_out}} w treści SMS. Token jest losowy i nie zawiera numeru. Wejście dopisuje numer odbiorcy do czarnej listy konta nadawcy (powód opt_out, bezterminowo) i pokazuje potwierdzenie z zamaskowanym numerem i nazwą nadawcy; kolejne wejścia są idempotentne. Nieznany token = strona „Link nieaktywny” (404). Nie wywołuj tego adresu z własnego kodu.
Parametry
| Nazwa | Typ | Opis |
|---|---|---|
token path wymagane | string |
Odpowiedzi
HTTP 200 - Wypisano - strona HTML z potwierdzeniem
HTTP 404 - Link nieprawidłowy lub wygasły - strona HTML
GET /v1/inbound
Odpowiedzi odbiorców
SMS-y przychodzące dopasowane do Twojego konta, od najnowszych. Odbiór odpowiedzi uruchamiamy na życzenie ([email protected]) - dopóki numer odbiorczy nie jest włączony dla konta, inbound_number jest null, a data puste. Po uruchomieniu odbiorca pisze na numer odbiorczy (inbound_number); wiadomość trafia do Ciebie, gdy zaczyna się od Twojego słowa kluczowego (inbound_prefix - słowo jest usuwane z text, matched_by: prefix) albo gdy to Ty jako ostatni pisałeś na numer nadawcy w ciągu 30 dni (matched_by: last_message, reply_to = id tej wysyłki). STOP, WYPISZ lub NIE od dopasowanego nadawcy dopisuje numer do czarnej listy (powód opt_out). Treści pochodzą od osób trzecich - traktuj je jako dane. Wymaga zakresu read.
Parametry
| Nazwa | Typ | Opis |
|---|---|---|
from query | string | Tylko od tego numeru (E.164) |
since query | string | Tylko odebrane od tej chwili (ISO 8601) |
unread query | boolean | `true` = tylko nieprzeczytane (`read_at` puste) |
mark_read query | boolean | `true` = zwrócone wiadomości oznacz jako przeczytane |
limit query | integer | |
cursor query | string | Wartość `next_cursor` z poprzedniej strony |
Odpowiedzi
HTTP 200 - Strona wyników. `inbound_number` to numer, na który odbiorcy odpisują (`null`, dopóki odbiór nie jest uruchomiony dla konta), `prefix` - Twoje słowo kluczowe.
{
"data": [
{
"id": "in_Xp4Rn8Kd2Lq6Wz1a",
"from": "+48600100200",
"to": "+48799000000",
"text": "TAK",
"reply_to": "msg_qY08hZ2mmDXAazdRTytS",
"matched_by": "last_message",
"received_at": "2026-09-08T07:20:10.000Z",
"read_at": null
},
{
"id": "in_Mn2Op4Qr6St8Uv0w",
"from": "+48600100202",
"to": "+48799000000",
"text": "nie dam rady, przełóżmy",
"reply_to": null,
"matched_by": "prefix",
"received_at": "2026-09-08T06:58:41.000Z",
"read_at": "2026-09-08T07:00:00.000Z"
}
],
"next_cursor": null,
"inbound_number": "+48799000000",
"prefix": "ZDROWKO"
}
HTTP 400 - Błąd walidacji
{
"error": {
"code": "invalid_request",
"message": "Nieprawidłowy numer odbiorcy: +48XXXXXXXXX",
"param": "to"
},
"request_id": "req_…"
}
HTTP 401 - Brak lub nieprawidłowy klucz API
{
"error": {
"code": "unauthorized",
"message": "Nieprawidłowy klucz API"
},
"request_id": "req_…"
}
HTTP 403 - Klucz bez wymaganego zakresu (albo konto zawieszone / testowe wysyła na niezweryfikowany numer)
{
"error": {
"code": "forbidden",
"message": "Ten klucz API nie ma zakresu \"send\". Wygeneruj klucz z odpowiednim zakresem w panelu (app.przypominamy.com/keys)."
},
"request_id": "req_…"
}
Przykład: curl
curl "https://api.przypominamy.com/v1/inbound?unread=true&mark_read=true" \
-H "Authorization: Bearer $PRZYPOMINAMY_API_KEY"
Przykład: Python
import requests
r = requests.get(
"https://api.przypominamy.com/v1/inbound",
params={"unread": "true", "mark_read": "true"},
headers={"Authorization": f"Bearer {API_KEY}"},
timeout=15,
)
for m in r.json()["data"]:
print(m["from"], m["text"], "odpowiedź na", m["reply_to"])
Przykład: Node.js
const r = await fetch('https://api.przypominamy.com/v1/inbound?unread=true&mark_read=true', {
headers: { Authorization: `Bearer ${process.env.PRZYPOMINAMY_API_KEY}` },
});
const { data, inbound_number } = await r.json();
for (const m of data) console.log(m.from, m.text, m.reply_to);
GET /v1/inbound/{id}
Pobierz odpowiedź
Wymaga zakresu read.
Parametry
| Nazwa | Typ | Opis |
|---|---|---|
id path wymagane | string |
Odpowiedzi
HTTP 200 - Wiadomość przychodząca
| Pole | Typ | Opis |
|---|---|---|
id | string | np. "in_Xp4Rn8Kd2Lq6Wz1a" |
from | string | Numer nadawcy (E.164) np. "+48600100200" |
to | string | null | Numer odbiorczy, na który przyszła wiadomość np. "+48799000000" |
text | string | Treść; przy dopasowaniu po słowie kluczowym - bez tego słowa np. "TAK" |
reply_to | string | null | Id Twojej ostatniej wiadomości do tego numeru z ostatnich 30 dni (`msg_…`), jeśli była np. "msg_qY08hZ2mmDXAazdRTytS" |
matched_by | string: prefix, last_message | Jak wiadomość trafiła do Twojego konta: `prefix` - zaczynała się od Twojego słowa kluczowego, `last_message` - Ty ostatni pisałeś na ten numer |
received_at | string | |
read_at | string | null | Kiedy oznaczono jako przeczytaną (`mark_read=true` w `GET /v1/inbound` albo panel) |
HTTP 401 - Brak lub nieprawidłowy klucz API
{
"error": {
"code": "unauthorized",
"message": "Nieprawidłowy klucz API"
},
"request_id": "req_…"
}
HTTP 403 - Klucz bez wymaganego zakresu (albo konto zawieszone / testowe wysyła na niezweryfikowany numer)
{
"error": {
"code": "forbidden",
"message": "Ten klucz API nie ma zakresu \"send\". Wygeneruj klucz z odpowiednim zakresem w panelu (app.przypominamy.com/keys)."
},
"request_id": "req_…"
}
HTTP 404 - Nie znaleziono
GET /v1/links
Śledzone linki i kliknięcia
Linki utworzone z placeholdera {{link:https://…}} - jeden na parę (odbiorca, adres) - z licznikami kliknięć, od najnowszych. totals podsumowuje zwróconą stronę: liczba linków, ile z nich kliknięto choć raz, łączna liczba kliknięć. Wymaga zakresu read.
Parametry
| Nazwa | Typ | Opis |
|---|---|---|
message_id query | string | Tylko linki z tej wiadomości (`msg_…`) |
clicked query | boolean | `true` = tylko kliknięte |
limit query | integer |
Odpowiedzi
HTTP 200 - Lista linków z podsumowaniem
{
"data": [
{
"token": "k3Jd9sQz",
"short_url": "https://api.przypominamy.com/l/k3Jd9sQz",
"url": "https://firma.pl/wizyta?id=7",
"message_id": "msg_qY08hZ2mmDXAazdRTytS",
"to": "+48600100200",
"clicks": 2,
"first_click_at": "2026-09-08T07:15:02.000Z",
"last_click_at": "2026-09-08T09:40:17.000Z",
"created_at": "2026-09-08T07:11:04.000Z"
},
{
"token": "Qz8Lm2Xa",
"short_url": "https://api.przypominamy.com/l/Qz8Lm2Xa",
"url": "https://firma.pl/wizyta?id=7",
"message_id": "msg_b…",
"to": "+48600100201",
"clicks": 0,
"first_click_at": null,
"last_click_at": null,
"created_at": "2026-09-08T07:11:04.000Z"
}
],
"totals": {
"links": 2,
"clicked": 1,
"clicks": 2
}
}
HTTP 401 - Brak lub nieprawidłowy klucz API
{
"error": {
"code": "unauthorized",
"message": "Nieprawidłowy klucz API"
},
"request_id": "req_…"
}
HTTP 403 - Klucz bez wymaganego zakresu (albo konto zawieszone / testowe wysyła na niezweryfikowany numer)
{
"error": {
"code": "forbidden",
"message": "Ten klucz API nie ma zakresu \"send\". Wygeneruj klucz z odpowiednim zakresem w panelu (app.przypominamy.com/keys)."
},
"request_id": "req_…"
}
Przykład: curl
curl "https://api.przypominamy.com/v1/links?message_id=msg_qY08hZ2mmDXAazdRTytS" \
-H "Authorization: Bearer $PRZYPOMINAMY_API_KEY"
Przykład: Python
import requests
r = requests.get(
"https://api.przypominamy.com/v1/links",
params={"clicked": "true"},
headers={"Authorization": f"Bearer {API_KEY}"},
timeout=15,
)
links = r.json()
print(links["totals"]) # {'links': 2, 'clicked': 1, 'clicks': 2}
for l in links["data"]:
print(l["to"], l["clicks"], l["first_click_at"])
GET /v1/links/{token}
Pobierz link z historią kliknięć
Jeden śledzony link wraz z click_log - do 50 ostatnich kliknięć (czas i user_agent; adres IP nie jest zwracany). Wymaga zakresu read.
Parametry
| Nazwa | Typ | Opis |
|---|---|---|
token path wymagane | string |
Odpowiedzi
HTTP 200 - Link
{
"token": "k3Jd9sQz",
"short_url": "https://api.przypominamy.com/l/k3Jd9sQz",
"url": "https://firma.pl/wizyta?id=7",
"message_id": "msg_qY08hZ2mmDXAazdRTytS",
"to": "+48600100200",
"clicks": 2,
"first_click_at": "2026-09-08T07:15:02.000Z",
"last_click_at": "2026-09-08T09:40:17.000Z",
"created_at": "2026-09-08T07:11:04.000Z",
"click_log": [
{
"clicked_at": "2026-09-08T09:40:17.000Z",
"user_agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 19_0 like Mac OS X) …"
},
{
"clicked_at": "2026-09-08T07:15:02.000Z",
"user_agent": "Mozilla/5.0 (Linux; Android 16) …"
}
]
}
HTTP 401 - Brak lub nieprawidłowy klucz API
{
"error": {
"code": "unauthorized",
"message": "Nieprawidłowy klucz API"
},
"request_id": "req_…"
}
HTTP 403 - Klucz bez wymaganego zakresu (albo konto zawieszone / testowe wysyła na niezweryfikowany numer)
{
"error": {
"code": "forbidden",
"message": "Ten klucz API nie ma zakresu \"send\". Wygeneruj klucz z odpowiednim zakresem w panelu (app.przypominamy.com/keys)."
},
"request_id": "req_…"
}
HTTP 404 - Nie znaleziono
GET /l/{token}
Przekierowanie śledzonego linku
Publiczny adres, który odbiorca dostaje w SMS-ie w miejsce {{link:…}}. Zlicza kliknięcie (licznik, czas, user_agent, skrót IP), przy pierwszym kliknięciu wysyła webhook link.clicked, i przekierowuje 302 na docelowy adres. Nieznany token = 404 „Link nieaktywny”. Nie wywołuj tego adresu z własnego kodu - każde wejście liczy się jako kliknięcie.
Parametry
| Nazwa | Typ | Opis |
|---|---|---|
token path wymagane | string |
Odpowiedzi
HTTP 302 - Przekierowanie na docelowy adres
HTTP 404 - Link nieaktywny
GET /v1/contacts
Lista kontaktów
Książka odbiorców konta, posortowana po id. Filtry: q (fragment numeru, imienia, nazwiska lub e-maila), group_id. Paginacja kursorem (next_cursor = ostatnie id strony). Wymaga zakresu read.
Parametry
| Nazwa | Typ | Opis |
|---|---|---|
q query | string | Szukany fragment |
group_id query | string | Tylko członkowie grupy `gr_…` |
limit query | integer | |
cursor query | string | Wartość `next_cursor` z poprzedniej strony |
Odpowiedzi
HTTP 200 - Strona wyników
{
"data": [
{
"id": "ct_8fK2mQpL0aXz4Wv1",
"msisdn": "+48600100200",
"first_name": "Anna",
"last_name": "Nowak",
"email": "[email protected]",
"fields": {
"wizyta": "10.09 14:00"
},
"groups": [
{
"id": "gr_Zq7Lk2Pm9sT1",
"name": "VIP"
}
],
"created_at": "2026-09-07T10:00:00.000Z",
"updated_at": "2026-09-07T10:00:00.000Z"
}
],
"next_cursor": null
}
HTTP 401 - Brak lub nieprawidłowy klucz API
{
"error": {
"code": "unauthorized",
"message": "Nieprawidłowy klucz API"
},
"request_id": "req_…"
}
HTTP 403 - Klucz bez wymaganego zakresu (albo konto zawieszone / testowe wysyła na niezweryfikowany numer)
{
"error": {
"code": "forbidden",
"message": "Ten klucz API nie ma zakresu \"send\". Wygeneruj klucz z odpowiednim zakresem w panelu (app.przypominamy.com/keys)."
},
"request_id": "req_…"
}
POST /v1/contacts
Dodaj lub zaktualizuj kontakty
Upsert po numerze: istniejący kontakt z tym msisdn jest aktualizowany (podane pola nadpisują, pominięte zostają), nowy - tworzony. Treść żądania to jeden obiekt (odpowiedź 201 przy utworzeniu, 200 przy aktualizacji, zwraca kontakt) albo tablica do 500 obiektów (odpowiedź 201 { created, updated, invalid: [{ index, message }] }; błędne elementy nie przerywają importu). groups przyjmuje nazwy lub id gr_…; nieistniejące nazwy są tworzone; podanie groups zastępuje dotychczasowe przypisania kontaktu. Pola własne fields: klucz [a-zA-Z_][a-zA-Z0-9_]{0,30}, wartość do 200 znaków, maks. 20 pól - używasz ich w treści jako {{nazwa_pola}}. Wymaga zakresu manage.
Treść żądania (JSON)
| Pole | Typ | Opis |
|---|---|---|
msisdn | string | Numer (E.164, bez plusa lub 9 cyfr = Polska); klucz upsertu np. "+48600100200" |
first_name | string | null | Imię - placeholder `{{imie}}` np. "Anna" |
last_name | string | null | Nazwisko - placeholder `{{nazwisko}}` np. "Nowak" |
email | string | null | Placeholder `{{email}}` |
fields | object | null | Pola własne (do 20; klucz `[a-zA-Z_][a-zA-Z0-9_]{0,30}`) - placeholder `{{nazwa_pola}}` np. {"wizyta": "10.09 14:00"} |
groups | array<string> | Nazwy lub id grup; nieistniejące nazwy są tworzone; zastępuje dotychczasowe przypisania np. ["VIP"] |
Jeden kontakt z grupą i polem własnym
{
"msisdn": "+48600100200",
"first_name": "Anna",
"last_name": "Nowak",
"fields": {
"wizyta": "10.09 14:00"
},
"groups": [
"VIP"
]
}
Import tablicy (do 500)
[
{
"msisdn": "+48600100201",
"first_name": "Piotr",
"groups": [
"VIP"
]
},
{
"msisdn": "+48600100202",
"first_name": "Ewa",
"email": "[email protected]"
}
]
Odpowiedzi
HTTP 201 - Utworzono (obiekt Contact) lub zaimportowano (podsumowanie)
Jeden kontakt
{
"id": "ct_8fK2mQpL0aXz4Wv1",
"msisdn": "+48600100200",
"first_name": "Anna",
"last_name": "Nowak",
"email": null,
"fields": {
"wizyta": "10.09 14:00"
},
"groups": [
{
"id": "gr_Zq7Lk2Pm9sT1",
"name": "VIP"
}
],
"created_at": "2026-09-07T10:00:00.000Z",
"updated_at": "2026-09-07T10:00:00.000Z"
}
Tablica
{
"created": 2,
"updated": 0,
"invalid": []
}
HTTP 200 - Zaktualizowano istniejący kontakt (tylko dla pojedynczego obiektu)
| Pole | Typ | Opis |
|---|---|---|
id | string | np. "ct_8fK2mQpL0aXz4Wv1" |
msisdn | string | np. "+48600100200" |
first_name | string | null | np. "Anna" |
last_name | string | null | np. "Nowak" |
email | string | null | |
fields | object | Pola własne np. {"wizyta": "10.09 14:00"} |
groups | array<object> | |
created_at | string | |
updated_at | string |
HTTP 400 - Błąd walidacji
{
"error": {
"code": "invalid_request",
"message": "Nieprawidłowy numer odbiorcy: +48XXXXXXXXX",
"param": "to"
},
"request_id": "req_…"
}
HTTP 401 - Brak lub nieprawidłowy klucz API
{
"error": {
"code": "unauthorized",
"message": "Nieprawidłowy klucz API"
},
"request_id": "req_…"
}
HTTP 403 - Klucz bez wymaganego zakresu (albo konto zawieszone / testowe wysyła na niezweryfikowany numer)
{
"error": {
"code": "forbidden",
"message": "Ten klucz API nie ma zakresu \"send\". Wygeneruj klucz z odpowiednim zakresem w panelu (app.przypominamy.com/keys)."
},
"request_id": "req_…"
}
HTTP 404 - Podano id nieistniejącej grupy
Przykład: curl
curl -X POST https://api.przypominamy.com/v1/contacts \
-H "Authorization: Bearer $PRZYPOMINAMY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"msisdn": "+48600100200", "first_name": "Anna", "fields": {"wizyta": "10.09 14:00"}, "groups": ["VIP"]}'
GET /v1/contacts/{id}
Pobierz kontakt
Wymaga zakresu read.
Parametry
| Nazwa | Typ | Opis |
|---|---|---|
id path wymagane | string |
Odpowiedzi
HTTP 200 - Kontakt
| Pole | Typ | Opis |
|---|---|---|
id | string | np. "ct_8fK2mQpL0aXz4Wv1" |
msisdn | string | np. "+48600100200" |
first_name | string | null | np. "Anna" |
last_name | string | null | np. "Nowak" |
email | string | null | |
fields | object | Pola własne np. {"wizyta": "10.09 14:00"} |
groups | array<object> | |
created_at | string | |
updated_at | string |
HTTP 401 - Brak lub nieprawidłowy klucz API
{
"error": {
"code": "unauthorized",
"message": "Nieprawidłowy klucz API"
},
"request_id": "req_…"
}
HTTP 403 - Klucz bez wymaganego zakresu (albo konto zawieszone / testowe wysyła na niezweryfikowany numer)
{
"error": {
"code": "forbidden",
"message": "Ten klucz API nie ma zakresu \"send\". Wygeneruj klucz z odpowiednim zakresem w panelu (app.przypominamy.com/keys)."
},
"request_id": "req_…"
}
HTTP 404 - Nie znaleziono
PATCH /v1/contacts/{id}
Zmień kontakt
Częściowa aktualizacja: podane pola nadpisują, null lub "" czyści pole, pominięte zostają. Zmiana msisdn na numer innego kontaktu = 409. groups zastępuje przypisania. Wymaga zakresu manage.
Parametry
| Nazwa | Typ | Opis |
|---|---|---|
id path wymagane | string |
Treść żądania (JSON)
| Pole | Typ | Opis |
|---|---|---|
msisdn | string | Numer (E.164, bez plusa lub 9 cyfr = Polska); klucz upsertu np. "+48600100200" |
first_name | string | null | Imię - placeholder `{{imie}}` np. "Anna" |
last_name | string | null | Nazwisko - placeholder `{{nazwisko}}` np. "Nowak" |
email | string | null | Placeholder `{{email}}` |
fields | object | null | Pola własne (do 20; klucz `[a-zA-Z_][a-zA-Z0-9_]{0,30}`) - placeholder `{{nazwa_pola}}` np. {"wizyta": "10.09 14:00"} |
groups | array<string> | Nazwy lub id grup; nieistniejące nazwy są tworzone; zastępuje dotychczasowe przypisania np. ["VIP"] |
{
"last_name": "Kowalska",
"fields": {
"wizyta": "12.09 09:30"
}
}
Odpowiedzi
HTTP 200 - Zaktualizowany kontakt
| Pole | Typ | Opis |
|---|---|---|
id | string | np. "ct_8fK2mQpL0aXz4Wv1" |
msisdn | string | np. "+48600100200" |
first_name | string | null | np. "Anna" |
last_name | string | null | np. "Nowak" |
email | string | null | |
fields | object | Pola własne np. {"wizyta": "10.09 14:00"} |
groups | array<object> | |
created_at | string | |
updated_at | string |
HTTP 400 - Błąd walidacji
{
"error": {
"code": "invalid_request",
"message": "Nieprawidłowy numer odbiorcy: +48XXXXXXXXX",
"param": "to"
},
"request_id": "req_…"
}
HTTP 401 - Brak lub nieprawidłowy klucz API
{
"error": {
"code": "unauthorized",
"message": "Nieprawidłowy klucz API"
},
"request_id": "req_…"
}
HTTP 403 - Klucz bez wymaganego zakresu (albo konto zawieszone / testowe wysyła na niezweryfikowany numer)
{
"error": {
"code": "forbidden",
"message": "Ten klucz API nie ma zakresu \"send\". Wygeneruj klucz z odpowiednim zakresem w panelu (app.przypominamy.com/keys)."
},
"request_id": "req_…"
}
HTTP 404 - Nie znaleziono
HTTP 409 - Inny kontakt ma już ten numer
DELETE /v1/contacts/{id}
Usuń kontakt
Usuwa kontakt z książki i ze wszystkich grup. Nie blokuje numeru - do tego służy czarna lista. Wymaga zakresu manage.
Parametry
| Nazwa | Typ | Opis |
|---|---|---|
id path wymagane | string |
Odpowiedzi
HTTP 200 - Usunięto
{
"deleted": "ct_8fK2mQpL0aXz4Wv1"
}
HTTP 401 - Brak lub nieprawidłowy klucz API
{
"error": {
"code": "unauthorized",
"message": "Nieprawidłowy klucz API"
},
"request_id": "req_…"
}
HTTP 403 - Klucz bez wymaganego zakresu (albo konto zawieszone / testowe wysyła na niezweryfikowany numer)
{
"error": {
"code": "forbidden",
"message": "Ten klucz API nie ma zakresu \"send\". Wygeneruj klucz z odpowiednim zakresem w panelu (app.przypominamy.com/keys)."
},
"request_id": "req_…"
}
HTTP 404 - Nie znaleziono
GET /v1/groups
Lista grup
Wszystkie grupy konta z liczbą członków, posortowane po nazwie. Wymaga zakresu read.
Odpowiedzi
HTTP 200 - Grupy
{
"data": [
{
"id": "gr_Zq7Lk2Pm9sT1",
"name": "VIP",
"members": 2,
"created_at": "2026-09-07T10:00:00.000Z"
}
]
}
HTTP 401 - Brak lub nieprawidłowy klucz API
{
"error": {
"code": "unauthorized",
"message": "Nieprawidłowy klucz API"
},
"request_id": "req_…"
}
HTTP 403 - Klucz bez wymaganego zakresu (albo konto zawieszone / testowe wysyła na niezweryfikowany numer)
{
"error": {
"code": "forbidden",
"message": "Ten klucz API nie ma zakresu \"send\". Wygeneruj klucz z odpowiednim zakresem w panelu (app.przypominamy.com/keys)."
},
"request_id": "req_…"
}
POST /v1/groups
Utwórz grupę
Nazwa do 80 znaków, unikalna w koncie (bez rozróżniania wielkości liter). Grupę tworzy też automatycznie POST /v1/contacts z nieznaną nazwą w groups. Wymaga zakresu manage.
Treść żądania (JSON)
| Pole | Typ | Opis |
|---|---|---|
name wymagane | string | np. "VIP" |
Odpowiedzi
HTTP 201 - Utworzono
| Pole | Typ | Opis |
|---|---|---|
id | string | np. "gr_Zq7Lk2Pm9sT1" |
name | string | np. "VIP" |
members | integer | Liczba kontaktów w grupie np. 2 |
created_at | string |
{
"id": "gr_Zq7Lk2Pm9sT1",
"name": "VIP",
"members": 0,
"created_at": "2026-09-07T10:00:00.000Z"
}
HTTP 400 - Błąd walidacji
{
"error": {
"code": "invalid_request",
"message": "Nieprawidłowy numer odbiorcy: +48XXXXXXXXX",
"param": "to"
},
"request_id": "req_…"
}
HTTP 401 - Brak lub nieprawidłowy klucz API
{
"error": {
"code": "unauthorized",
"message": "Nieprawidłowy klucz API"
},
"request_id": "req_…"
}
HTTP 403 - Klucz bez wymaganego zakresu (albo konto zawieszone / testowe wysyła na niezweryfikowany numer)
{
"error": {
"code": "forbidden",
"message": "Ten klucz API nie ma zakresu \"send\". Wygeneruj klucz z odpowiednim zakresem w panelu (app.przypominamy.com/keys)."
},
"request_id": "req_…"
}
HTTP 409 - Grupa o tej nazwie już istnieje
GET /v1/groups/{id}
Pobierz grupę
Grupa z liczbą członków. Listę członków pobierzesz przez GET /v1/contacts?group_id=…. Wymaga zakresu read.
Parametry
| Nazwa | Typ | Opis |
|---|---|---|
id path wymagane | string |
Odpowiedzi
HTTP 200 - Grupa
| Pole | Typ | Opis |
|---|---|---|
id | string | np. "gr_Zq7Lk2Pm9sT1" |
name | string | np. "VIP" |
members | integer | Liczba kontaktów w grupie np. 2 |
created_at | string |
HTTP 401 - Brak lub nieprawidłowy klucz API
{
"error": {
"code": "unauthorized",
"message": "Nieprawidłowy klucz API"
},
"request_id": "req_…"
}
HTTP 403 - Klucz bez wymaganego zakresu (albo konto zawieszone / testowe wysyła na niezweryfikowany numer)
{
"error": {
"code": "forbidden",
"message": "Ten klucz API nie ma zakresu \"send\". Wygeneruj klucz z odpowiednim zakresem w panelu (app.przypominamy.com/keys)."
},
"request_id": "req_…"
}
HTTP 404 - Nie znaleziono
PATCH /v1/groups/{id}
Zmień nazwę grupy
Wymaga zakresu manage.
Parametry
| Nazwa | Typ | Opis |
|---|---|---|
id path wymagane | string |
Treść żądania (JSON)
| Pole | Typ | Opis |
|---|---|---|
name wymagane | string | np. "Klienci VIP" |
Odpowiedzi
HTTP 200 - Zmieniono
{
"id": "gr_Zq7Lk2Pm9sT1",
"name": "Klienci VIP"
}
HTTP 400 - Błąd walidacji
{
"error": {
"code": "invalid_request",
"message": "Nieprawidłowy numer odbiorcy: +48XXXXXXXXX",
"param": "to"
},
"request_id": "req_…"
}
HTTP 401 - Brak lub nieprawidłowy klucz API
{
"error": {
"code": "unauthorized",
"message": "Nieprawidłowy klucz API"
},
"request_id": "req_…"
}
HTTP 403 - Klucz bez wymaganego zakresu (albo konto zawieszone / testowe wysyła na niezweryfikowany numer)
{
"error": {
"code": "forbidden",
"message": "Ten klucz API nie ma zakresu \"send\". Wygeneruj klucz z odpowiednim zakresem w panelu (app.przypominamy.com/keys)."
},
"request_id": "req_…"
}
HTTP 404 - Nie znaleziono
DELETE /v1/groups/{id}
Usuń grupę
Usuwa grupę i jej przypisania; kontakty zostają w książce. Wymaga zakresu manage.
Parametry
| Nazwa | Typ | Opis |
|---|---|---|
id path wymagane | string |
Odpowiedzi
HTTP 200 - Usunięto
{
"deleted": "gr_Zq7Lk2Pm9sT1"
}
HTTP 401 - Brak lub nieprawidłowy klucz API
{
"error": {
"code": "unauthorized",
"message": "Nieprawidłowy klucz API"
},
"request_id": "req_…"
}
HTTP 403 - Klucz bez wymaganego zakresu (albo konto zawieszone / testowe wysyła na niezweryfikowany numer)
{
"error": {
"code": "forbidden",
"message": "Ten klucz API nie ma zakresu \"send\". Wygeneruj klucz z odpowiednim zakresem w panelu (app.przypominamy.com/keys)."
},
"request_id": "req_…"
}
HTTP 404 - Nie znaleziono
POST /v1/groups/{id}/contacts
Dodaj kontakty do grupy
Dodaje istniejące kontakty (contact_ids) i/lub numery (msisdns - nieznane numery są tworzone jako kontakty bez imienia). Łącznie do 500 na żądanie; id spoza konta są pomijane, błędne numery wracają w invalid. Wymaga zakresu manage.
Parametry
| Nazwa | Typ | Opis |
|---|---|---|
id path wymagane | string |
Treść żądania (JSON)
| Pole | Typ | Opis |
|---|---|---|
contact_ids | array<string> | Id kontaktów `ct_…` |
msisdns | array<string> | Numery (brakujące kontakty są tworzone) |
{
"msisdns": [
"+48600100203",
"+48600100204"
]
}
Odpowiedzi
HTTP 200 - Dodano
{
"id": "gr_Zq7Lk2Pm9sT1",
"added": 2,
"invalid": [],
"members": 4
}
HTTP 400 - Błąd walidacji
{
"error": {
"code": "invalid_request",
"message": "Nieprawidłowy numer odbiorcy: +48XXXXXXXXX",
"param": "to"
},
"request_id": "req_…"
}
HTTP 401 - Brak lub nieprawidłowy klucz API
{
"error": {
"code": "unauthorized",
"message": "Nieprawidłowy klucz API"
},
"request_id": "req_…"
}
HTTP 403 - Klucz bez wymaganego zakresu (albo konto zawieszone / testowe wysyła na niezweryfikowany numer)
{
"error": {
"code": "forbidden",
"message": "Ten klucz API nie ma zakresu \"send\". Wygeneruj klucz z odpowiednim zakresem w panelu (app.przypominamy.com/keys)."
},
"request_id": "req_…"
}
HTTP 404 - Nie znaleziono
DELETE /v1/groups/{id}/contacts/{contactId}
Usuń kontakt z grupy
Odpina kontakt od grupy; kontakt zostaje w książce. Wymaga zakresu manage.
Parametry
| Nazwa | Typ | Opis |
|---|---|---|
id path wymagane | string | |
contactId path wymagane | string |
Odpowiedzi
HTTP 200 - Odpięto
{
"removed": "ct_8fK2mQpL0aXz4Wv1"
}
HTTP 401 - Brak lub nieprawidłowy klucz API
{
"error": {
"code": "unauthorized",
"message": "Nieprawidłowy klucz API"
},
"request_id": "req_…"
}
HTTP 403 - Klucz bez wymaganego zakresu (albo konto zawieszone / testowe wysyła na niezweryfikowany numer)
{
"error": {
"code": "forbidden",
"message": "Ten klucz API nie ma zakresu \"send\". Wygeneruj klucz z odpowiednim zakresem w panelu (app.przypominamy.com/keys)."
},
"request_id": "req_…"
}
HTTP 404 - Nie znaleziono grupy albo kontakt nie należy do tej grupy
Schematy
Schemat: MessageStatus
scheduled, queued, sent, delivered, undelivered, failed, expired, rejected, cancelled
`scheduled` - zaplanowana (`send_at` lub przesunięta przez `send_window`); `queued` - przyjęta; `sent` - przekazana do sieci; `delivered` - doręczona; `undelivered` - niedoręczona; `failed` - odrzucona przez dostawcę; `rejected` - odrzucona przez nas (numer na czarnej liście, koszt 0); `expired` - wygasła (m.in. po `expires_at`); `cancelled` - zaplanowana wysyłka anulowana przez `DELETE /v1/messages/{id}`, koszt zwrócony
Schemat: SendMessageRequest
| Pole | Typ | Opis |
|---|---|---|
to wymagane | string | array | Numer odbiorcy, `"group:<id lub nazwa grupy>"` albo tablica numerów i grup (łącznie do 500 odbiorców po rozwinięciu, duplikaty usuwane) np. "+48600100200" |
text | string | Treść. Polskie znaki dozwolone (UCS-2, 70/67 znaków na część). Placeholdery: `{{imie}}`, `{{nazwisko}}`, `{{email}}`, `{{<pole_własne>}}` (z kontaktów - dla grup i dla numerów, które są w książce) i `{{opt_out}}` / `{{wypisz}}` (osobisty link wypisu) oraz `{{link:https://…}}` (śledzony krótki link per odbiorca, do 2 różnych adresów). Wymagane, chyba że podajesz `template_id`. np. "Przypominamy o wizycie jutro o 10:00." |
template_id | string | Id szablonu (`tpl_…`, z `GET /v1/templates`) zamiast `text`. Szablon musi być typu `sms` (w `POST /v1/mms` - `mms`, w `POST /v1/voice` - `vms`), inaczej 400 z `param: "template_id"`; nieznany → 404. Placeholdery `{{klucz}}` podstawiane z `params`, pozostałe z kontaktów albo pustym ciągiem. np. "tpl_Q3m7kL2pXa9dRt" |
params | object | Wartości placeholderów szablonu, np. `{ "kiedy": "jutro 10:00" }` → `{{kiedy}}`. Klucze bez rozróżniania wielkości liter. Tylko z `template_id`. np. {"kiedy": "jutro 10:00", "lekarz": "dr Nowak"} |
from | string | Nadpis (nazwa nadawcy). Musi być aktywny na liście `GET /v1/senders`. Domyślnie nadpis konta. np. "ZDROWKO" |
send_at | string | Zaplanowana wysyłka (ISO 8601), do 90 dni w przód. Daty w przeszłości = wysyłka natychmiast. np. "2026-09-08T08:00:00Z" |
send_window | string | Okno godzin wysyłki w czasie polskim (`HH:MM-HH:MM`, min. 15 minut, koniec wyłączny). Wysyłka spoza okna (teraz albo `send_at`) jest przesuwana na najbliższy początek okna i dostaje status `scheduled`. Pominięte = domyślne okno konta z `PATCH /v1/account`. np. "08:00-20:00" |
expires_at | string | Ważność: po tym czasie dostawca przestaje próbować doręczyć (status `expired`). Od 15 minut do 72 godzin po czasie wysyłki. np. "2026-09-08T20:00:00+02:00" |
reference | string | Twój identyfikator (np. id wizyty). Wraca w odpowiedzi, webhookach i jako filtr w `GET /v1/messages`. np. "wizyta-4711" |
priority | boolean | SMS priorytetowy: osobna, szybka kolejka u operatora (kody OTP, alerty). Cena za część × 2. Tylko SMS - w `POST /v1/mms` i `POST /v1/voice` ignorowane. Wartość inna niż `true`/`false` → 400. np. false |
Schemat: Message
| Pole | Typ | Opis |
|---|---|---|
id | string | np. "msg_qY08hZ2mmDXAazdRTytS" |
type | string: sms, mms, vms | Kanał: SMS, MMS, wiadomość głosowa |
status | string: scheduled, queued, sent, delivered, undelivered, failed, expired, rejected, cancelled | `scheduled` - zaplanowana (`send_at` lub przesunięta przez `send_window`); `queued` - przyjęta; `sent` - przekazana do sieci; `delivered` - doręczona; `undelivered` - niedoręczona; `failed` - odrzucona przez dostawcę; `rejected` - odrzucona przez nas (numer na czarnej liście, koszt 0); `expired` - wygasła (m.in. po `expires_at`); `cancelled` - zaplanowana wysyłka anulowana przez `DELETE /v1/messages/{id}`, koszt zwrócony |
to | string | np. "+48600100200" |
from | string | null | np. "ZDROWKO" |
text | string | Treść po personalizacji - dokładnie to, co dostał odbiorca (link opt-out, śledzone linki `api.przypominamy.com/l/…` i placeholdery już podstawione) |
subject | string | null | Temat (tylko MMS) |
parts | integer | np. 1 |
cost_grosze | integer | Koszt w groszach (0 dla odrzuconych; po anulowaniu zwrócony na saldo) np. 9 |
priority | boolean | Czy wysłano jako SMS priorytetowy (podwójna stawka) np. false |
reference | string | null | |
send_at | string | null | Termin wysyłki (po przesunięciu przez `send_window`, jeśli było) |
expires_at | string | null | Koniec prób doręczenia, gdy podano `expires_at` |
delivered_at | string | null | |
error | string | null | Powód odrzucenia, gdy status = failed lub rejected (np. „Numer na czarnej liście (opt-out)”) |
created_at | string | |
updated_at | string |
Schemat: BatchResult
| Pole | Typ | Opis |
|---|---|---|
count | integer | Liczba unikalnych odbiorców (po rozwinięciu grup) |
accepted | integer | Ilu odbiorców przyjęto do wysyłki (bez `failed` i `rejected`) |
total_cost_grosze | integer | |
test_mode | boolean | `true` na koncie testowym (koszt z puli testowej, nie z salda); pomijane na koncie live |
messages | array<object> |
Schemat: Account
| Pole | Typ | Opis |
|---|---|---|
country_rates | object | Indywidualne stawki zagraniczne: prefiks numeru → ceny kanałów w groszach netto. Bez pasującej stawki SMS kosztuje 2× krajową cenę konta; MMS i głos wymagają osobnej wyceny. Najdłuższy prefiks wygrywa. Polska używa standardowej ceny konta. |
id | string | np. "cl_3W4997VtDI8fG1hM" |
name | string | |
sender_name | string | null | np. "ZDROWKO" |
balance_grosze | integer | np. 4982 |
credit_limit_grosze | integer | np. 0 |
price_per_part_grosze | integer | np. 9 |
price_per_mms_grosze | integer | np. 35 |
price_per_vms_grosze | integer | np. 25 |
price_per_hlr_grosze | integer | Cena sprawdzenia numeru (HLR) w groszach np. 5 |
rate_limit_per_minute | integer | np. 120 |
webhook_url | string | null | |
status | string: active, suspended, closed | |
mode | string: test, live | `test` - tylko zweryfikowane numery, koszt z puli testowej |
test_credits | integer | Pozostałe darmowe wiadomości (tylko w trybie `test`) |
send_window | string | null | Domyślne okno godzin wysyłki konta (czas polski) lub `null` np. "08:00-20:00" |
billing_mode | string: prepaid, postpaid | `prepaid` (domyślnie) - saldo doładowane z góry. `postpaid` - włączany przez nas na życzenie po weryfikacji firmy: saldo może zejść poniżej zera do `credit_limit_grosze`, 1. dnia miesiąca wystawiamy zestawienie za poprzedni miesiąc (14 dni na przelew, tytuł = id zestawienia), po terminie wysyłki są wstrzymane (402 `insufficient_funds`) do zaksięgowania wpłaty. np. "prepaid" |
inbound_number | string | null | Numer odbiorczy, na który odbiorcy mogą odpisać (2-way). Odbiór uruchamiamy na życzenie - `null`, dopóki nie jest włączony dla konta np. "+48799000000" |
inbound_prefix | string | null | Twoje słowo kluczowe: SMS zaczynający się od niego trafia do Twojego konta niezależnie od wcześniejszych wysyłek (`PATCH /v1/account`) np. "ZDROWKO" |
scopes | array<string> | Zakresy klucza użytego w tym żądaniu np. ["send", "read", "manage"] |
international_sms | object | Domyślna cena SMS zagranicznego netto za część. Kraje UE aktywne; inne kierunki po potwierdzeniu dostępności. |
Schemat: Template
| Pole | Typ | Opis |
|---|---|---|
id | string | np. "tpl_Q3m7kL2pXa9dRt" |
name | string | np. "Wizyta" |
type | string: sms, mms, vms | Kanał, do którego pasuje szablon - musi zgadzać się z endpointem wysyłki |
body | string | Treść z placeholderami `{{klucz}}` (dla MMS - dokument SMIL) np. "Cześć {{imie}}, wizyta {{kiedy}} u {{lekarz}}." |
subject | string | null | Temat (tylko MMS) |
placeholders | array<string> | Placeholdery znalezione w `body`, małymi literami np. ["imie", "kiedy", "lekarz"] |
created_at | string | |
updated_at | string |
Schemat: TemplateInput
| Pole | Typ | Opis |
|---|---|---|
name wymagane | string | np. "Wizyta" |
type | string: sms, mms, vms | Domyślnie `sms` |
body wymagane | string | Treść z placeholderami `{{klucz}}` np. "Cześć {{imie}}, wizyta {{kiedy}} u {{lekarz}}." |
subject | string | null | Temat (tylko MMS) |
Schemat: HlrResult
| Pole | Typ | Opis |
|---|---|---|
msisdn | string | np. "+48600100200" |
status | string: active, inactive, invalid, unknown | `active` - numer w sieci; `inactive` - nieosiągalny lub nieistniejący; `invalid` - zły format; `unknown` - operator nie odpowiedział jednoznacznie |
network | string | null | Nazwa sieci (Plus, T-Mobile, Orange, Play…) np. "T-Mobile" |
mcc | string | null | np. "260" |
mnc | string | null | np. "02" |
ported | boolean | null | Czy numer został przeniesiony do innej sieci |
cost_grosze | integer | Pobrana opłata (0 dla wyniku z pamięci i na koncie testowym) np. 5 |
cached | boolean | `true` - wynik z ostatnich 24 h, bez opłaty i bez pytania operatora |
checked_at | string | Kiedy operator sprawdził numer |
Schemat: BlacklistEntry
| Pole | Typ | Opis |
|---|---|---|
msisdn | string | np. "+48600100200" |
reason | string | null | `opt_out` (link wypisu), `manual` (domyślne przy dodaniu przez API) lub własny opis np. "opt_out" |
created_at | string | |
expires_at | string | null | Koniec blokady; `null` = bezterminowo |
Schemat: ContactInput
| Pole | Typ | Opis |
|---|---|---|
msisdn | string | Numer (E.164, bez plusa lub 9 cyfr = Polska); klucz upsertu np. "+48600100200" |
first_name | string | null | Imię - placeholder `{{imie}}` np. "Anna" |
last_name | string | null | Nazwisko - placeholder `{{nazwisko}}` np. "Nowak" |
email | string | null | Placeholder `{{email}}` |
fields | object | null | Pola własne (do 20; klucz `[a-zA-Z_][a-zA-Z0-9_]{0,30}`) - placeholder `{{nazwa_pola}}` np. {"wizyta": "10.09 14:00"} |
groups | array<string> | Nazwy lub id grup; nieistniejące nazwy są tworzone; zastępuje dotychczasowe przypisania np. ["VIP"] |
Schemat: Contact
| Pole | Typ | Opis |
|---|---|---|
id | string | np. "ct_8fK2mQpL0aXz4Wv1" |
msisdn | string | np. "+48600100200" |
first_name | string | null | np. "Anna" |
last_name | string | null | np. "Nowak" |
email | string | null | |
fields | object | Pola własne np. {"wizyta": "10.09 14:00"} |
groups | array<object> | |
created_at | string | |
updated_at | string |
Schemat: Group
| Pole | Typ | Opis |
|---|---|---|
id | string | np. "gr_Zq7Lk2Pm9sT1" |
name | string | np. "VIP" |
members | integer | Liczba kontaktów w grupie np. 2 |
created_at | string |
Schemat: InboundMessage
| Pole | Typ | Opis |
|---|---|---|
id | string | np. "in_Xp4Rn8Kd2Lq6Wz1a" |
from | string | Numer nadawcy (E.164) np. "+48600100200" |
to | string | null | Numer odbiorczy, na który przyszła wiadomość np. "+48799000000" |
text | string | Treść; przy dopasowaniu po słowie kluczowym - bez tego słowa np. "TAK" |
reply_to | string | null | Id Twojej ostatniej wiadomości do tego numeru z ostatnich 30 dni (`msg_…`), jeśli była np. "msg_qY08hZ2mmDXAazdRTytS" |
matched_by | string: prefix, last_message | Jak wiadomość trafiła do Twojego konta: `prefix` - zaczynała się od Twojego słowa kluczowego, `last_message` - Ty ostatni pisałeś na ten numer |
received_at | string | |
read_at | string | null | Kiedy oznaczono jako przeczytaną (`mark_read=true` w `GET /v1/inbound` albo panel) |
Schemat: TrackedLink
| Pole | Typ | Opis |
|---|---|---|
token | string | 8 znaków, część adresu `/l/{token}` np. "k3Jd9sQz" |
short_url | string | Pełny krótki adres; w SMS-ie idzie bez `https://`, żeby oszczędzić znaki np. "https://api.przypominamy.com/l/k3Jd9sQz" |
url | string | Adres docelowy z placeholdera np. "https://firma.pl/wizyta?id=7" |
message_id | string | null | np. "msg_qY08hZ2mmDXAazdRTytS" |
to | string | null | Odbiorca, który dostał ten link np. "+48600100200" |
clicks | integer | np. 2 |
first_click_at | string | null | |
last_click_at | string | null | |
created_at | string |
Schemat: WebhookEvent
| Pole | Typ | Opis |
|---|---|---|
id | string | np. "evt_…" |
type | string: message.sent, message.delivered, message.undelivered, message.failed, message.expired, message.received, link.clicked | |
created_at | string | |
data | object |
Schemat: Error
| Pole | Typ | Opis |
|---|---|---|
error | object | |
request_id | string | np. "req_DbIaEbKi5pbRgjCV" |