API bramki SMS

Wysyłaj wiadomości do swoich klientów prosto ze swojego systemu — pojedynczo albo do całej listy, z raportem doręczenia każdej z nich.

Wszystkie żądania wysyłasz w formacie JSON, z nagłówkiem Content-Type: application/json. Kodowanie to UTF-8. Odpowiedzi też są w JSON.

BASE https://paybylink.pl/api/sms

Usługę uruchamiasz w panelu klienta, w zakładce Marketing SMS — po akceptacji regulaminu i doładowaniu salda. Klucz do API utworzysz w tej samej zakładce, w sekcji API.

Saldo doładujesz przelewem online albo BLIK-iem — środki są dostępne w kilka sekund po potwierdzeniu płatności, więc integrację możesz uruchomić od razu.

Masz pytanie techniczne? Napisz na [email protected] — odpowiadamy w dni robocze.

Klucz i limity

Klucz składa się z jawnego prefiksu i sekretu, rozdzielonych kropką. Przekazujesz go w nagłówku każdego żądania:

curl https://paybylink.pl/api/sms/balance/ \
  -H 'X-Sms-Key: sms_a1b2c3d4.TWOJ_SEKRET'

Możesz też użyć nagłówka Authorization: Bearer prefiks.sekret. Sekret przechowujemy wyłącznie jako skrót — pokazujemy go raz, przy tworzeniu klucza. Jeśli go zgubisz, utwórz nowy i unieważnij stary.

Klucz trzymaj na swoim serwerze. Nie umieszczaj go w kodzie strony ani w aplikacji mobilnej — każdy, kto go pozna, może wysyłać wiadomości na Twój koszt.

Limit żądań

Domyślnie 120 żądań na minutę. Aktualny stan zwracamy w nagłówkach:

X-RateLimit-Limit: 120
X-RateLimit-Remaining: 118

Po przekroczeniu limitu dostaniesz kod 429 i błąd rate_limited. Limit możemy podnieść — napisz, jeśli Twój ruch tego wymaga.

Warianty wysyłki

Wariant decyduje o cenie i o tym, co odbiorca zobaczy w polu nadawcy. Aktualne ceny Twojego konta zwraca zasób /pricing/.

WariantNazwaPole nadawcyZastosowanie
ECOPodstawowy numer skrócony operatora Najtańsza wysyłka masowa, gdy nazwa nadawcy nie ma znaczenia.
FULLDynamiczny Twoja nazwa Powiadomienia i informacje, które mają przyjść od Twojej firmy.
PROUnikalny Twoja nazwa Wiadomości transakcyjne — kody jednorazowe, potwierdzenia. Wyższy priorytet.
INTERMiędzynarodowy Twoja nazwa Numery spoza Polski.
VOICEGłosowy zawsze VOICE Komunikat odczytywany przez telefon zamiast wiadomości tekstowej.
W wariancie ECO nazwa nadawcy nie działa. Możesz ją podać, ale operator sieci zastąpi ją numerem skróconym — odbiorca nie zobaczy Twojej firmy. Jeśli zależy Ci na rozpoznawalności nadawcy, wybierz FULL albo PRO.

Długość wiadomości

Jedna część to 160 znaków alfabetu podstawowego albo 70 znaków, jeśli użyjesz polskich liter lub znaków specjalnych. Dłuższa wiadomość dzieli się na części — każda rozliczana osobno.

Zestaw znakówJedna częśćKolejne częściMaksimum
podstawowy1601537 części
polskie znaki706716 części

Łącznie najwyżej 1071 znaków. Odpowiedź zawiera pole parts oraz encoding, więc zawsze wiesz, za ile części zapłacisz.

Napisanie „Dzień dobry” zamiast „Dzien dobry” skraca dostępną długość ze 160 do 70 znaków. Przy krótkich powiadomieniach to bez znaczenia, przy dłuższych potrafi podwoić koszt.

Wysłanie jednej wiadomości

Droga dla wiadomości pilnych — kodów jednorazowych, potwierdzeń zamówienia. Wiadomość trafia do operatora natychmiast.

