Przejdź do głównej zawartości

Wysyłka SMS przez API

API wysyłki SMS pozwala wysyłać wiadomości z Twoją nazwą nadawcy bezpośrednio z Twojego systemu. Możesz wysłać pojedynczą wiadomość, np. powiadomienie o zamówieniu albo kod, albo paczkę do 1000 wiadomości w jednym żądaniu. Koszt i rozliczenie są takie same jak przy wysyłce z panelu.

Wersja API

Ten przewodnik opisuje API v2 (/api/v2/sms). Dotychczasowe API v1 (/api/v1/sending/{klucz}) nadal działa. Różnice opisuje sekcja Przejście z API v1.

Zanim zaczniesz​

  • Usługa Wysyłka SMS jest aktywna na Twoim koncie w panelu.
  • Masz co najmniej jednego zatwierdzonego nadawcę (status active). Nazwy nadawców (do 12 znaków) rejestrujesz w panelu w zakładce Nadawcy.
  • Masz środki: saldo prepaid albo wolny limit postpaid.

Klucz API​

Klucz znajdziesz w panelu: Wysyłka SMS → Dostęp API. Przekazuj go w nagłówku każdego żądania:

Authorization: Bearer TWOJ_KLUCZ

Adres bazowy API to https://panel.dpay.pl/api/v2/sms. Treść żądań to obiekt JSON (Content-Type: application/json).

Klucz to hasło

Kto zna klucz, ten wysyła SMS na Twój koszt. Używaj go wyłącznie po stronie serwera. Nigdy nie umieszczaj go w aplikacji mobilnej ani w kodzie strony.

Endpointy​

POST/api/v2/sms/messagesWysłanie jednej wiadomości.Pełny kontrakt w API Reference GET/api/v2/sms/messages/{id}Stan wiadomości.Pełny kontrakt w API Reference POST/api/v2/sms/batchesWysłanie paczki do 1000 wiadomości.Pełny kontrakt w API Reference GET/api/v2/sms/batches/{id}Stan paczki i wynik każdej wiadomości.Pełny kontrakt w API Reference GET/api/v2/sms/sendersNadawcy konta i ich status.Pełny kontrakt w API Reference

Pojedyncza wiadomość​

curl -X POST "https://panel.dpay.pl/api/v2/sms/messages" \
-H "Authorization: Bearer TWOJ_KLUCZ" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: zamowienie-1234-wyslane" \
-d '{"msisdn":"600100200","sender":"SKLEP","message":"Twoje zamówienie zostało wysłane."}'
PoleWymaganeOpis
msisdntakNumer odbiorcy, patrz Numer odbiorcy.
sendertakZatwierdzona nazwa nadawcy Twojego konta.
messagetakTreść, do 900 bajtów, patrz Treść i segmenty.

Odpowiedź 202 Accepted oznacza, że wiadomość przyjęliśmy do kolejki i zarezerwowaliśmy jej koszt. Nie oznacza doręczenia - wiadomość przekazujemy operatorowi w tle.

{
"batch_id": null,
"id": "9b2f4c1e-6f0a-4d7e-9a41-3c8f2d7b5e10",
"msisdn": "600100200",
"sender": "SKLEP",
"status": "queued",
"segments": 1,
"cost_net": "0.081300",
"created_at": "2026-10-14T12:00:00+02:00",
"finished_at": null
}

Zapisz id - pod GET /api/v2/sms/messages/{id} sprawdzisz, jak zakończyło się przekazanie wiadomości. Adres jest też w nagłówku Location odpowiedzi.

Wysyłka masowa​

Paczka to do 1000 wiadomości w jednym żądaniu. sender na poziomie paczki jest domyślnym nadawcą, a każda wiadomość może ustawić własny.

curl -X POST "https://panel.dpay.pl/api/v2/sms/batches" \
-H "Authorization: Bearer TWOJ_KLUCZ" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: kampania-2026-10" \
-d '{
"name": "Kampania październik",
"sender": "SKLEP",
"messages": [
{"msisdn": "600100200", "message": "Wiadomość 1"},
{"msisdn": "+48600100201", "message": "Wiadomość 2 od innego nadawcy", "sender": "INNY"}
]
}'

