Every API here is available over the APIs.io API and to AI agents over MCP.
openapi: 3.2.0
info:
title: Przypominamy Com Kontakty i grupy API
version: 2.3.0
contact:
name: Wsparcie Przypominamy.com
email: support@przypominamy.com
url: https://przypominamy.com/api
license:
name: Proprietary
url: https://przypominamy.com/regulamin
termsOfService: https://przypominamy.com/regulamin
x-audience: Polskie małe i średnie firmy integrujące SMS w CRM, e-commerce, aplikacjach 2FA, systemach umawiania wizyt i windykacji.
x-llm-summary: 'Przypominamy.com to polskie REST API do wysyłki SMS. Jeden endpoint POST /v1/messages wysyła do jednego lub do 500 odbiorców (pole to: string, tablica albo "group:<nazwa>" - grupa kontaktów), z polami text (placeholdery {{imie}}, {{nazwisko}}, {{email}}, pola własne, {{opt_out}} = osobisty link wypisu), from (nadpis), send_at (ISO 8601, do 90 dni), send_window ("08:00-20:00", czas polski), expires_at (15 min – 72 h), reference. Zamiast text: template_id (szablon z GET/POST /v1/templates, {{klucz}} z params); priority: true = SMS priorytetowy, osobna kolejka, cena ×2. GET /v1/numbers/{msisdn}/lookup = HLR (status active/inactive/invalid/unknown, sieć; 0,05 zł, wynik z 24 h bez opłaty). DELETE /v1/messages/{id} anuluje zaplanowaną wysyłkę (status cancelled, zwrot kosztu). Historia: GET /v1/messages (cursor, filtry status/reference/to) i GET /v1/messages/{id}. Konto: GET /v1/account (saldo w groszach, cena za część, scopes, send_window, inbound_number, inbound_prefix), PATCH /v1/account (sender_name, send_window, inbound_prefix), GET /v1/senders, PUT /v1/account/webhook. Śledzone linki: {{link:https://…}} w text (do 2 adresów) = krótki link api.przypominamy.com/l/<token> per odbiorca z licznikiem kliknięć; GET /v1/messages/{id} zwraca links[], GET /v1/links (message_id, clicked=true) i GET /v1/links/{token} (click_log), webhook link.clicked przy pierwszym kliknięciu; bez dopłaty. Odbiór odpowiedzi (2-way) na życzenie, po uruchomieniu numeru odbiorczego w usłudze (do tego czasu inbound_number = null, lista pusta): odpowiedź ze słowem kluczowym klienta (inbound_prefix) albo od numeru, do którego klient pisał w ciągu 30 dni, trafia na GET /v1/inbound (from, since, unread, mark_read, cursor; pola id, from, to, text, reply_to, matched_by prefix|last_message, received_at, read_at) i GET /v1/inbound/{id}; webhook message.received z data.inbound i data.opt_out; STOP/WYPISZ/NIE = numer na czarną listę. Czarna lista: GET/POST /v1/blacklist, DELETE /v1/blacklist/{msisdn}; numery z listy dostają status rejected bez opłaty. Kontakty i grupy: GET/POST /v1/contacts, GET/PATCH/DELETE /v1/contacts/{id}, GET/POST /v1/groups, GET/PATCH/DELETE /v1/groups/{id}, POST /v1/groups/{id}/contacts, DELETE /v1/groups/{id}/contacts/{contactId}. Autoryzacja Bearer pk_live_… z zakresami send/read/manage (403 forbidden bez zakresu); klucz z panelu app.przypominamy.com/keys. Webhooki message.sent/delivered/undelivered/failed/expired, message.received i link.clicked podpisane HMAC-SHA256 w nagłówku X-Przypominamy-Signature (t=<unix>,v1=<hex>, podpis nad ''<t>.<body>'', tolerancja 300 s). Idempotency-Key. Błędy jako {error:{code,message,param},request_id}. Prepaid (domyślnie; billing_mode w GET /v1/account), saldo w groszach, 402 przy braku środków, 120 żądań/min. Postpaid na życzenie po weryfikacji: zestawienie miesięczne 1. dnia miesiąca, 14 dni na przelew, po terminie 402 do zaksięgowania wpłaty.'
x-logo:
url: https://przypominamy.com/przypominamy-logo.png
altText: Przypominamy.com
description: 'Operations tagged Kontakty i grupy across 2 of this provider''s published API definitions: openapi.json, przypominamy-com-openapi.json. Each path carries the servers of the definition it was published in.'
servers:
- url: https://api.przypominamy.com
description: Produkcja
security:
- bearerAuth: []
tags:
- name: Kontakty i grupy
description: Książka odbiorców, grupy do wysyłki, personalizacja
paths:
/v1/contacts:
get:
tags:
- Kontakty i grupy
summary: Lista kontaktów
operationId: listContacts
description: '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`.'
parameters:
- name: q
in: query
schema:
type: string
description: Szukany fragment
- name: group_id
in: query
schema:
type: string
description: Tylko członkowie grupy `gr_…`
- name: limit
in: query
schema:
type: integer
minimum: 1
maximum: 500
default: 100
- name: cursor
in: query
schema:
type: string
description: Wartość `next_cursor` z poprzedniej strony
responses:
'200':
description: Strona wyników
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Contact'
next_cursor:
type:
- string
- 'null'
example:
data:
- id: ct_8fK2mQpL0aXz4Wv1
msisdn: '+48600100200'
first_name: Anna
last_name: Nowak
email: anna@example.pl
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
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
post:
tags:
- Kontakty i grupy
summary: Dodaj lub zaktualizuj kontakty
operationId: upsertContacts
description: '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`.'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ContactInput'
examples:
jeden:
summary: Jeden kontakt z grupą i polem własnym
value:
msisdn: '+48600100200'
first_name: Anna
last_name: Nowak
fields:
wizyta: 10.09 14:00
groups:
- VIP
import:
summary: Import tablicy (do 500)
value:
- msisdn: '+48600100201'
first_name: Piotr
groups:
- VIP
- msisdn: '+48600100202'
first_name: Ewa
email: ewa@example.pl
responses:
'201':
description: Utworzono (obiekt Contact) lub zaimportowano (podsumowanie)
content:
application/json:
examples:
kontakt:
summary: Jeden kontakt
value:
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'
import:
summary: Tablica
value:
created: 2
updated: 0
invalid: []
'200':
description: Zaktualizowano istniejący kontakt (tylko dla pojedynczego obiektu)
content:
application/json:
schema:
$ref: '#/components/schemas/Contact'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
description: Podano id nieistniejącej grupy
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
x-codeSamples:
- lang: curl
source: "curl -X POST https://api.przypominamy.com/v1/contacts \\\n -H \"Authorization: Bearer $PRZYPOMINAMY_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\"msisdn\": \"+48600100200\", \"first_name\": \"Anna\", \"fields\": {\"wizyta\": \"10.09 14:00\"}, \"groups\": [\"VIP\"]}'"
servers:
- url: https://api.przypominamy.com
description: Produkcja
/v1/contacts/{id}:
get:
tags:
- Kontakty i grupy
summary: Pobierz kontakt
operationId: getContact
description: Wymaga zakresu `read`.
parameters:
- name: id
in: path
required: true
schema:
type: string
example: ct_8fK2mQpL0aXz4Wv1
responses:
'200':
description: Kontakt
content:
application/json:
schema:
$ref: '#/components/schemas/Contact'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
patch:
tags:
- Kontakty i grupy
summary: Zmień kontakt
operationId: updateContact
description: '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`.'
parameters:
- name: id
in: path
required: true
schema:
type: string
example: ct_8fK2mQpL0aXz4Wv1
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ContactInput'
example:
last_name: Kowalska
fields:
wizyta: 12.09 09:30
responses:
'200':
description: Zaktualizowany kontakt
content:
application/json:
schema:
$ref: '#/components/schemas/Contact'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'409':
description: Inny kontakt ma już ten numer
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
delete:
tags:
- Kontakty i grupy
summary: Usuń kontakt
operationId: deleteContact
description: Usuwa kontakt z książki i ze wszystkich grup. Nie blokuje numeru - do tego służy czarna lista. Wymaga zakresu `manage`.
parameters:
- name: id
in: path
required: true
schema:
type: string
example: ct_8fK2mQpL0aXz4Wv1
responses:
'200':
description: Usunięto
content:
application/json:
example:
deleted: ct_8fK2mQpL0aXz4Wv1
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
servers:
- url: https://api.przypominamy.com
description: Produkcja
/v1/groups:
get:
tags:
- Kontakty i grupy
summary: Lista grup
operationId: listGroups
description: Wszystkie grupy konta z liczbą członków, posortowane po nazwie. Wymaga zakresu `read`.
responses:
'200':
description: Grupy
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Group'
example:
data:
- id: gr_Zq7Lk2Pm9sT1
name: VIP
members: 2
created_at: '2026-09-07T10:00:00.000Z'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
post:
tags:
- Kontakty i grupy
summary: Utwórz grupę
operationId: createGroup
description: 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`.
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- name
properties:
name:
type: string
maxLength: 80
example: VIP
responses:
'201':
description: Utworzono
content:
application/json:
schema:
$ref: '#/components/schemas/Group'
example:
id: gr_Zq7Lk2Pm9sT1
name: VIP
members: 0
created_at: '2026-09-07T10:00:00.000Z'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'409':
description: Grupa o tej nazwie już istnieje
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
servers:
- url: https://api.przypominamy.com
description: Produkcja
/v1/groups/{id}:
get:
tags:
- Kontakty i grupy
summary: Pobierz grupę
operationId: getGroup
description: Grupa z liczbą członków. Listę członków pobierzesz przez `GET /v1/contacts?group_id=…`. Wymaga zakresu `read`.
parameters:
- name: id
in: path
required: true
schema:
type: string
example: gr_Zq7Lk2Pm9sT1
responses:
'200':
description: Grupa
content:
application/json:
schema:
$ref: '#/components/schemas/Group'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
patch:
tags:
- Kontakty i grupy
summary: Zmień nazwę grupy
operationId: updateGroup
description: Wymaga zakresu `manage`.
parameters:
- name: id
in: path
required: true
schema:
type: string
example: gr_Zq7Lk2Pm9sT1
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- name
properties:
name:
type: string
maxLength: 80
example: Klienci VIP
responses:
'200':
description: Zmieniono
content:
application/json:
example:
id: gr_Zq7Lk2Pm9sT1
name: Klienci VIP
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
delete:
tags:
- Kontakty i grupy
summary: Usuń grupę
operationId: deleteGroup
description: Usuwa grupę i jej przypisania; kontakty zostają w książce. Wymaga zakresu `manage`.
parameters:
- name: id
in: path
required: true
schema:
type: string
example: gr_Zq7Lk2Pm9sT1
responses:
'200':
description: Usunięto
content:
application/json:
example:
deleted: gr_Zq7Lk2Pm9sT1
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
servers:
- url: https://api.przypominamy.com
description: Produkcja
/v1/groups/{id}/contacts:
post:
tags:
- Kontakty i grupy
summary: Dodaj kontakty do grupy
operationId: addGroupContacts
description: 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`.
parameters:
- name: id
in: path
required: true
schema:
type: string
example: gr_Zq7Lk2Pm9sT1
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
contact_ids:
type: array
items:
type: string
description: Id kontaktów `ct_…`
msisdns:
type: array
items:
type: string
description: Numery (brakujące kontakty są tworzone)
example:
msisdns:
- '+48600100203'
- '+48600100204'
responses:
'200':
description: Dodano
content:
application/json:
example:
id: gr_Zq7Lk2Pm9sT1
added: 2
invalid: []
members: 4
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
servers:
- url: https://api.przypominamy.com
description: Produkcja
/v1/groups/{id}/contacts/{contactId}:
delete:
tags:
- Kontakty i grupy
summary: Usuń kontakt z grupy
operationId: removeGroupContact
description: Odpina kontakt od grupy; kontakt zostaje w książce. Wymaga zakresu `manage`.
parameters:
- name: id
in: path
required: true
schema:
type: string
example: gr_Zq7Lk2Pm9sT1
- name: contactId
in: path
required: true
schema:
type: string
example: ct_8fK2mQpL0aXz4Wv1
responses:
'200':
description: Odpięto
content:
application/json:
example:
removed: ct_8fK2mQpL0aXz4Wv1
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
description: Nie znaleziono grupy albo kontakt nie należy do tej grupy
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
servers:
- url: https://api.przypominamy.com
description: Produkcja
components:
responses:
NotFound:
description: Nie znaleziono
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
BadRequest:
description: Błąd walidacji
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error:
code: invalid_request
message: 'Nieprawidłowy numer odbiorcy: +48XXXXXXXXX'
param: to
request_id: req_…
Unauthorized:
description: Brak lub nieprawidłowy klucz API
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error:
code: unauthorized
message: Nieprawidłowy klucz API
request_id: req_…
Forbidden:
description: Klucz bez wymaganego zakresu (albo konto zawieszone / testowe wysyła na niezweryfikowany numer)
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
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_…
schemas:
Contact:
type: object
properties:
id:
type: string
example: ct_8fK2mQpL0aXz4Wv1
msisdn:
type: string
example: '+48600100200'
first_name:
type:
- string
- 'null'
example: Anna
last_name:
type:
- string
- 'null'
example: Nowak
email:
type:
- string
- 'null'
fields:
type: object
additionalProperties:
type: string
description: Pola własne
example:
wizyta: 10.09 14:00
groups:
type: array
items:
type: object
properties:
id:
type: string
example: gr_Zq7Lk2Pm9sT1
name:
type: string
example: VIP
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
Group:
type: object
properties:
id:
type: string
example: gr_Zq7Lk2Pm9sT1
name:
type: string
example: VIP
members:
type: integer
description: Liczba kontaktów w grupie
example: 2
created_at:
type: string
format: date-time
Error:
type: object
properties:
error:
type: object
properties:
code:
type: string
enum:
- unauthorized
- forbidden
- not_found
- invalid_request
- insufficient_funds
- rate_limited
- idempotency_conflict
- provider_error
- internal_error
message:
type: string
param:
type: string
description: Pole żądania, którego dotyczy błąd (jeśli dotyczy)
request_id:
type: string
example: req_DbIaEbKi5pbRgjCV
ContactInput:
type: object
description: Treść `POST /v1/contacts` (wymagane `msisdn`) i `PATCH /v1/contacts/{id}` (wszystko opcjonalne). W `POST` może być też tablicą takich obiektów (do 500).
properties:
msisdn:
type: string
description: Numer (E.164, bez plusa lub 9 cyfr = Polska); klucz upsertu
example: '+48600100200'
first_name:
type:
- string
- 'null'
maxLength: 80
description: Imię - placeholder `{{imie}}`
example: Anna
last_name:
type:
- string
- 'null'
maxLength: 80
description: Nazwisko - placeholder `{{nazwisko}}`
example: Nowak
email:
type:
- string
- 'null'
maxLength: 200
description: Placeholder `{{email}}`
fields:
type:
- object
- 'null'
additionalProperties:
type: string
maxLength: 200
description: Pola własne (do 20; klucz `[a-zA-Z_][a-zA-Z0-9_]{0,30}`) - placeholder `{{nazwa_pola}}`
example:
wizyta: 10.09 14:00
groups:
type: array
items:
type: string
description: Nazwy lub id grup; nieistniejące nazwy są tworzone; zastępuje dotychczasowe przypisania
example:
- VIP
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: pk_live_…
description: 'Klucz API z panelu app.przypominamy.com/keys (`pk_live_…` lub `pk_test_…`). Klucz ma zakresy: `send` (wysyłka i anulowanie), `read` (odczyt historii, raportów, konta, nadpisów, czarnej listy, kontaktów i grup, odpowiedzi 2-way i śledzonych linków), `manage` (ustawienia konta, webhook, zapis czarnej listy, kontaktów i grup). Brak zakresu = HTTP 403 `forbidden`. Klucze sprzed wprowadzenia zakresów mają wszystkie trzy.'
x-refined-from:
- openapi.json
- przypominamy-com-openapi.json