POST /api/sms/send/

Pola żądania

PoleTypWymaganeOpis
tostringwymaganeNumer odbiorcy. Format krajowy (500100200) albo z prefiksem (48500100200).
messagestringwymaganeTreść wiadomości.
senderstringopcjonalneNazwa nadawcy. Musi być zatwierdzona na Twoim koncie. Pomijana w wariancie ECO.
variantstringopcjonalneWariant wysyłki. Domyślnie PRO.
referencestringopcjonalneTwój własny identyfikator. Chroni przed podwójną wysyłką i pozwala odpytać o status bez zapamiętywania naszego id.
curl -X POST https://paybylink.pl/api/sms/send/ \
  -H 'X-Sms-Key: sms_a1b2c3d4.TWOJ_SEKRET' \
  -H 'Content-Type: application/json' \
  -d '{
    "to": "500100200",
    "message": "Twoj kod: 458213.",
    "sender": "MOJSKLEP",
    "variant": "PRO",
    "reference": "zamowienie-9001"
  }'

Odpowiedź

{
  "ok": true,
  "id": 8412,
  "reference": "zamowienie-9001",
  "to": "48500100200",
  "sender": "MOJSKLEP",
  "variant": "PRO",
  "parts": 1,
  "encoding": "GSM",
  "price": "0.1400",
  "status": "queued"
}
Zawsze podawaj reference. Jeśli Twoje żądanie nie doczeka odpowiedzi i ponowisz je, powtórka z tym samym reference zwróci istniejące id z polem duplicate: true — nie wyśle wiadomości drugi raz ani nie obciąży salda.

Wysyłka do wielu odbiorców

Jedno żądanie z listą numerów. Odpowiedź wraca od razu, wysyłka rusza w tle.

POST /api/sms/bulk/

Pola żądania

PoleTypWymaganeOpis
toarraywymaganeLista numerów. Może być też pojedynczym tekstem z numerami rozdzielonymi przecinkiem.
messagestringwymaganeTreść wysyłana do wszystkich odbiorców.
namestringopcjonalneNazwa wysyłki, widoczna w Twoim panelu i raportach.
senderstringopcjonalneNazwa nadawcy. Pomijana w wariancie ECO.
variantstringopcjonalneWariant wysyłki. Domyślnie ECO.
sendAtstringopcjonalneTermin wysyłki w formacie ISO 8601. Pominięty oznacza natychmiast.
referencestringopcjonalneTwój identyfikator wysyłki, chroni przed podwójnym zleceniem.
curl -X POST https://paybylink.pl/api/sms/bulk/ \
  -H 'X-Sms-Key: sms_a1b2c3d4.TWOJ_SEKRET' \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "Powiadomienia o wysylce",
    "to": ["500100200", "501300400"],
    "message": "Twoje zamowienie zostalo wyslane.",
    "sender": "MOJSKLEP",
    "variant": "FULL",
    "sendAt": "2026-09-01T10:00:00+02:00"
  }'

Pole rejected mówi, ile wpisów nie było poprawnym numerem, a optedOut — ile pominęliśmy, bo są na Twojej liście wypisanych. Powtórzone numery odfiltrowujemy automatycznie.

Status wiadomości

GET /api/sms/status/?reference=zamowienie-9001

Możesz odpytać po reference albo po id z odpowiedzi na wysyłkę.

{
  "ok": true,
  "id": 8412,
  "reference": "zamowienie-9001",
  "to": "48500100200",
  "status": "delivered",
  "operator": "MESSAGE_DELIVERED",
  "parts": 1,
  "price": "0.1400",
  "createdAt": "2026-09-01T10:00:00+02:00",
  "sentAt": "2026-09-01T10:00:02+02:00",
  "deliveredAt": "2026-09-01T10:00:09+02:00"
}

Możliwe statusy

