# 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 no plano Business. Tokens Bearer, JSON, endpoints idempotentes, códigos de erro previsíveis. Cada endpoint inclui um exemplo de requisição e resposta. ### Base URL ``` https://app.piv.day/api/v1 ``` Todos os endpoints ficam sob este prefixo. Um único ambiente — sem hosts de staging separados. ### Autenticação ``` Authorization: Bearer YOUR_API_KEY ``` As chaves são criadas no dashboard em `Configurações → API Keys`. Cada chave possui escopos granulares (leitura de números, envio de SMS, compra de proxies, etc.). Um token comprometido é rotacionado com um clique — sem necessidade de recadastrar o time. ### Conta **200 OK** ``` curl https://app.piv.day/api/v1/account \ -H "Authorization: Bearer YOUR_API_KEY" ``` **Um único endpoint utilitário — saldo e email da conta atual. Útil para confirmar que a chave funciona e que a autenticação está configurada corretamente.** ``` { "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 ### Formato de resposta ``` { "success": true, "data": { ... } } ``` Todas as respostas são JSON. Em caso de erro, `success` é `false` e o corpo contém `error.code` e `error.message`. ### Rate limits **100 requisições por minuto por API key. O limite é compartilhado entre todos os endpoints. Precisa de mais capacidade para um pico? Fale com o suporte no Telegram e aumentaremos o limite. Ao exceder o limite, você recebe `429 RATE_LIMITED` e o header `Retry-After` — quantos segundos aguardar antes da próxima chamada.** ``` 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 ## Números Compre, renove e restaure números. Receba e envie SMS. Inicie verificações Google QR. Assine eventos via webhooks. ### Países e preços `GET /api/v1/numbers/countries` Retorna países disponíveis para compra com o preço atual e recursos de SMS. Todos os preços incluem o desconto da sua assinatura. **Response fields** | Field | Type | Description | | --- | --- | --- | | `country_code` | string | Código de país ISO de duas letras (ex.: `SE`). | | `price_per_month` | number | Preço final para seu plano — o que é cobrado na compra. Descontos Premium / Business já estão aplicados. | | `base_price` | number | Preço sem descontos (plano Free). Retornado para comparação para ver quanto a assinatura economiza. | | `can_send_sms` | boolean | Se o envio de SMS de saída é suportado a partir deste número. | | `can_receive_sms` | boolean | Se o recebimento de SMS de entrada é suportado. | | `sms_send_price` | number\|null | Preço por SMS de saída, também com o desconto do plano aplicado. `null` quando o envio não é suportado neste país. | **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 } ] } ``` ### Listar números `GET /api/v1/numbers` Retorna uma página de números da conta com filtros por país, status e busca por número ou nome personalizado. **Query parameters** | Field | Type | Description | | --- | --- | --- | | `limit` | integer | Tamanho da página (padrão 50, máximo 200). | | `offset` | integer | Offset de paginação. | | `country` | string | Filtro de código de país ISO. | | `status` | string | Um de `active`, `expired`, `pending_restore`. | | `search` | string | Busca por substring no número de telefone ou nome personalizado. | **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 } } } ``` ### Obter um número por ID `GET /api/v1/numbers/{piv_num_id}` Registro completo do número: status, datas, renovação automática, tags, direções SMS permitidas. **Errors** | Code | HTTP | When it fires | | --- | --- | --- | | `NUMBER_NOT_FOUND` | 404 | O número não existe ou não pertence à conta. | **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 } } ``` ### Comprar um número `POST /api/v1/numbers/purchase` Compra um único número no país selecionado pelo período especificado. O custo é debitado do saldo da conta. Retorna `piv_num_id` usado em todas as operações posteriores do número. **Request body** | Field | Type | Description | | --- | --- | --- | | `country_code` * | string | Código de país ISO. | | `duration_months` * | integer | Período de aluguel em meses (mínimo 1). | | `auto_renew` * | boolean | Ativar renovação automática logo após a compra. | | `custom_name` | string | Nome amigável opcional para o número. | **Errors** | Code | HTTP | When it fires | | --- | --- | --- | | `COUNTRY_NOT_AVAILABLE` | 400 | País não disponível ou sem preços. | | `NO_NUMBERS_AVAILABLE` | 400 | Não há números disponíveis no país solicitado no momento. | | `INSUFFICIENT_BALANCE` | 402 | Saldo insuficiente para a compra. | | `VALIDATION_ERROR` | 400 | Campos inválidos no corpo da requisição. | **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" } ] } ``` ### Renovar um número `POST /api/v1/numbers/{piv_num_id}/renew` Estende um número ativo pelo período especificado. O custo é debitado no momento da chamada. **Request body** | Field | Type | Description | | --- | --- | --- | | `duration_months` * | integer | Número de meses a adicionar. | **Errors** | Code | HTTP | When it fires | | --- | --- | --- | | `NUMBER_NOT_FOUND` | 404 | O número não existe ou não pertence à conta. | | `COUNTRY_NOT_AVAILABLE` | 400 | Nenhum preço encontrado para o país do número. | | `INSUFFICIENT_BALANCE` | 402 | Saldo insuficiente para renovar. | **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 } } ``` ### Atualizar um número `PATCH /api/v1/numbers/{piv_num_id}` Atualmente apenas o nome personalizado pode ser atualizado. **Request body** | Field | Type | Description | | --- | --- | --- | | `custom_name` * | string | Novo nome para o número. | **Errors** | Code | HTTP | When it fires | | --- | --- | --- | | `NUMBER_NOT_FOUND` | 404 | O número não existe ou não pertence à conta. | | `VALIDATION_ERROR` | 400 | Valor inválido no corpo da requisição. | **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": [] } } ``` ### Gerenciar renovação automática `PATCH /api/v1/numbers/{piv_num_id}/auto-renewal` Ativa ou desativa a renovação automática do número. Quando ativada, a renovação é debitada automaticamente 24 horas antes do vencimento. Se o saldo for insuficiente, o número expira; você pode recuperá-lo via `POST /numbers/restore` dentro de 7 dias. **Request body** | Field | Type | Description | | --- | --- | --- | | `auto_renew` * | boolean | Novo valor do sinalizador de renovação automática. | **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 } } ``` ### Restaurar números expirados `POST /api/v1/numbers/restore` Recupera números expirados dentro de um período de 7 dias. Passe um array de `piv_num_id` — os números retornam com histórico SMS e configurações preservadas. A restauração custa mais do que comprar um número novo (inclui um multiplicador de restauração) — os valores exatos aparecem no dashboard antes da confirmação. O status final de cada número chega via webhook `number.restore_completed`; reembolsos por números malsucedidos são creditados automaticamente. **Request body** | Field | Type | Description | | --- | --- | --- | | `piv_num_ids` * | string[] | Array de IDs de números para restaurar. | **Errors** | Code | HTTP | When it fires | | --- | --- | --- | | `NO_RESTORABLE_NUMBERS` | 404 | Nenhum dos números fornecidos pode ser restaurado (período de 7 dias expirou ou não são seus). | | `INSUFFICIENT_BALANCE` | 402 | Saldo insuficiente para cobrir a restauração. | **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" } ] } ``` ### Histórico de SMS do número `GET /api/v1/numbers/{piv_num_id}/sms` Retorna mensagens de entrada e saída do número em ordem cronológica reversa. **Query parameters** | Field | Type | Description | | --- | --- | --- | | `limit` | integer | Quantas mensagens retornar (padrão 50, máximo 200). | | `offset` | integer | Offset de paginação. | **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 } } } ``` ### Enviar SMS `POST /api/v1/numbers/{piv_num_id}/sms/send` Disponível para países onde o envio de saída é permitido (ex.: CA, GB, SE). O custo da mensagem é debitado no momento do envio. **Request body** | Field | Type | Description | | --- | --- | --- | | `to_number` * | string | Número do destinatário no formato internacional (E.164). | | `message_body` * | string | Texto da mensagem. GSM-7 e UCS-2 são suportados. | **Errors** | Code | HTTP | When it fires | | --- | --- | --- | | `NUMBER_NOT_FOUND` | 404 | O número não existe ou não pertence à conta. | | `NUMBER_EXPIRED` | 403 | O número já expirou. | | `NUMBER_NOT_ACTIVE` | 400 | O número está em um estado que não permite envio. | | `INSUFFICIENT_BALANCE` | 402 | Saldo insuficiente para enviar. | | `INVALID_MESSAGE_FORMAT` | 400 | O corpo da mensagem excede o comprimento permitido ou contém caracteres proibidos. | **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" } } ``` ### Iniciar verificação Google QR `POST /api/v1/numbers/{piv_num_id}/verify` Inicia uma verificação Google QR usando a URL fornecida. O resultado — sucesso ou falha — chega via webhook verify.completed ou verify.failed. O custo é debitado quando a tarefa é enfileirada. **Request body** | Field | Type | Description | | --- | --- | --- | | `gv_url` * | string | URL completa de verificação do Google (retirada da página do Google). | **Errors** | Code | HTTP | When it fires | | --- | --- | --- | | `NUMBER_NOT_FOUND` | 404 | O número não existe ou não é seu. | | `NUMBER_NOT_ACTIVE` | 400 | O número não está ativo. | | `SMS_DISABLED` | 400 | O envio de SMS está desativado para este número. | | `INSUFFICIENT_BALANCE` | 402 | Saldo insuficiente para a verificação. | | `PROXY_DEAD` | 502 | Proxy indisponível — saldo reembolsado. | | `QUEUE_FULL` | 503 | Fila cheia, tente mais tarde — saldo reembolsado. | | `SERVER_UNAVAILABLE` | 503 | Servidor de automação indisponível — saldo reembolsado. | **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 IPv6 residencial em dezenas de países. Compra em massa, renovação, Restore mantendo o mesmo login e senha, exportação no formato desejado. ### Lista de servidores `GET /api/v1/proxy/servers` Servidores proxy disponíveis com preços. **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 de pedidos `GET /api/v1/proxy/orders` Lista dos seus pedidos de proxy com filtros por status ou pesquisa. **Query parameters** | Field | Type | Description | | --- | --- | --- | | `limit` | integer | Tamanho da página. Padrão 100, máximo 500. | | `offset` | integer | Deslocamento de paginação. | | `status` | string | Filtro por status: `active`, `expired`. | | `search` | string | Pesquisa em pedidos. | **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 } } } ``` ### Obter um pedido `GET /api/v1/proxy/orders/{id}` Obter os detalhes de um pedido específico, incluindo a lista de credenciais de 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" } ] } } } ``` ### Comprar proxies `POST /api/v1/proxy/purchase` Comprar proxies no servidor escolhido. Uma requisição cria um pedido com N proxies (até 500). Não há pedidos em massa — chame o método novamente se precisar de mais. **Request body** | Field | Type | Description | | --- | --- | --- | | `server_id` * | string | ID do servidor de `GET /proxy/servers`. | | `quantity` * | integer | Quantos proxies comprar (1–500). | | `months` * | integer | Período de locação em meses (1–12). | **Errors** | Code | HTTP | When it fires | | --- | --- | --- | | `INSUFFICIENT_BALANCE` | 402 | Saldo insuficiente. | | `NOT_FOUND` | 404 | Servidor proxy não encontrado ou inativo. | | `VALIDATION_ERROR` | 400 | Corpo da requisição inválido. | **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" } ] } } } ``` ### Renovar um pedido `POST /api/v1/proxy/orders/{id}/renew` Estender um pedido de proxy ativo por um número de meses. **Request body** | Field | Type | Description | | --- | --- | --- | | `months` * | integer | Meses a adicionar. | **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 de pedido vencido `POST /api/v1/proxy/orders/{id}/restore` Recuperar um pedido de proxy vencido sem recompra. Login, senha, endereços IPv6, país e vinculações — os mesmos. O prazo é estendido por 1 mês. Sem necessidade de reconfigurar o 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" } } ``` ### Exportar proxies `GET /api/v1/proxy/orders/{id}/export` Exportar as credenciais de proxy do pedido como uma lista de texto (login:password@host:port). **Query parameters** | Field | Type | Description | | --- | --- | --- | | `format` | string | Formato de exportação: `socks5`, `http` ou `both` (padrão `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 } } ``` ## Domínios Pesquisa e registro sem KYC, Cloudflare e SSL automáticos, gerenciamento de registros DNS e servidores NS via API. ### Verificação de disponibilidade `GET /api/v1/domains/search` Verificar se um domínio está disponível e quanto custa registrá-lo. **Query parameters** | Field | Type | Description | | --- | --- | --- | | `q` * | string | Nome de domínio para pesquisar, ex.: `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" } } ``` ### Listar domínios `GET /api/v1/domains` Lista dos seus domínios registrados com filtragem. **Query parameters** | Field | Type | Description | | --- | --- | --- | | `limit` | integer | Tamanho da página. Padrão 100, máximo 500. | | `offset` | integer | Offset de paginação. | | `status` | string | Status do domínio: `active`, `pending`, `expired`. | | `cloudflare` | string | Filtrar por status do Cloudflare: `true` ou `false`. | | `auto_renew` | string | Filtrar por renovação automática: `true` ou `false`. | | `search` | string | Pesquisar por nome de domínio. | **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 } } } ``` ### Registrar um domínio `POST /api/v1/domains` Registrar um novo domínio. A requisição é assíncrona — retorna `queue_id` para rastreamento. Cloudflare ATIVADO: não passe `nameservers`; opcionalmente pode passar `dns_records` e `ssl_mode`. Cloudflare DESATIVADO: não passe `dns_records` nem `ssl_mode`; `nameservers` é obrigatório (mínimo 2). Nunca expomos os nameservers do Cloudflare. **Request body** | Field | Type | Description | | --- | --- | --- | | `domain` * | string | Nome de domínio a registrar, ex.: `mysite.com`. | | `period` * | integer | Período de registro em anos (1–10). | | `cloudflare` * | boolean | Conectar o domínio ao Cloudflare automaticamente. | | `auto_renew` * | boolean | Ativar renovação automática. | | `ssl_mode` | string | `flexible` \| `full` \| `strict`. Somente com `cloudflare: true`. | | `nameservers` | string[] | Obrigatório com `cloudflare: false` (≥2 NS). Proibido com `cloudflare: true`. | | `dns_records` | object[] | Registros DNS iniciais. Somente com `cloudflare: true`. | **Errors** | Code | HTTP | When it fires | | --- | --- | --- | | `DOMAIN_NOT_AVAILABLE` | 400 | O domínio não está disponível para registro. | | `INSUFFICIENT_BALANCE` | 402 | Saldo insuficiente. | | `VALIDATION_ERROR` | 400 | Corpo da requisição inválido. | **Cloudflare ATIVADO** ```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 DESATIVADO — NS próprios** ```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 da fila de registro `GET /api/v1/domains/queue/{id}` Verificar o status de uma entrada na fila de registro ou renovação de domínio. No status `completed`, a resposta já traz o cartão completo do domínio — não é necessária uma chamada separada a `/domains/{id}`. **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 — cartão completo** ```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 } ] } } } ``` ### Obter um domínio `GET /api/v1/domains/{id}` Obter informações completas sobre um domínio registrado. O campo `nameservers` está presente somente quando `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 } ] } } } ``` ### Renovar domínio `POST /api/v1/domains/{id}/renew` Renovar o registro do domínio. Retorna `queue_id` para rastreamento. **Request body** | Field | Type | Description | | --- | --- | --- | | `period` * | integer | Anos a adicionar. | **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" } } ``` ### Alternar renovação automática `POST /api/v1/domains/{id}/auto-renew` Ativar ou desativar a renovação automática do domínio. **Request body** | Field | Type | Description | | --- | --- | --- | | `auto_renew` * | boolean | Novo valor do sinalizador. | **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 } } ``` ### Registros DNS do domínio `GET /api/v1/domains/{id}/dns` Listar os registros DNS do domínio (via 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 } ] } } ``` ### Adicionar registro DNS `POST /api/v1/domains/{id}/dns` Criar um novo registro DNS. **Request body** | Field | Type | Description | | --- | --- | --- | | `type` * | string | Tipo de registro: `A`, `AAAA`, `CNAME`, `MX`, `TXT`, etc. | | `name` * | string | Nome do registro, ex.: `@` ou `subdomain`. | | `content` * | string | Valor do registro. | | `ttl` | integer | TTL em segundos (`1` = automático). | | `proxied` | boolean | Fazer proxy pelo 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 } } } ``` ### Atualizar registro DNS `PUT /api/v1/domains/{id}/dns/{recordId}` Atualizar um registro DNS existente por ID. Apenas os campos enviados são sobrescritos. **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" }' ``` ### Excluir registro DNS `DELETE /api/v1/domains/{id}/dns/{recordId}` Excluir um registro DNS por ID. **curl** ```bash curl -X DELETE https://app.piv.day/api/v1/domains/dom-uuid-.../dns/rec-uuid-... \ -H "Authorization: Bearer YOUR_API_KEY" ``` ### Ativar Cloudflare `POST /api/v1/domains/{id}/cloudflare` Ativar Cloudflare para o domínio. Não retornamos os nameservers do Cloudflare — a delegação é configurada do nosso lado. Desativar Cloudflare via este endpoint não é suportado. **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" } } ``` ### Definir nameservers `POST /api/v1/domains/{id}/ns-servers` Definir nameservers personalizados para o domínio. **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 } ] } } ``` ## Whites Geração de white-pages por nicho e tier. Cada site é único. Troque domínio e contatos sem regenerar. ### Listar tiers `GET /api/v1/whites/tiers` Tiers de geração disponíveis com preços. `price` é o preço por geração já ajustado à sua conta (assinatura aplicada), um único número. `quality: "premium"` custa mais (calculado no momento da criação). Blog apenas no `v2_tier3`: os primeiros 3 artigos estão incluídos; cada artigo extra (até 20) é cobrado a `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 } ] } } ``` ### Listar whites `GET /api/v1/whites` Lista dos seus jobs de geração com filtragem. **Query parameters** | Field | Type | Description | | --- | --- | --- | | `limit` | integer | Tamanho da página. Padrão 100, máximo 500. | | `offset` | integer | Offset de paginação. | | `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 } } } ``` ### Iniciar geração `POST /api/v1/whites` Coloque um job de geração de white-page na fila. O pagamento é cobrado imediatamente. O status final chega via webhook `white.completed` / `white.failed` ou pode ser consultado via `GET /whites/{id}`. **Request body** | Field | Type | Description | | --- | --- | --- | | `name` * | string | Nome do job (2–20 caracteres). | | `tier_key` * | string | `v2_tier1` \| `v2_tier2` \| `v2_tier3`. | | `niche` * | string | Nicho do site (até 25 caracteres). | | `country` * | string | Código do país (ISO 3166-1 alpha-2). | | `language` * | string | Idioma principal do site (ISO 639-1). | | `quality` | string | `standard` \| `premium` (padrão `standard`). | | `languages` | string[] | Lista de idiomas. O primeiro está incluído no preço; cada idioma extra tem custo adicional. | | `domain` | string | Domínio completo (ex.: `example.com`). Sem autocompletar. | | `email` | string | Email completo (ex.: `info@example.com`). Sem autocompletar. | | `phone` | string | Telefone de contato. | | `address` | string | Endereço da empresa. | | `legal_name` | string | Nome jurídico. | | `style_hint` | string | Estilo de design (Random, Minimalista, Corporativo, etc.). | | `keywords` | string[] | Palavras-chave SEO. | | `banned_words` | string[] | Palavras proibidas no conteúdo. | | `blog_count` | integer | Quantidade de artigos do blog 3–20. Apenas para `v2_tier3`. Artigos além de 3 têm custo extra. | | `contacts_mode` | string | `same` \| `template`. | | `contacts_template` | string | Template da página de contato (quando `contacts_mode=template`). | | `facebook` | string | URL completa da página do Facebook. | | `instagram` | string | URL completa do perfil do Instagram. | | `linkedin` | string | URL completa do perfil do LinkedIn. | | `youtube` | string | URL completa do canal do YouTube. | | `tiktok` | string | URL completa do perfil do TikTok. | **Errors** | Code | HTTP | When it fires | | --- | --- | --- | | `INSUFFICIENT_BALANCE` | 402 | Saldo insuficiente. | | `INVALID_TIER` | 400 | Nenhum tier encontrado com essa chave. | | `VALIDATION_ERROR` | 400 | Corpo da requisição inválido. | **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" } } } ``` ### Obter um white `GET /api/v1/whites/{id}` Obter o estado atual de um job de geração. **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" } } } ``` ### Baixar arquivo `GET /api/v1/whites/{id}/download` Obtenha um link assinado de curta duração para o arquivo final da white-page. O link é válido por ~5 minutos (veja `expires_at`). Se expirou, basta chamar `/download` novamente — emitiremos um novo. Se a white-page ainda não foi gerada, retorna `409 NOT_READY`. **Query parameters** | Field | Type | Description | | --- | --- | --- | | `format` | string | Formato do arquivo. Padrão `php`. | **Errors** | Code | HTTP | When it fires | | --- | --- | --- | | `NOT_READY` | 409 | A white-page ainda está sendo gerada — tente novamente após `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" } } ``` ### Trocar domínio e contatos `POST /api/v1/whites/{id}/config` Atualize os dados de contato da empresa na white-page sem regenerá-la. **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 Enviamos um POST simples com corpo JSON para sua URL. O formato é o mesmo para todos os eventos: `event_type`, `timestamp` e um bloco `data`. Seu servidor deve responder com qualquer 2xx em 5 segundos. ``` POST Content-Type: application/json User-Agent: piv.day-webhook/1.0 { "event_type": "", "timestamp": "2026-05-22T12:34:56Z", "data": { ... } } ``` **Retries.** Em caso de não-2xx ou timeout — até 3 tentativas com espera de 1s / 2s / 4s. O histórico completo de entregas fica na página de chaves API no dashboard. Se todas as três falharem, o evento é marcado como failed e pode ser reenviado manualmente. **Security.** Use um endpoint HTTPS. Cada requisição chega com o cabeçalho `User-Agent: piv.day-webhook/1.0`. A URL do webhook é configurada no perfil da chave API. ### All events | Event | When it fires | | --- | --- | | `sms.received` | Um remetente confiável acabou de enviar uma mensagem para um dos seus números. | | `sms.status_updated` | Um SMS de saída mudou de estado — entregue, falhou, etc. | | `number.restore_completed` | Um Restore em lote foi concluído — o resumo final chega aqui. | | `verify.completed` | A verificação da conta Google foi concluída com sucesso. | | `verify.failed` | Algo deu errado — o Google não aceitou. | | `proxy.expires_soon` | Restam cerca de três dias no pedido de proxy. | | `domain.registered` | O pedido de registro foi concluído com sucesso — o domínio está ativo. | | `domain.failed` | O pedido não foi concluído — causa comum: o nome acabou de ser registrado. | | `domain.expires_soon` | Falta cerca de uma semana para o domínio expirar. | | `white.completed` | A tarefa de geração do White foi concluída com sucesso. | | `white.failed` | A tarefa falhou — os fundos são reembolsados ao saldo. | ### SMS recebido no seu número **`sms.received`** Na maioria das vezes são códigos de verificação de redes de publicidade. O payload inclui o texto bruto e um código detectado automaticamente (quando presente) para que você possa passá-lo diretamente para seu fluxo de trabalho sem parsing. Mensagens de remetentes de spam conhecidos não são encaminhadas. ```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 do SMS enviado mudou **`sms.status_updated`** Útil quando você envia confirmações do seu próprio número e precisa saber se realmente chegaram. Se o status for failed, o código de erro e a mensagem da operadora estão no payload. ```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 } } ``` ### Restauração de números concluída **`number.restore_completed`** Contém duas listas — quais números voltaram e quais não. O valor reembolsado pelos que falharam também está no payload. Prático para scripts que tentam novamente de forma inteligente. ```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 } } ``` ### Verificação Google QR bem-sucedida **`verify.completed`** Se um SMS com código chegou durante o processo, já está aqui — não é necessária uma busca extra. captured_phone e captured_message contêm o que o Google enviou. ```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" } } ``` ### Verificação Google QR falhou **`verify.failed`** error_code informa o que especificamente — timeout, rejeição, URL inválida. Verificações com falha são reembolsadas ao saldo automaticamente. ```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 expirando em breve **`proxy.expires_soon`** Ideal para quem não renova automaticamente: você vê com antecedência e decide — estender ou encerrar a campanha. Conecte ao POST /proxy/orders/{id}/renew para renovação totalmente automática. ```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" } } ``` ### Domínio registrado **`domain.registered`** Se você solicitou Cloudflare e SSL na compra, ambos já estão ativos — cloudflare_enabled reflete o status. Você pode adicionar registros DNS ou implantar o site imediatamente. ```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 } } ``` ### Registro de domínio falhou **`domain.failed`** O campo error tem uma razão legível por humanos. O custo é reembolsado ao saldo. Escolha outro nome e tente novamente. ```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" } } ``` ### Domínio expirando em breve **`domain.expires_soon`** Útil quando a renovação automática está desativada: você tem tempo para renovar manualmente antes que o domínio entre em redenção. O sinalizador auto_renew indica se é necessária intervenção. ```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 gerado **`white.completed`** O arquivo está disponível via GET /whites/{id}/download. Se o White tinha um domínio configurado, o sitemap e contatos já estão vinculados a ele — pronto para deploy. ```json { "event_type": "white.completed", "timestamp": "2026-05-22T12:34:56Z", "data": { "job_id": "job-uuid-...", "name": "My White", "tier_key": "t1", "country": "DE" } } ``` ### Geração do White falhou **`white.failed`** O campo error explica o motivo. Inicie um novo trabalho via POST /whites — sem perda de dinheiro. ```json { "event_type": "white.failed", "timestamp": "2026-05-22T12:34:56Z", "data": { "job_id": "job-uuid-...", "name": "My White", "error": "Generation failed" } } ``` ## Error codes Todos os erros seguem o mesmo formato: status HTTP + campo `error.code` + mensagem legível em `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 | Chave ausente, expirada ou revogada. | | `INSUFFICIENT_PERMISSIONS` | 403 | A chave não possui o scope necessário para esta ação. | | `PERMISSION_DENIED` | 403 | O acesso no nível da conta não permite esta ação (ex.: funcionalidade desativada). | | `VALIDATION_ERROR` | 400 | Corpo da requisição inválido. A mensagem explica qual campo falhou e por quê. | | `NUMBER_NOT_FOUND` | 404 | O número não existe ou não pertence à conta. | | `NUMBER_EXPIRED` | 403 | O número expirou — use Restore (dentro de 7 dias) ou compre um novo. | | `NUMBER_NOT_ACTIVE` | 400 | O número está em um estado que não permite esta operação. | | `INSUFFICIENT_BALANCE` | 402 | Saldo insuficiente para esta operação. | | `INVALID_MESSAGE_FORMAT` | 400 | O corpo do SMS é muito longo ou contém caracteres não permitidos. | | `COUNTRY_NOT_AVAILABLE` | 400 | O país não está disponível para compra ou renovação. | | `NO_NUMBERS_AVAILABLE` | 400 | Não há números disponíveis no país escolhido no momento. | | `NO_RESTORABLE_NUMBERS` | 404 | Nenhum dos números fornecidos pode ser restaurado. | | `RATE_LIMITED` | 429 | Rate limit excedido. Aguarde o tempo indicado no cabeçalho `Retry-After`. | | `INTERNAL_ERROR` | 500 | Algo deu errado do nosso lado. Se persistir, entre em contato com o suporte. |