Paczkę przyjmujemy w całości albo wcale.

  • Jeśli choć jedna wiadomość jest niepoprawna, dostajesz 422 i nic nie zostaje przyjęte. Pole error.fields wskazuje każdą błędną wiadomość, np. messages.1.msisdn to numer drugiej wiadomości (liczymy od zera).
  • Jeśli środki nie wystarczają na całą paczkę, dostajesz 402.

Przyjęta paczka dostaje 202 ze statusem pending i wyceną w polu estimate. Wiadomości tworzymy w tle, zwykle w ciągu kilku sekund - dopiero wtedy rezerwujemy koszt.

{
"id": "3d6a0f5e-2b7c-4e19-8f3a-1c9d5e7b2a40",
"name": "Kampania październik",
"status": "pending",
"failure_reason": null,
"messages_count": 2,
"counts": {"queued": 0, "sending": 0, "sent": 0, "failed": 0, "unknown": 0},
"segments": 0,
"cost_net": null,
"created_at": "2026-10-14T12:00:00+02:00",
"updated_at": "2026-10-14T12:00:00+02:00",
"messages": [],
"estimate": {"segments": 2, "cost_net": "0.162600"}
}

Paczki wysłane przez API widać też w panelu w zakładce Import, a ich wiadomości w Historii i raportach.

Postęp i wyniki paczki​

curl "https://panel.dpay.pl/api/v2/sms/batches/3d6a0f5e-2b7c-4e19-8f3a-1c9d5e7b2a40" \
-H "Authorization: Bearer TWOJ_KLUCZ"

Odpowiedź zawiera liczniki wiadomości w każdym statusie i wynik każdej wiadomości w kolejności z żądania (index):

{
"id": "3d6a0f5e-2b7c-4e19-8f3a-1c9d5e7b2a40",
"status": "completed_with_errors",
"counts": {"queued": 0, "sending": 0, "sent": 1, "failed": 1, "unknown": 0},
"segments": 2,
"cost_net": "0.081300",
"messages": [
{"index": 0, "id": "5a1e9c2d-7b3f-4a8e-b6d4-0f2c9e1a7b35", "msisdn": "600100200", "sender": "SKLEP", "status": "sent", "segments": 1, "cost_net": "0.081300"},
{"index": 1, "id": "c7d2b8e4-1f6a-4c3d-9e5b-8a0f2d4c6e19", "msisdn": "600100201", "sender": "INNY", "status": "failed", "segments": 1, "cost_net": "0.000000"}
]
}
Status paczkiZnaczenie
pendingPrzyjęta, czeka na przetworzenie. Lista messages jest jeszcze pusta.
processingWiadomości utworzone, część jest jeszcze w kolejce albo w trakcie przekazania.
completedWszystkie wiadomości przekazane operatorowi (sent).
completed_with_errorsZakończona, ale część wiadomości ma status failed albo unknown.
rejectedOdrzucona podczas przetwarzania. Nic nie wysłaliśmy i niczego nie pobraliśmy - powód jest w failure_reason.

Paczka może zostać odrzucona już po przyjęciu, jeśli w międzyczasie zmieni się stan konta:

failure_reasonCo się stałoCo zrobić
insufficient_fundsŚrodki wykorzystała inna wysyłka między przyjęciem a przetworzeniem paczki.Doładuj konto i wyślij paczkę ponownie.
sender_inactiveNadawca z paczki przestał być aktywny.Sprawdź nadawców w panelu.
account_unavailableUsługa SMS przestała być dostępna na koncie.Sprawdź stan usługi w panelu.
invalid_batch, processing_failedPaczki nie udało się przetworzyć.Wyślij ponownie, a przy powtórce skontaktuj się z obsługą.

Odrzuconą paczkę możesz wysłać ponownie, także z tym samym Idempotency-Key.

Statusy wiadomości​

StatusZnaczenie
queuedPrzyjęta, czeka w kolejce.
sendingPrzekazujemy ją operatorowi.
sentOperator przyjął wiadomość. To nie jest potwierdzenie doręczenia na telefon odbiorcy.
failedOperator odrzucił wiadomość. Nie pobieramy za nią opłaty (cost_net = 0.000000).
unknownNie udało się potwierdzić wyniku przekazania. Kwota pozostaje zarezerwowana do wyjaśnienia - w razie wątpliwości skontaktuj się z obsługą.

Idempotencja​