PoleTypWymaganeOpis
queuedstatusopcjonalnePrzyjęta, czeka na przekazanie operatorowi.
sentstatusopcjonalnePrzekazana do sieci operatora.
deliveredstatusopcjonalnePotwierdzone doręczenie na telefon odbiorcy.
undeliveredstatusopcjonalneOperator zgłosił, że nie udało się doręczyć.
rejectedstatusopcjonalneOdrzucona przed wysłaniem. Opłata została zwrócona.
Zamiast odpytywać nas w pętli, włącz powiadomienia — sami damy znać, gdy status się zmieni.

Status wysyłki do wielu odbiorców

GET /api/sms/campaign/?id=331

Dodaj &recipients=1, żeby dostać listę odbiorców ze statusem każdego numeru — po 500 na stronę, kolejne przez &page=2.

{
  "ok": true,
  "id": 331,
  "name": "Powiadomienia o wysylce",
  "status": "done",
  "recipients": 2,
  "sent": 2,
  "delivered": 2,
  "failed": 0,
  "charged": "0.24",
  "finishedAt": "2026-09-01T10:01:11+02:00"
}

Saldo i cennik

GET /api/sms/balance/
{
  "ok": true,
  "balance": "850.00",
  "reserved": "120.00",
  "available": "730.00",
  "currency": "PLN",
  "net": true,
  "prices": { "ECO": "0.1100", "FULL": "0.1200" },
  "limits": { "daily": 0, "monthly": 0, "perMinute": 120 }
}

reserved to kwota zablokowana na wysyłki, które jeszcze trwają. Do dyspozycji masz available. Wszystkie kwoty są netto.

Zasób /pricing/ zwraca warianty z cenami i informacją, czy dany wariant honoruje Twoją nazwę nadawcy.

Nazwy nadawcy

GET /api/sms/senders/
{
  "ok": true,
  "senders": [
    { "name": "INFORMACJA", "type": "shared", "status": "approved" },
    { "name": "MOJSKLEP", "type": "own", "status": "approved" }
  ]
}

Nazwy typu shared są dostępne od razu i dzielisz je z innymi nadawcami. Własną nazwę firmy zgłaszasz w panelu — sprawdzamy prawo do niej i zatwierdzamy. Nazw zastrzeżonych dla banków, urzędów i firm kurierskich nie zatwierdzamy.

Lista wypisanych

Numery, które zgłosiły rezygnację. Filtrujemy przez tę listę każdą wysyłkę tuż przed przekazaniem jej operatorowi — także wtedy, gdy numer zostanie w Twojej bazie.

POST /api/sms/optout/
curl -X POST https://paybylink.pl/api/sms/optout/ \
  -H 'X-Sms-Key: sms_a1b2c3d4.TWOJ_SEKRET' \
  -H 'Content-Type: application/json' \
  -d '{"to": ["500100200", "501300400"]}'

Sprawdzenie pojedynczego numeru

GET /api/sms/optout/?to=500100200
{ "ok": true, "to": "48500100200", "optedOut": true }

Wywołanie bez parametru to zwraca całą listę, po 500 pozycji na stronę.

Raporty doręczeń

Podaj w panelu adres, pod który mamy wysyłać powiadomienia. Damy znać, gdy wiadomość dotrze do odbiorcy albo gdy wysyłka masowa się zakończy — nie musisz nas odpytywać.

Adres musi zaczynać się od https://.

Powiadomienie o wiadomości

{
  "event": "message.status",
  "id": 8412,
  "reference": "zamowienie-9001",
  "to": "48500100200",
  "sender": "MOJSKLEP",
  "variant": "PRO",
  "status": "delivered",
  "operator": "MESSAGE_DELIVERED",
  "price": "0.1400",
  "deliveredAt": "2026-09-01T10:00:09"
}

Powiadomienie o wysyłce masowej

{
  "event": "campaign.finished",
  "id": 331,
  "reference": null,
  "name": "Powiadomienia o wysylce",
  "status": "done",
  "recipients": 2,
  "sent": 2,
  "delivered": 2,
  "failed": 0,
  "charged": "0.24"
}

Odpowiedz kodem z zakresu 2xx, żeby potwierdzić odbiór. Jeśli nie odpowiesz, ponawiamy z rosnącym odstępem — do ośmiu prób.

