# piv.day API Reference Full reference for the piv.day REST API: every endpoint, request body, response shape, error code and webhook. Exported from https://piv.day/api/docs for use with AI assistants. --- ## Getting started REST API w planie Business. Tokeny Bearer, JSON, idempotentne endpointy, przewidywalne kody błędów. Każdy endpoint zawiera przykład żądania i odpowiedzi. ### Base URL ``` https://app.piv.day/api/v1 ``` Wszystkie endpointy znajdują się pod tym prefiksem. Jedno środowisko — brak oddzielnych hostów staging. ### Uwierzytelnianie ``` Authorization: Bearer YOUR_API_KEY ``` Klucze są tworzone w dashboardzie w sekcji `Ustawienia → API Keys`. Każdy klucz ma szczegółowe uprawnienia (odczyt numerów, wysyłanie SMS, kupowanie proxy itp.). Skompromitowany token rotuje się jednym kliknięciem — bez ponownego onboardingu zespołu. ### Konto **200 OK** ``` curl https://app.piv.day/api/v1/account \ -H "Authorization: Bearer YOUR_API_KEY" ``` **Jeden pomocniczy endpoint — saldo i email bieżącego konta. Wygodne do sprawdzenia, czy klucz działa i uwierzytelnianie jest poprawnie skonfigurowane.** ``` { "success": true, "data": { "user_id": "usr-uuid-...", "balance": 150.50, "email": "u***@example.com", "team_id": null, "is_team_member": false } } ``` GET /api/v1/account ### Format odpowiedzi ``` { "success": true, "data": { ... } } ``` Wszystkie odpowiedzi są w formacie JSON. W przypadku błędu `success` = `false`, a ciało zawiera `error.code` i `error.message`. ### Rate limits **100 żądań na minutę na klucz API. Limit jest wspólny dla wszystkich endpointów. Potrzebujesz większego limitu pod obciążenie? Napisz do wsparcia Telegram, a podniesiemy limit bez zbędnych formalności. Po przekroczeniu limitu otrzymasz `429 RATE_LIMITED` i nagłówek `Retry-After` — ile sekund czekać przed kolejnym żądaniem.** ``` HTTP/1.1 429 Too Many Requests Retry-After: 12 { "success": false, "error": { "code": "RATE_LIMITED", "message": "Rate limit exceeded, retry in 12s" } } ``` 429 Too Many Requests ## Numery Kupuj, odnawiaj i przywracaj numery. Odbieraj i wysyłaj SMS. Uruchamiaj weryfikacje Google QR. Subskrybuj zdarzenia przez webhooki. ### Kraje i ceny `GET /api/v1/numbers/countries` Zwraca kraje dostępne do zakupu z aktualną ceną i możliwościami SMS. Wszystkie ceny uwzględniają zniżkę z subskrypcji. **Response fields** | Field | Type | Description | | --- | --- | --- | | `country_code` | string | Dwuliterowy kod kraju ISO (np. `SE`). | | `price_per_month` | number | Ostateczna cena dla Twojego planu — to, co zostanie naliczone przy zakupie. Zniżki Premium / Business są już uwzględnione. | | `base_price` | number | Cena bez rabatów (plan Free). Zwracana w celu porównania — żeby zobaczyć, ile oszczędza subskrypcja. | | `can_send_sms` | boolean | Czy z tego numeru można wysyłać wychodzące SMS. | | `can_receive_sms` | boolean | Czy przychodzące SMS są obsługiwane. | | `sms_send_price` | number\|null | Cena za wychodzący SMS, również z rabatem planu. `null`, gdy wysyłanie z tego kraju nie jest obsługiwane. | **curl** ```bash curl https://app.piv.day/api/v1/numbers/countries \ -H "Authorization: Bearer YOUR_API_KEY" ``` **200 OK** ```json { "success": true, "data": [ { "country_code": "SE", "price_per_month": 4.00, "base_price": 5.00, "can_send_sms": true, "can_receive_sms": true, "sms_send_price": 0.25 }, { "country_code": "GB", "price_per_month": 3.00, "base_price": 3.00, "can_send_sms": true, "can_receive_sms": true, "sms_send_price": 0.20 } ] } ``` ### Lista numerów konta `GET /api/v1/numbers` Zwraca stronę numerów konta z filtrami według kraju, statusu i wyszukiwaniem po numerze lub niestandardowej nazwie. **Query parameters** | Field | Type | Description | | --- | --- | --- | | `limit` | integer | Rozmiar strony (domyślnie 50, maksymalnie 200). | | `offset` | integer | Przesunięcie paginacji. | | `country` | string | Filtr kodu kraju ISO. | | `status` | string | Jeden z: `active`, `expired`, `pending_restore`. | | `search` | string | Wyszukiwanie podciągu po numerze telefonu lub niestandardowej nazwie. | **curl** ```bash curl "https://app.piv.day/api/v1/numbers?country=SE&status=active&limit=10" \ -H "Authorization: Bearer YOUR_API_KEY" ``` **200 OK** ```json { "success": true, "data": { "numbers": [ { "piv_num_id": "vzPA1-kHKSg-EAL7e-Jqd3o", "phone_number": "+46764794425", "country_code": "SE", "status": "active", "created_at": "2026-05-01T10:00:00Z", "expires_at": "2026-05-31T10:00:00Z", "auto_renew": false, "custom_name": "Office line", "purchased_at": "2026-05-01T10:00:00Z", "next_renewal_date": "2026-05-31T10:00:00Z", "tags": ["support"], "can_send_sms": true, "can_receive_sms": true } ], "pagination": { "total": 1, "limit": 10, "offset": 0 } } } ``` ### Jeden numer po ID `GET /api/v1/numbers/{piv_num_id}` Pełna karta numeru: status, daty, auto-odnowienie, tagi, dozwolone kierunki SMS. **Errors** | Code | HTTP | When it fires | | --- | --- | --- | | `NUMBER_NOT_FOUND` | 404 | Numer nie istnieje lub nie należy do konta. | **curl** ```bash curl https://app.piv.day/api/v1/numbers/vzPA1-kHKSg-EAL7e-Jqd3o \ -H "Authorization: Bearer YOUR_API_KEY" ``` **200 OK** ```json { "success": true, "data": { "piv_num_id": "vzPA1-kHKSg-EAL7e-Jqd3o", "phone_number": "+46764794425", "country_code": "SE", "status": "active", "created_at": "2026-05-01T10:00:00Z", "expires_at": "2026-05-31T10:00:00Z", "auto_renew": false, "custom_name": "Office line", "purchased_at": "2026-05-01T10:00:00Z", "next_renewal_date": "2026-05-31T10:00:00Z", "tags": ["support"], "can_send_sms": true, "can_receive_sms": true } } ``` ### Kup numer `POST /api/v1/numbers/purchase` Kupuje jeden numer w wybranym kraju na wskazany okres. Kwota jest pobierana z salda konta. Zwraca `piv_num_id` używane we wszystkich późniejszych operacjach na numerze. **Request body** | Field | Type | Description | | --- | --- | --- | | `country_code` * | string | Kod kraju ISO. | | `duration_months` * | integer | Okres wynajmu w miesiącach (minimum 1). | | `auto_renew` * | boolean | Włączyć auto-odnowienie zaraz po zakupie. | | `custom_name` | string | Opcjonalna czytelna dla człowieka nazwa numeru. | **Errors** | Code | HTTP | When it fires | | --- | --- | --- | | `COUNTRY_NOT_AVAILABLE` | 400 | Kraj niedostępny lub brak cennika. | | `NO_NUMBERS_AVAILABLE` | 400 | Brak dostępnych numerów w żądanym kraju w tej chwili. | | `INSUFFICIENT_BALANCE` | 402 | Niewystarczające środki na saldzie. | | `VALIDATION_ERROR` | 400 | Nieprawidłowe pola w treści żądania. | **curl** ```bash curl -X POST https://app.piv.day/api/v1/numbers/purchase \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "country_code": "SE", "duration_months": 1, "auto_renew": false, "custom_name": "My Sweden Number" }' ``` **200 OK** ```json { "success": true, "cost": 5.00, "numbers": [ { "piv_num_id": "vzPA1-kHKSg-EAL7e-Jqd3o", "country_code": "SE", "phone_number": "+46764794425", "created_at": "2026-05-01T10:00:00Z", "expires_at": "2026-05-31T10:00:00Z", "auto_renew": false, "custom_name": "My Sweden Number" } ] } ``` ### Odnów numer `POST /api/v1/numbers/{piv_num_id}/renew` Przedłuża aktywny numer na wskazany okres. Koszt jest pobierany w momencie wywołania. **Request body** | Field | Type | Description | | --- | --- | --- | | `duration_months` * | integer | O ile miesięcy przedłużyć. | **Errors** | Code | HTTP | When it fires | | --- | --- | --- | | `NUMBER_NOT_FOUND` | 404 | Numer nie istnieje lub nie należy do konta. | | `COUNTRY_NOT_AVAILABLE` | 400 | Nie znaleziono cen dla kraju numeru. | | `INSUFFICIENT_BALANCE` | 402 | Niewystarczające środki na odnowienie. | **curl** ```bash curl -X POST https://app.piv.day/api/v1/numbers/vzPA1-kHKSg-EAL7e-Jqd3o/renew \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "duration_months": 1 }' ``` **200 OK** ```json { "success": true, "data": { "piv_num_id": "vzPA1-kHKSg-EAL7e-Jqd3o", "phone_number": "+46764794425", "old_expires_at": "2026-05-31T10:00:00Z", "new_expires_at": "2026-06-30T10:00:00Z", "cost": 5.00 } } ``` ### Zaktualizuj numer `PATCH /api/v1/numbers/{piv_num_id}` Obecnie można zaktualizować tylko niestandardową nazwę numeru. **Request body** | Field | Type | Description | | --- | --- | --- | | `custom_name` * | string | Nowa nazwa numeru. | **Errors** | Code | HTTP | When it fires | | --- | --- | --- | | `NUMBER_NOT_FOUND` | 404 | Numer nie istnieje lub nie należy do konta. | | `VALIDATION_ERROR` | 400 | Nieprawidłowa wartość w treści żądania. | **curl** ```bash curl -X PATCH https://app.piv.day/api/v1/numbers/vzPA1-kHKSg-EAL7e-Jqd3o \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "custom_name": "Support line" }' ``` **200 OK** ```json { "success": true, "data": { "piv_num_id": "vzPA1-kHKSg-EAL7e-Jqd3o", "phone_number": "+46764794425", "country_code": "SE", "status": "active", "custom_name": "Support line", "auto_renew": false, "expires_at": "2026-05-31T10:00:00Z", "tags": [] } } ``` ### Zarządzanie auto-odnowieniem `PATCH /api/v1/numbers/{piv_num_id}/auto-renewal` Włącza lub wyłącza auto-odnowienie numeru. Gdy jest włączone, odnowienie jest pobierane automatycznie 24 godziny przed wygaśnięciem. Jeśli środki są niewystarczające, numer wygasa; można go odzyskać przez `POST /numbers/restore` w ciągu 7 dni. **Request body** | Field | Type | Description | | --- | --- | --- | | `auto_renew` * | boolean | Nowa wartość flagi auto-odnowienia. | **curl** ```bash curl -X PATCH https://app.piv.day/api/v1/numbers/vzPA1-kHKSg-EAL7e-Jqd3o/auto-renewal \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "auto_renew": true }' ``` **200 OK** ```json { "success": true, "data": { "piv_num_id": "vzPA1-kHKSg-EAL7e-Jqd3o", "phone_number": "+46764794425", "auto_renew": true } } ``` ### Przywróć wygasłe numery `POST /api/v1/numbers/restore` Odzyskuje wygasłe numery w ciągu 7-dniowego okna. Przekaż tablicę `piv_num_id` — numery wracają z zachowaną historią SMS i ustawieniami. Przywrócenie kosztuje więcej niż zakup nowego numeru (zawiera mnożnik przywracania) — dokładne liczby są widoczne w dashboardzie przed potwierdzeniem. Ostateczny status każdego numeru przychodzi przez webhook `number.restore_completed`; zwroty za nieudane numery są automatycznie dopisywane do salda. **Request body** | Field | Type | Description | | --- | --- | --- | | `piv_num_ids` * | string[] | Tablica ID numerów do przywrócenia. | **Errors** | Code | HTTP | When it fires | | --- | --- | --- | | `NO_RESTORABLE_NUMBERS` | 404 | Żaden z przekazanych numerów nie może być przywrócony (upłynął 7-dniowy termin lub numery nie należą do Ciebie). | | `INSUFFICIENT_BALANCE` | 402 | Niewystarczające środki na pokrycie przywrócenia. | **curl** ```bash curl -X POST https://app.piv.day/api/v1/numbers/restore \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "piv_num_ids": [ "vzPA1-kHKSg-EAL7e-Jqd3o", "abc12-defgh-ijklm-nopqr" ] }' ``` **200 OK** ```json { "success": true, "queued": 2, "skipped": 0, "total_charged": 9.00, "numbers": [ { "piv_num_id": "vzPA1-kHKSg-EAL7e-Jqd3o", "phone_number": "+46764794425", "status": "pending" } ] } ``` ### Historia SMS numeru `GET /api/v1/numbers/{piv_num_id}/sms` Zwraca przychodzące i wychodzące wiadomości dla numeru w odwrotnym porządku chronologicznym. **Query parameters** | Field | Type | Description | | --- | --- | --- | | `limit` | integer | Ile wiadomości zwrócić (domyślnie 50, maksymalnie 200). | | `offset` | integer | Przesunięcie paginacji. | **curl** ```bash curl "https://app.piv.day/api/v1/numbers/vzPA1-kHKSg-EAL7e-Jqd3o/sms?limit=20" \ -H "Authorization: Bearer YOUR_API_KEY" ``` **200 OK** ```json { "success": true, "data": { "messages": [ { "id": "42", "from_number": "+46764794425", "to_number": "+14155551234", "message_body": "Hello from piv.day", "direction": "outbound", "status": "delivered", "received_at": "2026-05-22T11:30:00Z" }, { "id": "41", "from_number": "+14155551234", "to_number": "+46764794425", "message_body": "Hey, got your message!", "direction": "inbound", "status": "received", "received_at": "2026-05-22T11:35:00Z" } ], "pagination": { "total": 2, "limit": 20, "offset": 0 } } } ``` ### Wyślij SMS `POST /api/v1/numbers/{piv_num_id}/sms/send` Dostępne dla krajów, gdzie dozwolone jest wysyłanie wychodzące (np. CA, GB, SE). Koszt wiadomości jest pobierany w momencie wysyłania. **Request body** | Field | Type | Description | | --- | --- | --- | | `to_number` * | string | Numer odbiorcy w formacie międzynarodowym (E.164). | | `message_body` * | string | Treść wiadomości. Obsługiwane są GSM-7 i UCS-2. | **Errors** | Code | HTTP | When it fires | | --- | --- | --- | | `NUMBER_NOT_FOUND` | 404 | Numer nie istnieje lub nie należy do konta. | | `NUMBER_EXPIRED` | 403 | Numer już wygasł. | | `NUMBER_NOT_ACTIVE` | 400 | Numer jest w stanie, który nie pozwala na wysyłanie. | | `INSUFFICIENT_BALANCE` | 402 | Niewystarczające środki na wysyłanie. | | `INVALID_MESSAGE_FORMAT` | 400 | Treść wiadomości przekracza dozwoloną długość lub zawiera zabronione znaki. | **curl** ```bash curl -X POST https://app.piv.day/api/v1/numbers/vzPA1-kHKSg-EAL7e-Jqd3o/sms/send \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "to_number": "+14155551234", "message_body": "Hello from piv.day" }' ``` **200 OK** ```json { "success": true, "data": { "message_id": "42", "from_number": "+46764794425", "to_number": "+14155551234", "message_body": "Hello from piv.day", "status": "queued", "created_at": "2026-05-22T11:30:00Z" } } ``` ### Uruchom weryfikację Google QR `POST /api/v1/numbers/{piv_num_id}/verify` Uruchamia weryfikację Google QR przy użyciu podanego URL. Wynik — sukces lub błąd — przychodzi przez webhook verify.completed lub verify.failed. Koszt jest pobierany w momencie kolejkowania zadania. **Request body** | Field | Type | Description | | --- | --- | --- | | `gv_url` * | string | Pełny URL weryfikacji Google (pobrany ze strony Google). | **Errors** | Code | HTTP | When it fires | | --- | --- | --- | | `NUMBER_NOT_FOUND` | 404 | Numer nie istnieje lub nie należy do Ciebie. | | `NUMBER_NOT_ACTIVE` | 400 | Numer nie jest aktywny. | | `SMS_DISABLED` | 400 | Wysyłanie SMS jest wyłączone dla tego numeru. | | `INSUFFICIENT_BALANCE` | 402 | Niewystarczające środki na weryfikację. | | `PROXY_DEAD` | 502 | Proxy niedostępne — saldo zwrócone. | | `QUEUE_FULL` | 503 | Kolejka jest pełna, spróbuj później — saldo zwrócone. | | `SERVER_UNAVAILABLE` | 503 | Serwer automatyzacji niedostępny — saldo zwrócone. | **curl** ```bash curl -X POST https://app.piv.day/api/v1/numbers/vzPA1-kHKSg-EAL7e-Jqd3o/verify \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "gv_url": "https://gv.google.com/..." }' ``` **202 Accepted** ```json { "success": true, "message": "Verification initiated" } ``` ## Proxy Residential IPv6 w dziesiątkach krajów. Zakup hurtowy, odnowienie, Restore z tym samym loginem i hasłem, eksport w wybranym formacie. ### Lista serwerów `GET /api/v1/proxy/servers` Dostępne serwery proxy z cenami. **curl** ```bash curl https://app.piv.day/api/v1/proxy/servers \ -H "Authorization: Bearer YOUR_API_KEY" ``` **200 OK** ```json { "success": true, "data": { "servers": [ { "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "name": "EU-DE-01", "country": "DE", "socks5_port": 1080, "http_port": 3128, "price_per_proxy": 0.50 }, { "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901", "name": "EU-NL-01", "country": "NL", "socks5_port": 1080, "http_port": 3128, "price_per_proxy": 0.45 } ] } } ``` ### Lista zamówień `GET /api/v1/proxy/orders` Lista Twoich zamówień proxy z możliwością filtrowania według statusu lub wyszukiwania. **Query parameters** | Field | Type | Description | | --- | --- | --- | | `limit` | integer | Rozmiar strony. Domyślnie 100, maksymalnie 500. | | `offset` | integer | Przesunięcie paginacji. | | `status` | string | Filtr statusu: `active`, `expired`. | | `search` | string | Wyszukiwanie w zamówieniach. | **curl** ```bash curl "https://app.piv.day/api/v1/proxy/orders?status=active&limit=20" \ -H "Authorization: Bearer YOUR_API_KEY" ``` **200 OK** ```json { "success": true, "data": { "orders": [ { "id": "ord-uuid-...", "country": "DE", "quantity": 10, "price_per_proxy": 0.50, "price_total": 5.00, "status": "active", "purchased_at": "2026-01-01T00:00:00Z", "expires_at": "2026-02-01T00:00:00Z" } ], "pagination": { "total": 1, "limit": 20, "offset": 0 } } } ``` ### Pobierz jedno zamówienie `GET /api/v1/proxy/orders/{id}` Pobierz szczegóły konkretnego zamówienia, w tym listę danych logowania proxy. **curl** ```bash curl https://app.piv.day/api/v1/proxy/orders/ord-uuid-... \ -H "Authorization: Bearer YOUR_API_KEY" ``` **200 OK** ```json { "success": true, "data": { "order": { "id": "ord-uuid-...", "country": "DE", "quantity": 10, "price_per_proxy": 0.50, "price_total": 5.00, "status": "active", "purchased_at": "2026-01-01T00:00:00Z", "expires_at": "2026-02-01T00:00:00Z", "created_at": "2026-01-01T00:00:00Z", "items": [ { "login": "user1", "password": "pass1", "host": "185.1.2.3", "socks5_port": 1080, "http_port": 3128, "ipv6": "2a00:1:2:3::1" } ] } } } ``` ### Kup proxy `POST /api/v1/proxy/purchase` Kup proxy na wybranym serwerze. Jedno żądanie tworzy jedno zamówienie z N proxy (do 500). Nie ma zamówień hurtowych — wywołaj metodę ponownie, jeśli potrzebujesz więcej. **Request body** | Field | Type | Description | | --- | --- | --- | | `server_id` * | string | ID serwera z `GET /proxy/servers`. | | `quantity` * | integer | Ile proxy kupić (1–500). | | `months` * | integer | Okres wynajmu w miesiącach (1–12). | **Errors** | Code | HTTP | When it fires | | --- | --- | --- | | `INSUFFICIENT_BALANCE` | 402 | Niewystarczające środki. | | `NOT_FOUND` | 404 | Serwer proxy nie został znaleziony lub jest nieaktywny. | | `VALIDATION_ERROR` | 400 | Nieprawidłowe ciało żądania. | **curl** ```bash curl -X POST https://app.piv.day/api/v1/proxy/purchase \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "server_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "quantity": 5, "months": 1 }' ``` **200 OK** ```json { "success": true, "data": { "order": { "id": "ord-uuid-...", "country": "DE", "quantity": 5, "price_total": 2.50, "status": "active", "expires_at": "2026-02-01T00:00:00Z", "created_at": "2026-01-01T00:00:00Z", "items": [ { "login": "user1", "password": "pass1", "host": "185.1.2.3", "socks5_port": 1080, "http_port": 3128, "ipv6": "2a00:1:2:3::1" }, { "login": "user2", "password": "pass2", "host": "185.1.2.3", "socks5_port": 1080, "http_port": 3128, "ipv6": "2a00:1:2:3::2" } ] } } } ``` ### Odnów zamówienie `POST /api/v1/proxy/orders/{id}/renew` Przedłuż aktywne zamówienie proxy o określoną liczbę miesięcy. **Request body** | Field | Type | Description | | --- | --- | --- | | `months` * | integer | Liczba miesięcy do dodania. | **curl** ```bash curl -X POST https://app.piv.day/api/v1/proxy/orders/ord-uuid-.../renew \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "months": 1 }' ``` **200 OK** ```json { "success": true, "data": { "order_id": "ord-uuid-...", "cost": 5.00, "new_expires_at": "2026-03-01T00:00:00Z" } } ``` ### Restore wygasłego zamówienia `POST /api/v1/proxy/orders/{id}/restore` Przywróć wygasłe zamówienie proxy bez ponownego zakupu. Login, hasło, adresy IPv6, kraj i powiązania — te same. Termin przedłużany o 1 miesiąc. Nie ma potrzeby ponownej konfiguracji antidetect. **curl** ```bash curl -X POST https://app.piv.day/api/v1/proxy/orders/ord-uuid-.../restore \ -H "Authorization: Bearer YOUR_API_KEY" ``` **200 OK** ```json { "success": true, "data": { "order_id": "ord-uuid-...", "quantity": 10, "total_cost": 5.00, "expires_at": "2026-03-01T00:00:00Z" } } ``` ### Eksportuj proxy `GET /api/v1/proxy/orders/{id}/export` Eksportuj dane logowania proxy zamówienia jako listę tekstową (login:password@host:port). **Query parameters** | Field | Type | Description | | --- | --- | --- | | `format` | string | Format eksportu: `socks5`, `http` lub `both` (domyślnie `socks5`). | **curl** ```bash curl "https://app.piv.day/api/v1/proxy/orders/ord-uuid-.../export?format=socks5" \ -H "Authorization: Bearer YOUR_API_KEY" ``` **200 OK** ```json { "success": true, "data": { "content": "user1:pass1@1.2.3.4:1080\nuser2:pass2@1.2.3.4:1080", "filename": "piv-day-proxy-ord-uuid--socks5.txt", "format": "socks5", "count": 2 } } ``` ## Domeny Wyszukiwanie i rejestracja bez KYC, automatyczny Cloudflare i SSL, zarządzanie rekordami DNS i serwerami NS przez API. ### Sprawdzenie dostępności `GET /api/v1/domains/search` Sprawdzić dostępność domeny i koszt jej rejestracji. **Query parameters** | Field | Type | Description | | --- | --- | --- | | `q` * | string | Nazwa domeny do wyszukania, np. `mysite.com`. | **curl** ```bash curl "https://app.piv.day/api/v1/domains/search?q=mysite.com" \ -H "Authorization: Bearer YOUR_API_KEY" ``` **200 OK** ```json { "success": true, "data": { "domain": "mysite.com", "available": true, "create_price": 12.50, "renew_price": 12.50, "currency": "USD" } } ``` ### Lista domen `GET /api/v1/domains` Lista zarejestrowanych domen z możliwością filtrowania. **Query parameters** | Field | Type | Description | | --- | --- | --- | | `limit` | integer | Rozmiar strony. Domyślnie 100, maksimum 500. | | `offset` | integer | Przesunięcie dla paginacji. | | `status` | string | Status domeny: `active`, `pending`, `expired`. | | `cloudflare` | string | Filtruj według statusu Cloudflare: `true` lub `false`. | | `auto_renew` | string | Filtruj według automatycznego odnawiania: `true` lub `false`. | | `search` | string | Wyszukaj według nazwy domeny. | **curl** ```bash curl "https://app.piv.day/api/v1/domains?status=active&limit=20" \ -H "Authorization: Bearer YOUR_API_KEY" ``` **200 OK** ```json { "success": true, "data": { "domains": [ { "id": "dom-uuid-...", "domain_name": "mysite.com", "status": "active", "registered_at": "2026-01-01T00:00:00Z", "expires_at": "2027-01-01T00:00:00Z", "auto_renew": true, "cloudflare_enabled": true, "cloudflare_status": "active", "ssl_type": "lets_encrypt", "ssl_status": "active", "ssl_mode": "full", "ssl_expires_at": "2026-04-01T00:00:00Z", "created_at": "2026-01-01T00:00:00Z", "updated_at": "2026-01-01T00:00:00Z" } ], "pagination": { "total": 1, "limit": 20, "offset": 0 } } } ``` ### Rejestracja domeny `POST /api/v1/domains` Zarejestrować nową domenę. Żądanie jest asynchroniczne — zwraca `queue_id` do śledzenia. Cloudflare WŁ: nie przekazywać `nameservers`; opcjonalnie można przekazać `dns_records` i `ssl_mode`. Cloudflare WYŁ: nie przekazywać `dns_records` ani `ssl_mode`; `nameservers` jest wymagany (co najmniej 2). Nigdy nie ujawniamy serwerów nazw Cloudflare. **Request body** | Field | Type | Description | | --- | --- | --- | | `domain` * | string | Nazwa domeny do rejestracji, np. `mysite.com`. | | `period` * | integer | Okres rejestracji w latach (1–10). | | `cloudflare` * | boolean | Automatycznie podłączyć domenę do Cloudflare. | | `auto_renew` * | boolean | Włączyć automatyczne odnawianie. | | `ssl_mode` | string | `flexible` \| `full` \| `strict`. Tylko przy `cloudflare: true`. | | `nameservers` | string[] | Wymagane przy `cloudflare: false` (≥2 NS). Zabronione przy `cloudflare: true`. | | `dns_records` | object[] | Początkowe rekordy DNS. Tylko przy `cloudflare: true`. | **Errors** | Code | HTTP | When it fires | | --- | --- | --- | | `DOMAIN_NOT_AVAILABLE` | 400 | Domena nie jest dostępna do rejestracji. | | `INSUFFICIENT_BALANCE` | 402 | Niewystarczające środki. | | `VALIDATION_ERROR` | 400 | Nieprawidłowe ciało żądania. | **Cloudflare WŁ** ```bash curl -X POST https://app.piv.day/api/v1/domains \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "domain": "mysite.com", "period": 1, "cloudflare": true, "auto_renew": true, "ssl_mode": "full", "dns_records": [ { "type": "A", "name": "@", "content": "1.2.3.4", "proxied": true } ] }' ``` **Cloudflare WYŁ — własne NS** ```bash curl -X POST https://app.piv.day/api/v1/domains \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "domain": "mysite.com", "period": 1, "cloudflare": false, "auto_renew": false, "nameservers": ["ns1.myhost.com", "ns2.myhost.com"] }' ``` **202 Accepted** ```json { "success": true, "data": { "queue_id": "que-uuid-...", "domain": { "id": "dom-uuid-...", "domain_name": "mysite.com", "status": "purchasing", "period": 1, "cloudflare_enabled": true, "auto_renew": true, "ssl_mode": "full", "created_at": "2026-01-01T00:00:00Z" } } } ``` ### Status zadania rejestracji `GET /api/v1/domains/queue/{id}` Sprawdzić status wpisu kolejki rejestracji lub odnawiania domeny. Przy statusie `completed` odpowiedź zawiera już pełną kartę domeny — osobne żądanie do `/domains/{id}` nie jest potrzebne. **curl** ```bash curl https://app.piv.day/api/v1/domains/queue/que-uuid-... \ -H "Authorization: Bearer YOUR_API_KEY" ``` **pending / processing** ```json { "success": true, "data": { "queue_id": "que-uuid-...", "domain": "mysite.com", "status": "pending" } } ``` **completed — pełna karta** ```json { "success": true, "data": { "queue_id": "que-uuid-...", "status": "completed", "domain": { "id": "dom-uuid-...", "domain_name": "mysite.com", "status": "active", "registered_at": "2026-01-01T12:00:00Z", "expires_at": "2027-01-01T12:00:00Z", "auto_renew": true, "cloudflare_enabled": true, "cloudflare_status": "active", "ssl_type": "lets_encrypt", "ssl_status": "active", "ssl_mode": "full", "ssl_expires_at": "2026-04-01T00:00:00Z", "created_at": "2026-01-01T00:00:00Z", "updated_at": "2026-01-01T12:00:00Z", "dns_records": [ { "name": "@", "type": "A", "content": "1.2.3.4", "ttl": 1, "priority": null, "proxied": true } ] } } } ``` ### Pobierz jedną domenę `GET /api/v1/domains/{id}` Pobierz pełne informacje o zarejestrowanej domenie. Pole `nameservers` jest obecne tylko gdy `cloudflare_enabled: false`. **curl** ```bash curl https://app.piv.day/api/v1/domains/dom-uuid-... \ -H "Authorization: Bearer YOUR_API_KEY" ``` **200 OK** ```json { "success": true, "data": { "domain": { "id": "dom-uuid-...", "domain_name": "mysite.com", "status": "active", "registered_at": "2026-01-01T12:00:00Z", "expires_at": "2027-01-01T12:00:00Z", "auto_renew": true, "cloudflare_enabled": true, "cloudflare_status": "active", "ssl_type": "lets_encrypt", "ssl_status": "active", "ssl_mode": "full", "ssl_expires_at": "2026-04-01T00:00:00Z", "created_at": "2026-01-01T00:00:00Z", "updated_at": "2026-01-01T12:00:00Z", "dns_records": [ { "name": "@", "type": "A", "content": "1.2.3.4", "ttl": 1, "priority": null, "proxied": true }, { "name": "www", "type": "CNAME", "content": "mysite.com", "ttl": 1, "priority": null, "proxied": true } ] } } } ``` ### Odnów domenę `POST /api/v1/domains/{id}/renew` Odnowić rejestrację domeny. Zwraca `queue_id` do śledzenia. **Request body** | Field | Type | Description | | --- | --- | --- | | `period` * | integer | O ile lat przedłużyć. | **curl** ```bash curl -X POST https://app.piv.day/api/v1/domains/dom-uuid-.../renew \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "period": 1 }' ``` **202 Accepted** ```json { "success": true, "data": { "queue_id": "que-uuid-...", "domain_id": "dom-uuid-...", "expires_at": "2027-01-01T12:00:00Z" } } ``` ### Przełącznik auto-odnawiania `POST /api/v1/domains/{id}/auto-renew` Włączyć lub wyłączyć automatyczne odnawianie domeny. **Request body** | Field | Type | Description | | --- | --- | --- | | `auto_renew` * | boolean | Nowa wartość flagi. | **curl** ```bash curl -X POST https://app.piv.day/api/v1/domains/dom-uuid-.../auto-renew \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "auto_renew": true }' ``` **200 OK** ```json { "success": true, "data": { "id": "dom-uuid-...", "auto_renew": true } } ``` ### Rekordy DNS domeny `GET /api/v1/domains/{id}/dns` Lista rekordów DNS domeny (przez Cloudflare). **curl** ```bash curl https://app.piv.day/api/v1/domains/dom-uuid-.../dns \ -H "Authorization: Bearer YOUR_API_KEY" ``` **200 OK** ```json { "success": true, "data": { "records": [ { "id": "rec-uuid-...", "type": "A", "name": "@", "content": "1.2.3.4", "ttl": 1, "priority": null, "proxied": true } ] } } ``` ### Dodaj rekord DNS `POST /api/v1/domains/{id}/dns` Utwórz nowy rekord DNS. **Request body** | Field | Type | Description | | --- | --- | --- | | `type` * | string | Typ rekordu: `A`, `AAAA`, `CNAME`, `MX`, `TXT` itp. | | `name` * | string | Nazwa rekordu, np. `@` lub `subdomain`. | | `content` * | string | Wartość rekordu. | | `ttl` | integer | TTL w sekundach (`1` = auto). | | `proxied` | boolean | Proxy przez Cloudflare. | **curl** ```bash curl -X POST https://app.piv.day/api/v1/domains/dom-uuid-.../dns \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "type": "A", "name": "@", "content": "1.2.3.4", "ttl": 1, "proxied": true }' ``` **201 Created** ```json { "success": true, "data": { "record": { "id": "rec-uuid-...", "type": "A", "name": "@", "content": "1.2.3.4", "ttl": 1, "priority": null, "proxied": true } } } ``` ### Zaktualizuj rekord DNS `PUT /api/v1/domains/{id}/dns/{recordId}` Zaktualizować istniejący rekord DNS po ID. Nadpisywane są tylko przekazane pola. **curl** ```bash curl -X PUT https://app.piv.day/api/v1/domains/dom-uuid-.../dns/rec-uuid-... \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "content": "5.6.7.8" }' ``` ### Usuń rekord DNS `DELETE /api/v1/domains/{id}/dns/{recordId}` Usuń rekord DNS po ID. **curl** ```bash curl -X DELETE https://app.piv.day/api/v1/domains/dom-uuid-.../dns/rec-uuid-... \ -H "Authorization: Bearer YOUR_API_KEY" ``` ### Włącz Cloudflare `POST /api/v1/domains/{id}/cloudflare` Włączyć Cloudflare dla domeny. Nie zwracamy serwerów nazw Cloudflare — delegację konfigurujemy po naszej stronie. Wyłączanie Cloudflare przez ten endpoint nie jest obsługiwane. **curl** ```bash curl -X POST https://app.piv.day/api/v1/domains/dom-uuid-.../cloudflare \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "enabled": true }' ``` **200 OK** ```json { "success": true, "data": { "domain_id": "dom-uuid-...", "ssl_mode": "flexible" } } ``` ### Ustaw serwery nazw `POST /api/v1/domains/{id}/ns-servers` Ustawić niestandardowe serwery nazw dla domeny. **curl** ```bash curl -X POST https://app.piv.day/api/v1/domains/dom-uuid-.../ns-servers \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "nameservers": ["ns1.example.com", "ns2.example.com"] }' ``` **200 OK** ```json { "success": true, "data": { "nameservers": [ { "nameserver": "ns1.example.com", "order_index": 1 }, { "nameserver": "ns2.example.com", "order_index": 2 } ] } } ``` ## White'y Generowanie white-page'ów według niszy i tiera. Każda strona jest unikalna. Zmiana domeny i kontaktów bez ponownej generacji. ### Lista tierów `GET /api/v1/whites/tiers` Dostępne tiery generacji z cenami. `price` to cena za generację dopasowana do twojego konta (z uwzględnieniem subskrypcji), pojedyncza liczba. `quality: "premium"` kosztuje więcej (obliczane przy tworzeniu). Blog tylko w `v2_tier3`: pierwsze 3 artykuły są wliczone, każdy kolejny (do 20) jest naliczany jako `extra_article_price`. **curl** ```bash curl https://app.piv.day/api/v1/whites/tiers \ -H "Authorization: Bearer YOUR_API_KEY" ``` **200 OK** ```json { "success": true, "data": { "tiers": [ { "tier_key": "v2_tier1", "name": "Landing", "generator_version": "v2", "min_articles": 0, "max_articles": 0, "price": 3.00, "extra_article_price": null }, { "tier_key": "v2_tier2", "name": "Multi-page", "generator_version": "v2", "min_articles": 0, "max_articles": 0, "price": 6.00, "extra_article_price": null }, { "tier_key": "v2_tier3", "name": "Full + Blog", "generator_version": "v2", "min_articles": 3, "max_articles": 20, "price": 10.00, "extra_article_price": 1.50 } ] } } ``` ### Lista white'ów `GET /api/v1/whites` Lista twoich zadań generacji z możliwością filtrowania. **Query parameters** | Field | Type | Description | | --- | --- | --- | | `limit` | integer | Rozmiar strony. Domyślnie 100, maksymalnie 500. | | `offset` | integer | Offset paginacji. | | `status` | string | `queued` \| `processing` \| `done` \| `failed`. | | `tier_key` | string | `v2_tier1` \| `v2_tier2` \| `v2_tier3`. | **curl** ```bash curl "https://app.piv.day/api/v1/whites?status=done&limit=20" \ -H "Authorization: Bearer YOUR_API_KEY" ``` **200 OK** ```json { "success": true, "data": { "whites": [ { "id": "job-uuid-...", "name": "My White", "status": 10, "tier_key": "v2_tier3", "quality": "standard", "niche": "IT Consulting", "country": "DE", "language": "de", "domain": "mysite.com", "result_url": null, "created_at": "2026-01-01T00:00:00Z" } ], "pagination": { "total": 1, "limit": 20, "offset": 0 } } } ``` ### Uruchom generację `POST /api/v1/whites` Dodaj zadanie generacji white-page do kolejki. Płatność jest pobierana natychmiast. Końcowy status trafia na webhook `white.completed` / `white.failed` lub można go sprawdzić przez `GET /whites/{id}`. **Request body** | Field | Type | Description | | --- | --- | --- | | `name` * | string | Nazwa zadania (2–20 znaków). | | `tier_key` * | string | `v2_tier1` \| `v2_tier2` \| `v2_tier3`. | | `niche` * | string | Nisza strony (do 25 znaków). | | `country` * | string | Kod kraju (ISO 3166-1 alpha-2). | | `language` * | string | Główny język strony (ISO 639-1). | | `quality` | string | `standard` \| `premium` (domyślnie `standard`). | | `languages` | string[] | Lista języków. Pierwszy jest wliczony w cenę; każdy dodatkowy kosztuje więcej. | | `domain` | string | Pełna domena (np. `example.com`). Bez autouzupełniania. | | `email` | string | Pełny adres email (np. `info@example.com`). Bez autouzupełniania. | | `phone` | string | Telefon kontaktowy. | | `address` | string | Adres firmy. | | `legal_name` | string | Nazwa prawna. | | `style_hint` | string | Styl designu (Random, Minimalistyczny, Korporacyjny itd.). | | `keywords` | string[] | Słowa kluczowe SEO. | | `banned_words` | string[] | Słowa zakazane w treści. | | `blog_count` | integer | Liczba artykułów bloga 3–20. Tylko dla `v2_tier3`. Artykuły powyżej 3 są dodatkowo płatne. | | `contacts_mode` | string | `same` \| `template`. | | `contacts_template` | string | Szablon strony kontaktowej (gdy `contacts_mode=template`). | | `facebook` | string | Pełny URL strony Facebook. | | `instagram` | string | Pełny URL profilu Instagram. | | `linkedin` | string | Pełny URL profilu LinkedIn. | | `youtube` | string | Pełny URL kanału YouTube. | | `tiktok` | string | Pełny URL profilu TikTok. | **Errors** | Code | HTTP | When it fires | | --- | --- | --- | | `INSUFFICIENT_BALANCE` | 402 | Niewystarczające środki. | | `INVALID_TIER` | 400 | Nie znaleziono tiera z takim kluczem. | | `VALIDATION_ERROR` | 400 | Nieprawidłowe ciało żądania. | **curl** ```bash curl -X POST https://app.piv.day/api/v1/whites \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Tech Blog DE", "tier_key": "v2_tier3", "niche": "IT Consulting", "country": "DE", "language": "de", "quality": "premium", "languages": ["de", "en"], "domain": "techblog-de.com", "email": "info@techblog-de.com", "phone": "+49 30 123456", "address": "Berliner Str. 1, 10115 Berlin", "legal_name": "TechBlog GmbH", "style_hint": "Корпоративный", "keywords": ["IT", "consulting", "cloud"], "banned_words": ["cheap", "free"], "blog_count": 8, "contacts_mode": "same", "facebook": "https://facebook.com/techblogde", "instagram": "https://instagram.com/techblogde", "linkedin": "https://linkedin.com/company/techblogde" }' ``` **200 OK** ```json { "success": true, "data": { "status": "queued", "white": { "id": "job-uuid-...", "name": "Tech Blog DE", "status": 0, "tier_key": "v2_tier3", "quality": "premium", "niche": "IT Consulting", "country": "DE", "language": "de", "domain": "techblog-de.com", "result_url": null, "created_at": "2026-01-01T00:00:00Z" } } } ``` ### Pobierz jeden white `GET /api/v1/whites/{id}` Pobierz bieżący stan zadania generacji. **curl** ```bash curl https://app.piv.day/api/v1/whites/job-uuid-... \ -H "Authorization: Bearer YOUR_API_KEY" ``` **200 OK** ```json { "success": true, "data": { "white": { "id": "job-uuid-...", "name": "Tech Blog DE", "status": 10, "tier_key": "v2_tier3", "quality": "premium", "niche": "IT Consulting", "country": "DE", "language": "de", "domain": "techblog-de.com", "result_url": null, "created_at": "2026-01-01T00:00:00Z" } } } ``` ### Pobierz archiwum `GET /api/v1/whites/{id}/download` Pobierz krótkotrwały podpisany link do gotowego archiwum white-page. Link jest ważny przez ~5 minut (patrz `expires_at`). Jeśli wygasł — ponownie wywołaj `/download`, a wystawimy nowy. Jeśli white page nie jest jeszcze wygenerowany, zwracany jest `409 NOT_READY`. **Query parameters** | Field | Type | Description | | --- | --- | --- | | `format` | string | Format archiwum. Domyślnie `php`. | **Errors** | Code | HTTP | When it fires | | --- | --- | --- | | `NOT_READY` | 409 | White page jest jeszcze generowany — ponów żądanie po `white.completed`. | **curl** ```bash curl "https://app.piv.day/api/v1/whites/job-uuid-.../download?format=php" \ -H "Authorization: Bearer YOUR_API_KEY" ``` **200 OK** ```json { "success": true, "data": { "url": "https://strg.piv.day/download//?format=php&token=&filename=.zip", "filename": "example.com_2026-05-28_DE_en.zip", "format": "php", "expires_at": "2026-05-28T14:46:00Z" } } ``` ### Zmień domenę i kontakty `POST /api/v1/whites/{id}/config` Zaktualizuj dane kontaktowe firmy w white-page bez ponownej generacji. **curl** ```bash curl -X POST https://app.piv.day/api/v1/whites/job-uuid-.../config \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "company": "My Brand", "domain": "newdomain.com", "email": "info@newdomain.com", "phone": "+49 30 123456", "address": "Berliner Str. 1, Berlin", "legal": "My Brand GmbH" }' ``` ## Webhooks Na Twój URL wysyłamy zwykły POST z ciałem JSON. Format jest taki sam dla wszystkich zdarzeń: `event_type`, `timestamp` i blok `data`. Twój serwer powinien odpowiedzieć dowolnym 2xx w ciągu 5 sekund. ``` POST Content-Type: application/json User-Agent: piv.day-webhook/1.0 { "event_type": "", "timestamp": "2026-05-22T12:34:56Z", "data": { ... } } ``` **Retries.** W przypadku nie-2xx lub przekroczenia czasu — do 3 ponownych prób z opóźnieniem 1s / 2s / 4s. Pełna historia dostarczeń jest dostępna na stronie kluczy API w dashboardzie. Jeśli wszystkie trzy nie powiodą się — zdarzenie jest oznaczane jako failed i można je ponownie wysłać ręcznie. **Security.** Używaj endpointu HTTPS. Każde żądanie przychodzi z nagłówkiem `User-Agent: piv.day-webhook/1.0`. URL webhooka jest konfigurowany w profilu klucza API. ### All events | Event | When it fires | | --- | --- | | `sms.received` | Zaufany nadawca właśnie wysłał SMS na jeden z Twoich numerów. | | `sms.status_updated` | Wychodzący SMS zmienił status — np. został dostarczony lub nie powiódł się. | | `number.restore_completed` | Wsadowy Restore dobiegł końca — tutaj trafia końcowe podsumowanie. | | `verify.completed` | Weryfikacja konta Google zakończyła się pomyślnie. | | `verify.failed` | Coś poszło nie tak — Google nie zaakceptował. | | `proxy.expires_soon` | Do końca zamówienia proxy pozostały około trzy dni. | | `domain.registered` | Zamówienie rejestracji zakończyło się pomyślnie — domena jest aktywna. | | `domain.failed` | Zamówienie nie zostało zrealizowane — częsta przyczyna: nazwa właśnie została zajęta. | | `domain.expires_soon` | Do wygaśnięcia domeny pozostał około tydzień. | | `white.completed` | Zadanie generowania White zakończyło się pomyślnie. | | `white.failed` | Zadanie nie powiodło się — środki są zwracane na saldo. | ### Przychodzący SMS na Twój numer **`sms.received`** Najczęściej są to kody weryfikacyjne z sieci reklamowych. Payload zawiera zarówno surowy tekst, jak i automatycznie wykryty kod (jeśli jest) — możesz go od razu przekazać do swojego workflow bez parsowania. Wiadomości od znanych nadawców spamu nie są przekazywane. ```json { "event_type": "sms.received", "timestamp": "2026-05-22T12:34:56Z", "data": { "piv_num_id": "vzPA1-kHKSg-EAL7e-Jqd3o", "text": "Your verification code is 123456", "code": "123456", "country": "SE", "received_at": "2026-05-22T12:34:56Z" } } ``` ### Status wysłanego SMS-a się zmienił **`sms.status_updated`** Przydatne, gdy wysyłasz potwierdzenia z własnego numeru i chcesz wiedzieć, czy wiadomość dotarła. Jeśli status to failed — w payload przychodzą kod błędu i komunikat od operatora. ```json { "event_type": "sms.status_updated", "timestamp": "2026-05-22T12:34:56Z", "data": { "piv_num_id": "vzPA1-kHKSg-EAL7e-Jqd3o", "message_id": "42", "old_status": "sent", "new_status": "delivered", "error_code": null, "error_message": null } } ``` ### Przywracanie numerów zakończone **`number.restore_completed`** Zawiera dwie listy: które numery wróciły i które nie. Zwrócona kwota za te, które nie wróciły, jest też w payload. Wygodne dla skryptów, które chcą inteligentnie ponowić próbę. ```json { "event_type": "number.restore_completed", "timestamp": "2026-05-22T12:34:56Z", "data": { "restored": [ { "piv_num_id": "vzPA1-kHKSg-EAL7e-Jqd3o", "phone_number": "+46764794425", "country": "SE" } ], "failed": [ { "piv_num_id": "abc12-defgh-ijklm-nopqr", "phone_number": "+46123456789", "country": "SE", "refunded": 7.50 } ], "total_restored": 1, "total_failed": 1, "total_refunded": 7.50 } } ``` ### Weryfikacja Google QR zakończona sukcesem **`verify.completed`** Jeśli podczas procesu przyszedł SMS z kodem — jest już tutaj, nie trzeba go osobno pobierać. Pola captured_phone i captured_message zawierają to, co wysłał Google. ```json { "event_type": "verify.completed", "timestamp": "2026-05-22T12:34:56Z", "data": { "task_id": 12, "piv_num_id": "vzPA1-kHKSg-EAL7e-Jqd3o", "status": "sms_sent", "captured_phone": "+14155551234", "captured_message": "Your Google verification code is 123456", "sms_message_id": 42, "sms_status": "queued" } } ``` ### Weryfikacja Google QR nieudana **`verify.failed`** error_code mówi dokładnie co: timeout, odrzucenie, nieprawidłowy URL. Za nieudane weryfikacje kwota jest automatycznie zwracana na saldo. ```json { "event_type": "verify.failed", "timestamp": "2026-05-22T12:34:56Z", "data": { "task_id": 12, "piv_num_id": "vzPA1-kHKSg-EAL7e-Jqd3o", "status": "failed", "error_code": "VERIFY_TIMEOUT", "error_message": "Verification timed out" } } ``` ### Proxy wkrótce wygaśnie **`proxy.expires_soon`** Dla tych, którzy nie odnawiają automatycznie: widzisz to z wyprzedzeniem i decydujesz — przedłużyć czy zakończyć kampanię. Podepnij pod POST /proxy/orders/{id}/renew, aby odnawiać w pełni automatycznie. ```json { "event_type": "proxy.expires_soon", "timestamp": "2026-05-22T12:34:56Z", "data": { "order_id": "ord-uuid-...", "country": "DE", "quantity": 10, "expires_at": "2026-05-25T00:00:00Z" } } ``` ### Domena zarejestrowana **`domain.registered`** Jeśli przy zakupie zażądałeś Cloudflare i SSL, oba są już aktywne — flaga cloudflare_enabled pokazuje status. Możesz od razu dodawać rekordy DNS lub wdrożyć stronę. ```json { "event_type": "domain.registered", "timestamp": "2026-05-22T12:34:56Z", "data": { "domain_id": "dom-uuid-...", "domain_name": "mysite.com", "registered_at": "2026-05-22T12:34:56Z", "expires_at": "2027-05-22T12:34:56Z", "cloudflare_enabled": true } } ``` ### Rejestracja domeny nie powiodła się **`domain.failed`** Pole error zawiera czytelne dla człowieka wyjaśnienie. Kwota jest zwracana na saldo. Można wybrać inną nazwę i złożyć zamówienie ponownie. ```json { "event_type": "domain.failed", "timestamp": "2026-05-22T12:34:56Z", "data": { "domain_id": "dom-uuid-...", "domain_name": "mysite.com", "error": "Domain is no longer available" } } ``` ### Domena wkrótce wygaśnie **`domain.expires_soon`** Wygodne, gdy automatyczne odnawianie jest wyłączone: masz czas, aby odnowić ręcznie, zanim domena przejdzie w fazę redemption. Flaga auto_renew poinformuje, czy konieczna jest interwencja. ```json { "event_type": "domain.expires_soon", "timestamp": "2026-05-22T12:34:56Z", "data": { "domain_id": "dom-uuid-...", "domain_name": "mysite.com", "expires_at": "2026-05-29T00:00:00Z", "auto_renew": false } } ``` ### White wygenerowany **`white.completed`** Archiwum jest dostępne przez GET /whites/{id}/download. Jeśli White miał ustawioną domenę, sitemap i kontakty są już pod nią skonfigurowane — gotowe do wdrożenia. ```json { "event_type": "white.completed", "timestamp": "2026-05-22T12:34:56Z", "data": { "job_id": "job-uuid-...", "name": "My White", "tier_key": "t1", "country": "DE" } } ``` ### Generowanie White nieudane **`white.failed`** Pole error wyjaśnia przyczynę. Możesz od razu uruchomić nowe zadanie przez POST /whites — bez strat. ```json { "event_type": "white.failed", "timestamp": "2026-05-22T12:34:56Z", "data": { "job_id": "job-uuid-...", "name": "My White", "error": "Generation failed" } } ``` ## Error codes Wszystkie błędy mają ten sam format: status HTTP + pole `error.code` + czytelna wiadomość w `error.message`. ```json { "success": false, "error": { "code": "INSUFFICIENT_BALANCE", "message": "Not enough balance: required $5.00, available $1.20" } } ``` | Code | HTTP | When it fires | | --- | --- | --- | | `UNAUTHORIZED` | 401 | Klucz jest nieobecny, wygasł lub został odwołany. | | `INSUFFICIENT_PERMISSIONS` | 403 | Klucz nie posiada wymaganego scope dla tej operacji. | | `PERMISSION_DENIED` | 403 | Dostęp na poziomie konta nie zezwala na tę operację (np. funkcja wyłączona). | | `VALIDATION_ERROR` | 400 | Nieprawidłowe ciało żądania. Wiadomość wyjaśnia, które pole jest błędne i dlaczego. | | `NUMBER_NOT_FOUND` | 404 | Numer nie istnieje lub nie należy do tego konta. | | `NUMBER_EXPIRED` | 403 | Numer wygasł — użyj Restore (w ciągu 7 dni) lub kup nowy. | | `NUMBER_NOT_ACTIVE` | 400 | Numer jest w stanie, który nie zezwala na tę operację. | | `INSUFFICIENT_BALANCE` | 402 | Niewystarczające środki do wykonania tej operacji. | | `INVALID_MESSAGE_FORMAT` | 400 | Treść SMS jest zbyt długa lub zawiera niedozwolone znaki. | | `COUNTRY_NOT_AVAILABLE` | 400 | Kraj jest niedostępny do zakupu lub odnowienia. | | `NO_NUMBERS_AVAILABLE` | 400 | W wybranym kraju nie ma teraz dostępnych numerów. | | `NO_RESTORABLE_NUMBERS` | 404 | Żaden z podanych numerów nie może być już przywrócony. | | `RATE_LIMITED` | 429 | Przekroczono rate limit. Poczekaj czas podany w nagłówku `Retry-After`. | | `INTERNAL_ERROR` | 500 | Coś poszło nie tak po naszej stronie. Jeśli problem się powtarza — skontaktuj się z pomocą techniczną. |