Sieć bywa zawodna: żądanie mogło dojść, a odpowiedź nie. Żeby ponowienie nie wysłało SMS-a drugi raz, dodaj nagłówek Idempotency-Key z własnym, unikalnym kluczem (1-128 drukowalnych znaków ASCII, wielkość liter ma znaczenie), np. numerem zamówienia.

  • Powtórka z tym samym kluczem i tą samą treścią zwraca pierwotny wynik zamiast wysyłać ponownie. Odpowiedź ma wtedy nagłówek Idempotent-Replayed: true.
  • Ten sam klucz z inną treścią to błąd 409 idempotency_conflict.
  • Klucz paczki obejmuje całą treść żądania, łącznie z name.
  • Żądanie odrzucone przez walidację, brak środków albo nieaktywne konto nie zużywa klucza. Klucz paczki odrzuconej podczas przetwarzania (rejected) też możesz użyć ponownie.

Numer odbiorcy​

msisdn to polski numer w jednym z formatów: 600100200, +48600100200, 0048600100200 albo 48600100200. Spacje i myślniki są pomijane. W odpowiedziach numer wraca zawsze jako 9 cyfr.

Treść i segmenty​

Treść może mieć do 900 bajtów w UTF-8. Wysyłamy ją dokładnie w takiej postaci, w jakiej przyszła - nie usuwamy spacji ani znaków nowej linii.

Długa wiadomość jest dzielona na segmenty, a opłata to liczba segmentów razy stawka Twojego konta:

Kodowanie1 segmentPrzy podziale, na segment
GSM-7 (litery łacińskie bez polskich znaków, cyfry, podstawowe symbole)160 znaków153 znaki
Unicode70 znaków67 znaków
Polskie znaki

Jeden znak spoza alfabetu GSM-7, np. ą, ę albo ł, przełącza całą wiadomość na Unicode. Wiadomość z 100 znakami mieści się w jednym segmencie bez polskich znaków, ale z nimi zajmuje dwa.

Liczbę segmentów i cenę każdej wiadomości zwracamy w polach segments i cost_net (kwota netto w PLN). Liczymy je tym samym kalkulatorem co przy wysyłce z panelu.

Błędy​

Każdy błąd ma tę samą postać: stabilny code do obsługi w kodzie i message dla człowieka.

{
"error": {
"code": "validation_failed",
"message": "Żądanie zawiera niepoprawne dane.",
"fields": {
"messages.1.msisdn": ["Numer odbiorcy to dziewięć cyfr, opcjonalnie z prefiksem +48."]
}
}
}
HTTPcodeZnaczenie
400invalid_jsonTreść żądania nie jest obiektem JSON.
401unauthenticatedBrak klucza albo niepoprawny klucz.
402insufficient_fundsBrak salda albo wolnego limitu (przy paczce: na całą paczkę).
403account_unavailableUsługa SMS nie jest aktywna na koncie.
404not_foundNie ma takiej wiadomości albo paczki na Twoim koncie.
409idempotency_conflictIdempotency-Key użyty już dla innej treści.
422validation_failedNiepoprawne pola - szczegóły w fields. Dotyczy też nieaktywnego nadawcy.
429rate_limitedPrzekroczony limit żądań. Ponów po czasie z nagłówka Retry-After.

Limity​

  • 120 żądań na minutę na klucz API. Do wysyłki wielu wiadomości używaj paczek, a nie pojedynczych żądań w pętli.
  • 1000 wiadomości w paczce i 900 bajtów na wiadomość.
  • Seria nieudanych prób uwierzytelnienia z jednego adresu blokuje kolejne żądania z tego adresu do końca minuty (429).

Przejście z API v1​

API v1 działa nadal, ale nowe integracje powinny korzystać z v2.

API v1API v2
Kluczw adresie: /api/v1/sending/{klucz}w nagłówku Authorization: Bearer
Pola wiadomościnumber, override, messagemsisdn, sender, message
Wysyłka masowa/{klucz}/mass, lista JSON, wiadomość po wiadomości/batches, obiekt JSON, paczka w całości przetwarzana w tle
Błędy200 z error|... przy każdej pozycji listykody HTTP i error.code, błędne pozycje wskazane w fields
Stan wiadomościbrakGET /messages/{id}, GET /batches/{id}
Ponowieniabrak ochrony przed duplikatemIdempotency-Key

Klucz API jest ten sam - nie trzeba generować nowego.