Weryfikacja podpisu

Każde powiadomienie ma nagłówek X-Sms-Signature. To skrót HMAC-SHA256 z surowej treści żądania, podpisany sekretem widocznym w panelu przy adresie powiadomień.

Sprawdzaj podpis, zanim zaufasz danym. Bez tego każdy, kto zna Twój adres powiadomień, mógłby podać się za nas.
<?php

$raw  = file_get_contents('php://input');
$sent = isset($_SERVER['HTTP_X_SMS_SIGNATURE']) ? $_SERVER['HTTP_X_SMS_SIGNATURE'] : '';
$calc = hash_hmac('sha256', $raw, SMS_WEBHOOK_SECRET);

if (!hash_equals($calc, $sent)) {
    http_response_code(403);
    exit;
}

$event = json_decode($raw, true);

// tu aktualizujesz status u siebie

http_response_code(200);
echo 'OK';

Podpisujemy surową treść żądania, dokładnie taką, jaka przyszła. Jeśli najpierw sparsujesz JSON, a potem zapiszesz go z powrotem, podpis się nie zgodzi.

Kody błędów

Każda odmowa ma ten sam kształt — kod maszynowy i wyjaśnienie:

{
  "ok": false,
  "error": "no_funds",
  "message": "Za malo srodkow na koncie. Doladuj saldo bramki SMS."
}

Sprawdzaj pole ok — wartość false zawsze oznacza, że nic nie zostało wysłane ani obciążone.

KodHTTPZnaczenie
no_key401Brak klucza w nagłówku.
bad_key401Klucz nieprawidłowy albo unieważniony.
account_off403Bramka nieaktywna na koncie.
sender_not_allowed403Nazwa nadawcy niezatwierdzona.
variant_unavailable403Wariant niedostępny na koncie.
no_funds402Za mało środków na saldzie.
bad_number400Numer odbiorcy nieprawidłowy.
message_rejected400Treść za długa albo za wiele części.
bad_json400Treść żądania nie jest poprawnym JSON-em.
opted_out409Numer na liście wypisanych.
forbidden_topic422Treść z kategorii, której operator nie przyjmuje.
rate_limited429Za dużo żądań na minutę.
limit_reached429Przekroczony limit dzienny albo miesięczny.
not_found404Nie znaleziono wiadomości albo wysyłki.
unavailable503Bramka chwilowo niedostępna.

Zasady wysyłki

Zgoda odbiorcy

Wiadomość handlową lub marketingową możesz wysłać wyłącznie do osób, które wyraziły na to zgodę. Obowiązek jej uzyskania i udokumentowania spoczywa na Tobie. W treści marketingowej podaj czytelny sposób rezygnacji.

Odpowiedź STOP

Gdy odbiorca odpisze STOP, dopisujemy go do Twojej listy wypisanych i pomijamy w kolejnych wysyłkach. Lista dotyczy wyłącznie Twoich wiadomości — nie przenosi się na innych nadawców.

Czego nie przyjmiemy

Operator sieci nie przepuszcza wysyłek promujących hazard, alkohol, wyroby tytoniowe, produkty lecznicze i usługi medyczne, broń, treści dla dorosłych ani zbiórek charytatywnych. Takie żądania odrzucamy kodem forbidden_topic, zanim cokolwiek wyjdzie.

Odrzucamy też wiadomości podszywające się pod inny podmiot, zmierzające do wyłudzenia danych lub płatności oraz zawierające numery o podwyższonej opłacie.

Pole nadawcy musi wskazywać na Ciebie. Nazwy zastrzeżone dla banków, urzędów, firm kurierskich i operatorów odrzucamy — także warianty łudząco do nich podobne. Operatorzy sieci blokują takie wysyłki niezależnie od nas.

Rozliczenie

Płacisz za wiadomości przyjęte do wysyłki. Za wiadomości, których operator w ogóle nie przyjął, opłata jest zwracana. Za nieodebrane — na przykład gdy telefon był wyłączony — opłaty nie zwracamy; wynik doręczenia widzisz w raporcie.