Documentación

Primeros pasos

REST API en el plan Business. Tokens Bearer, JSON, endpoints idempotentes, códigos de error predecibles. Cada endpoint incluye un ejemplo de solicitud y respuesta.

Base URL

https://app.piv.day/api/v1

Todos los endpoints se encuentran bajo este prefijo. Un solo entorno — no hay hosts de staging separados.

Autenticación

Authorization: Bearer YOUR_API_KEY

Las claves se crean en el dashboard en Configuración → API Keys. Cada clave tiene permisos granulares (leer números, enviar SMS, comprar proxies, etc.). Un token comprometido se rota con un clic — sin necesidad de volver a registrar al equipo.

Cuenta

GET/api/v1/account
curl https://app.piv.day/api/v1/account \
  -H "Authorization: Bearer YOUR_API_KEY"
Un endpoint utilitario único — balance y email de la cuenta actual. Útil para confirmar que la clave funciona y la autenticación está configurada correctamente.
{
  "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 respuesta

{
  "success": true,
  "data": { ... }
}

Todas las respuestas son JSON. En caso de error, success es false y el cuerpo contiene error.code y error.message.

Rate limits

100 solicitudes por minuto por API key. El límite es compartido entre todos los endpoints. ¿Necesita más margen para un pico de tráfico? Contacte al soporte de Telegram y aumentaremos el límite. Al superar el límite recibirá `429 RATE_LIMITED` y el encabezado `Retry-After` — cuántos segundos esperar antes de la próxima solicitud.
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

Documentación

Números

Compra, renueva y restaura números. Recibe y envía SMS. Inicia verificaciones Google QR. Suscríbete a eventos mediante webhooks.

Países y precios

GET/api/v1/numbers/countries

Devuelve los países disponibles para compra con el precio actual y capacidades SMS. Todos los precios incluyen el descuento de tu suscripción.

Campos de respuesta

CampoTipoDescripción
country_codestringCódigo de país ISO de dos letras (p. ej. SE).
price_per_monthnumberPrecio final para tu plan — lo que se cobra realmente al comprar. Los descuentos de Premium / Business ya están aplicados.
base_pricenumberPrecio sin descuentos (plan Free). Se devuelve para comparación, para ver cuánto ahorra la suscripción.
can_send_smsbooleanSi el envío de SMS salientes es compatible desde este número.
can_receive_smsbooleanSi los SMS entrantes son compatibles.
sms_send_pricenumber|nullPrecio por SMS saliente, también con el descuento del plan aplicado. null cuando el envío no es compatible desde este país.
GET/api/v1/numbers/countries
curl https://app.piv.day/api/v1/numbers/countries \
  -H "Authorization: Bearer YOUR_API_KEY"
200OK
{
  "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

Devuelve una página de números de cuenta con filtros por país, estado y búsqueda por número o nombre personalizado.

Parámetros de consulta

CampoTipoDescripción
limitintegerTamaño de página (predeterminado 50, máximo 200).
offsetintegerDesplazamiento de paginación.
countrystringFiltro de código de país ISO.
statusstringUno de active, expired, pending_restore.
searchstringBúsqueda de subcadena por número de teléfono o nombre personalizado.
GET/api/v1/numbers
curl "https://app.piv.day/api/v1/numbers?country=SE&status=active&limit=10" \
  -H "Authorization: Bearer YOUR_API_KEY"
200OK
{
  "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 }
  }
}

Obtener un número por ID

GET/api/v1/numbers/{piv_num_id}

Registro completo del número: estado, fechas, renovación automática, etiquetas, direcciones SMS permitidas.

Errores

CódigoHTTPCuándo se activa
NUMBER_NOT_FOUND404El número no existe o no pertenece a la cuenta.
GET/api/v1/numbers/vzPA1-kHKSg-EAL7e-Jqd3o
curl https://app.piv.day/api/v1/numbers/vzPA1-kHKSg-EAL7e-Jqd3o \
  -H "Authorization: Bearer YOUR_API_KEY"
200OK
{
  "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 un número

POST/api/v1/numbers/purchase

Compra un número en el país seleccionado por el período indicado. El costo se debita del saldo de la cuenta. Devuelve piv_num_id que se utiliza en todas las operaciones posteriores del número.

Cuerpo de la solicitud

CampoTipoDescripción
country_code*stringCódigo de país ISO.
duration_months*integerPeríodo de alquiler en meses (mínimo 1).
auto_renew*booleanActivar la renovación automática justo después de la compra.
custom_namestringNombre opcional legible para el número.

Errores

CódigoHTTPCuándo se activa
COUNTRY_NOT_AVAILABLE400El país no está disponible o no tiene precios.
NO_NUMBERS_AVAILABLE400No hay números disponibles en el país solicitado en este momento.
INSUFFICIENT_BALANCE402Fondos insuficientes en el saldo.
VALIDATION_ERROR400Campos inválidos en el cuerpo de la solicitud.
POST/api/v1/numbers/purchase
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"
  }'
200OK
{
  "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 un número

POST/api/v1/numbers/{piv_num_id}/renew

Extiende un número activo por el período indicado. El costo se debita en el momento de la llamada.

Cuerpo de la solicitud

CampoTipoDescripción
duration_months*integerNúmero de meses a agregar.

Errores

CódigoHTTPCuándo se activa
NUMBER_NOT_FOUND404El número no existe o no pertenece a la cuenta.
COUNTRY_NOT_AVAILABLE400No se encontraron precios para el país del número.
INSUFFICIENT_BALANCE402Fondos insuficientes para renovar.
POST/api/v1/numbers/vzPA1-kHKSg-EAL7e-Jqd3o/renew
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 }'
200OK
{
  "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
  }
}

Actualizar un número

PATCH/api/v1/numbers/{piv_num_id}

Actualmente solo se puede actualizar el nombre personalizado.

Cuerpo de la solicitud

CampoTipoDescripción
custom_name*stringNuevo nombre para el número.

Errores

CódigoHTTPCuándo se activa
NUMBER_NOT_FOUND404El número no existe o no pertenece a la cuenta.
VALIDATION_ERROR400Valor inválido en el cuerpo de la solicitud.
PATCH/api/v1/numbers/vzPA1-kHKSg-EAL7e-Jqd3o
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" }'
200OK
{
  "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": []
  }
}

Gestión de renovación automática

PATCH/api/v1/numbers/{piv_num_id}/auto-renewal

Activa o desactiva la renovación automática del número. Cuando está habilitada, la renovación se debita automáticamente 24 horas antes del vencimiento. Si el saldo es insuficiente, el número expira; puedes reclamarlo mediante POST /numbers/restore dentro de 7 días.

Cuerpo de la solicitud

CampoTipoDescripción
auto_renew*booleanNuevo valor del indicador de renovación automática.
PATCH/api/v1/numbers/vzPA1-kHKSg-EAL7e-Jqd3o/auto-renewal
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 }'
200OK
{
  "success": true,
  "data": {
    "piv_num_id": "vzPA1-kHKSg-EAL7e-Jqd3o",
    "phone_number": "+46764794425",
    "auto_renew": true
  }
}

Restaurar números vencidos

POST/api/v1/numbers/restore

Recupera números vencidos dentro de un período de 7 días. Pasa un array de piv_num_id — los números regresan con el historial SMS y la configuración conservados. La restauración cuesta más que comprar un número nuevo (incluye un multiplicador de restauración) — las cifras exactas se muestran en el dashboard antes de confirmar. El estado final de cada número llega mediante el webhook number.restore_completed; los reembolsos por números fallidos se acreditan automáticamente.

Cuerpo de la solicitud

CampoTipoDescripción
piv_num_ids*string[]Array de IDs de números a restaurar.

Errores

CódigoHTTPCuándo se activa
NO_RESTORABLE_NUMBERS404Ninguno de los números proporcionados puede restaurarse (el período de 7 días venció o no son tuyos).
INSUFFICIENT_BALANCE402Fondos insuficientes para cubrir la restauración.
POST/api/v1/numbers/restore
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"
    ]
  }'
200OK
{
  "success": true,
  "queued": 2,
  "skipped": 0,
  "total_charged": 9.00,
  "numbers": [
    {
      "piv_num_id": "vzPA1-kHKSg-EAL7e-Jqd3o",
      "phone_number": "+46764794425",
      "status": "pending"
    }
  ]
}

Historial SMS del número

GET/api/v1/numbers/{piv_num_id}/sms

Devuelve los mensajes entrantes y salientes del número en orden cronológico inverso.

Parámetros de consulta

CampoTipoDescripción
limitintegerCuántos mensajes devolver (predeterminado 50, máximo 200).
offsetintegerDesplazamiento de paginación.
GET/api/v1/numbers/vzPA1-kHKSg-EAL7e-Jqd3o/sms
curl "https://app.piv.day/api/v1/numbers/vzPA1-kHKSg-EAL7e-Jqd3o/sms?limit=20" \
  -H "Authorization: Bearer YOUR_API_KEY"
200OK
{
  "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

Disponible para países donde el envío saliente está permitido (p. ej. CA, GB, SE). El costo del mensaje se debita en el momento del envío.

Cuerpo de la solicitud

CampoTipoDescripción
to_number*stringNúmero del destinatario en formato internacional (E.164).
message_body*stringTexto del mensaje. Se admiten GSM-7 y UCS-2.

Errores

CódigoHTTPCuándo se activa
NUMBER_NOT_FOUND404El número no existe o no pertenece a la cuenta.
NUMBER_EXPIRED403El número ya ha vencido.
NUMBER_NOT_ACTIVE400El número está en un estado que no permite el envío.
INSUFFICIENT_BALANCE402Fondos insuficientes para enviar.
INVALID_MESSAGE_FORMAT400El cuerpo del mensaje supera la longitud permitida o contiene caracteres prohibidos.
POST/api/v1/numbers/vzPA1-kHKSg-EAL7e-Jqd3o/sms/send
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"
  }'
200OK
{
  "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 verificación Google QR

POST/api/v1/numbers/{piv_num_id}/verify

Inicia una verificación Google QR usando la URL proporcionada. El resultado — éxito o fallo — llega mediante el webhook verify.completed o verify.failed. El costo se debita cuando la tarea se pone en cola.

Cuerpo de la solicitud

CampoTipoDescripción
gv_url*stringURL completa de verificación de Google (obtenida de la página de Google).

Errores

CódigoHTTPCuándo se activa
NUMBER_NOT_FOUND404El número no existe o no es tuyo.
NUMBER_NOT_ACTIVE400El número no está activo.
SMS_DISABLED400El envío de SMS está desactivado para este número.
INSUFFICIENT_BALANCE402Fondos insuficientes para la verificación.
PROXY_DEAD502Proxy no disponible — saldo reembolsado.
QUEUE_FULL503La cola está llena, inténtelo más tarde — saldo reembolsado.
SERVER_UNAVAILABLE503Servidor de automatización no disponible — saldo reembolsado.
POST/api/v1/numbers/vzPA1-kHKSg-EAL7e-Jqd3o/verify
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/..." }'
202Accepted
{
  "success": true,
  "message": "Verification initiated"
}
Documentación

Proxy

IPv6 residencial en docenas de países. Compra masiva, renovación, Restore que mantiene el mismo login y contraseña, exportación en el formato que necesitas.

Lista de servidores

GET/api/v1/proxy/servers

Servidores proxy disponibles con precios.

GET/api/v1/proxy/servers
curl https://app.piv.day/api/v1/proxy/servers \
  -H "Authorization: Bearer YOUR_API_KEY"
200OK
{
  "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 de tus pedidos de proxy con filtros por estado o búsqueda.

Parámetros de consulta

CampoTipoDescripción
limitintegerTamaño de página. Por defecto 100, máximo 500.
offsetintegerDesplazamiento de paginación.
statusstringFiltro por estado: active, expired.
searchstringBúsqueda en pedidos.
GET/api/v1/proxy/orders
curl "https://app.piv.day/api/v1/proxy/orders?status=active&limit=20" \
  -H "Authorization: Bearer YOUR_API_KEY"
200OK
{
  "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 }
  }
}

Obtener un pedido

GET/api/v1/proxy/orders/{id}

Obtener los detalles de un pedido específico, incluida la lista de credenciales de proxy.

GET/api/v1/proxy/orders/ord-uuid-...
curl https://app.piv.day/api/v1/proxy/orders/ord-uuid-... \
  -H "Authorization: Bearer YOUR_API_KEY"
200OK
{
  "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 en el servidor elegido. Una solicitud crea un pedido con N proxies (hasta 500). No existen pedidos masivos: llama al método nuevamente si necesitas más.

Cuerpo de la solicitud

CampoTipoDescripción
server_id*stringID del servidor de GET /proxy/servers.
quantity*integerCuántos proxies comprar (1–500).
months*integerPeríodo de arrendamiento en meses (1–12).

Errores

CódigoHTTPCuándo se activa
INSUFFICIENT_BALANCE402Fondos insuficientes.
NOT_FOUND404Servidor proxy no encontrado o inactivo.
VALIDATION_ERROR400Cuerpo de solicitud inválido.
POST/api/v1/proxy/purchase
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
  }'
200OK
{
  "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 un pedido

POST/api/v1/proxy/orders/{id}/renew

Extender un pedido de proxy activo por un número de meses.

Cuerpo de la solicitud

CampoTipoDescripción
months*integerMeses a añadir.
POST/api/v1/proxy/orders/ord-uuid-.../renew
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 }'
200OK
{
  "success": true,
  "data": {
    "order_id": "ord-uuid-...",
    "cost": 5.00,
    "new_expires_at": "2026-03-01T00:00:00Z"
  }
}

Restore de orden vencida

POST/api/v1/proxy/orders/{id}/restore

Recupera una orden de proxy vencida sin recomprarla. Login, contraseña, direcciones IPv6, país y vínculos — todo igual. El plazo se extiende 1 mes. No es necesario reconfigurar el antidetect.

POST/api/v1/proxy/orders/ord-uuid-.../restore
curl -X POST https://app.piv.day/api/v1/proxy/orders/ord-uuid-.../restore \
  -H "Authorization: Bearer YOUR_API_KEY"
200OK
{
  "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 las credenciales de proxy del pedido como una lista de texto (login:password@host:port).

Parámetros de consulta

CampoTipoDescripción
formatstringFormato de exportación: socks5, http o both (por defecto socks5).
GET/api/v1/proxy/orders/ord-uuid-.../export
curl "https://app.piv.day/api/v1/proxy/orders/ord-uuid-.../export?format=socks5" \
  -H "Authorization: Bearer YOUR_API_KEY"
200OK
{
  "success": true,
  "data": {
    "content": "user1:[email protected]:1080\nuser2:[email protected]:1080",
    "filename": "piv-day-proxy-ord-uuid--socks5.txt",
    "format": "socks5",
    "count": 2
  }
}
Documentación

Dominios

Búsqueda y registro sin KYC, Cloudflare y SSL automáticos, gestión de registros DNS y servidores NS a través de la API.

Listar dominios

GET/api/v1/domains

Lista de sus dominios registrados con posibilidad de filtrado.

Parámetros de consulta

CampoTipoDescripción
limitintegerTamaño de página. Por defecto 100, máximo 500.
offsetintegerDesplazamiento para paginación.
statusstringEstado del dominio: active, pending, expired.
cloudflarestringFiltrar por estado de Cloudflare: true o false.
auto_renewstringFiltrar por renovación automática: true o false.
searchstringBuscar por nombre de dominio.
GET/api/v1/domains
curl "https://app.piv.day/api/v1/domains?status=active&limit=20" \
  -H "Authorization: Bearer YOUR_API_KEY"
200OK
{
  "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 un dominio

POST/api/v1/domains

Registrar un nuevo dominio. La solicitud es asíncrona — devuelve queue_id para seguimiento. Cloudflare ACTIVADO: no pasar nameservers; opcionalmente puede pasar dns_records y ssl_mode. Cloudflare DESACTIVADO: no pasar dns_records ni ssl_mode; nameservers es obligatorio (mínimo 2). Nunca exponemos los nameservers de Cloudflare.

Cuerpo de la solicitud

CampoTipoDescripción
domain*stringNombre de dominio a registrar, p. ej. mysite.com.
period*integerPeríodo de registro en años (1–10).
cloudflare*booleanConectar el dominio a Cloudflare automáticamente.
auto_renew*booleanHabilitar renovación automática.
ssl_modestringflexible | full | strict. Solo con cloudflare: true.
nameserversstring[]Obligatorio con cloudflare: false (≥2 NS). Prohibido con cloudflare: true.
dns_recordsobject[]Registros DNS iniciales. Solo con cloudflare: true.

Errores

CódigoHTTPCuándo se activa
DOMAIN_NOT_AVAILABLE400El dominio no está disponible para registro.
INSUFFICIENT_BALANCE402Fondos insuficientes.
VALIDATION_ERROR400Cuerpo de la solicitud no válido.
POST/api/v1/domains
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 }
    ]
  }'
POST/api/v1/domains
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"]
  }'
202Accepted
{
  "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"
    }
  }
}

Estado de la tarea de registro

GET/api/v1/domains/queue/{id}

Verificar el estado de una entrada en la cola de registro o renovación de dominio. Con el estado completed, la respuesta ya contiene la ficha completa del dominio — no es necesaria una llamada separada a /domains/{id}.

GET/api/v1/domains/queue/que-uuid-...
curl https://app.piv.day/api/v1/domains/queue/que-uuid-... \
  -H "Authorization: Bearer YOUR_API_KEY"
pending / processing
{
  "success": true,
  "data": {
    "queue_id": "que-uuid-...",
    "domain": "mysite.com",
    "status": "pending"
  }
}
completed — ficha completa
{
  "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 }
      ]
    }
  }
}

Obtener un dominio

GET/api/v1/domains/{id}

Obtener información completa sobre un dominio registrado. El campo nameservers solo está presente cuando cloudflare_enabled: false.

GET/api/v1/domains/dom-uuid-...
curl https://app.piv.day/api/v1/domains/dom-uuid-... \
  -H "Authorization: Bearer YOUR_API_KEY"
200OK
{
  "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 dominio

POST/api/v1/domains/{id}/renew

Renovar el registro del dominio. Devuelve queue_id para seguimiento.

Cuerpo de la solicitud

CampoTipoDescripción
period*integerAños a agregar.
POST/api/v1/domains/dom-uuid-.../renew
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 }'
202Accepted
{
  "success": true,
  "data": {
    "queue_id": "que-uuid-...",
    "domain_id": "dom-uuid-...",
    "expires_at": "2027-01-01T12:00:00Z"
  }
}

Toggle de renovación automática

POST/api/v1/domains/{id}/auto-renew

Activar o desactivar la renovación automática del dominio.

Cuerpo de la solicitud

CampoTipoDescripción
auto_renew*booleanNuevo valor del indicador.
POST/api/v1/domains/dom-uuid-.../auto-renew
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 }'
200OK
{
  "success": true,
  "data": {
    "id": "dom-uuid-...",
    "auto_renew": true
  }
}

Registros DNS del dominio

GET/api/v1/domains/{id}/dns

Listar los registros DNS del dominio (a través de Cloudflare).

GET/api/v1/domains/dom-uuid-.../dns
curl https://app.piv.day/api/v1/domains/dom-uuid-.../dns \
  -H "Authorization: Bearer YOUR_API_KEY"
200OK
{
  "success": true,
  "data": {
    "records": [
      {
        "id": "rec-uuid-...",
        "type": "A",
        "name": "@",
        "content": "1.2.3.4",
        "ttl": 1,
        "priority": null,
        "proxied": true
      }
    ]
  }
}

Agregar registro DNS

POST/api/v1/domains/{id}/dns

Crear un nuevo registro DNS.

Cuerpo de la solicitud

CampoTipoDescripción
type*stringTipo de registro: A, AAAA, CNAME, MX, TXT, etc.
name*stringNombre del registro, p. ej. @ o subdomain.
content*stringValor del registro.
ttlintegerTTL en segundos (1 = automático).
proxiedbooleanRedirigir a través de Cloudflare.
POST/api/v1/domains/dom-uuid-.../dns
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
  }'
201Created
{
  "success": true,
  "data": {
    "record": {
      "id": "rec-uuid-...",
      "type": "A",
      "name": "@",
      "content": "1.2.3.4",
      "ttl": 1,
      "priority": null,
      "proxied": true
    }
  }
}

Actualizar registro DNS

PUT/api/v1/domains/{id}/dns/{recordId}

Actualizar un registro DNS existente por ID. Solo se sobreescriben los campos enviados.

PUT/api/v1/domains/dom-uuid-.../dns/rec-uuid-...
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" }'

Eliminar registro DNS

DELETE/api/v1/domains/{id}/dns/{recordId}

Eliminar un registro DNS por ID.

DELETE/api/v1/domains/dom-uuid-.../dns/rec-uuid-...
curl -X DELETE https://app.piv.day/api/v1/domains/dom-uuid-.../dns/rec-uuid-... \
  -H "Authorization: Bearer YOUR_API_KEY"

Habilitar Cloudflare

POST/api/v1/domains/{id}/cloudflare

Activar Cloudflare para el dominio. No devolvemos los nameservers de Cloudflare — la delegación se configura de nuestra parte. No se admite la desactivación de Cloudflare mediante este endpoint.

POST/api/v1/domains/dom-uuid-.../cloudflare
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 }'
200OK
{
  "success": true,
  "data": {
    "domain_id": "dom-uuid-...",
    "ssl_mode": "flexible"
  }
}

Configurar nameservers

POST/api/v1/domains/{id}/ns-servers

Configurar nameservers personalizados para el dominio.

POST/api/v1/domains/dom-uuid-.../ns-servers
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"] }'
200OK
{
  "success": true,
  "data": {
    "nameservers": [
      { "nameserver": "ns1.example.com", "order_index": 1 },
      { "nameserver": "ns2.example.com", "order_index": 2 }
    ]
  }
}
Documentación

Whites

Generación de white-pages por nicho y tier. Cada sitio es único. Cambia dominio y contactos sin regenerar.

Listar tiers

GET/api/v1/whites/tiers

Tiers de generación disponibles con precios. price es el precio por generación ya ajustado a tu cuenta (suscripción aplicada), un único número. quality: "premium" cuesta más (se calcula al crear). Blog solo en v2_tier3: los primeros 3 artículos están incluidos; cada artículo adicional (hasta 20) se cobra a extra_article_price.

GET/api/v1/whites/tiers
curl https://app.piv.day/api/v1/whites/tiers \
  -H "Authorization: Bearer YOUR_API_KEY"
200OK
{
  "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 de tus trabajos de generación con filtrado.

Parámetros de consulta

CampoTipoDescripción
limitintegerTamaño de página. Por defecto 100, máximo 500.
offsetintegerDesplazamiento de paginación.
statusstringqueued | processing | done | failed.
tier_keystringv2_tier1 | v2_tier2 | v2_tier3.
GET/api/v1/whites
curl "https://app.piv.day/api/v1/whites?status=done&limit=20" \
  -H "Authorization: Bearer YOUR_API_KEY"
200OK
{
  "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 generación

POST/api/v1/whites

Encola un job de generación de white-page. El pago se cobra de inmediato. El estado final llega vía el webhook white.completed / white.failed o puede consultarse mediante GET /whites/{id}.

Cuerpo de la solicitud

CampoTipoDescripción
name*stringNombre del trabajo (2–20 caracteres).
tier_key*stringv2_tier1 | v2_tier2 | v2_tier3.
niche*stringNicho del sitio (hasta 25 caracteres).
country*stringCódigo de país (ISO 3166-1 alpha-2).
language*stringIdioma principal del sitio (ISO 639-1).
qualitystringstandard | premium (por defecto standard).
languagesstring[]Lista de idiomas. El primero está incluido en el precio; cada idioma adicional tiene un costo extra.
domainstringDominio completo (p. ej. example.com). Sin autocompletado.
emailstringEmail completo (p. ej. [email protected]). Sin autocompletado.
phonestringTeléfono de contacto.
addressstringDirección de la empresa.
legal_namestringNombre legal.
style_hintstringEstilo de diseño (Random, Minimal, Corporativo, etc.).
keywordsstring[]Palabras clave SEO.
banned_wordsstring[]Palabras prohibidas en el contenido.
blog_countintegerCantidad de artículos del blog 3–20. Solo para v2_tier3. Los artículos que superen 3 tienen costo adicional.
contacts_modestringsame | template.
contacts_templatestringPlantilla de la página de contacto (cuando contacts_mode=template).
facebookstringURL completa de la página de Facebook.
instagramstringURL completa del perfil de Instagram.
linkedinstringURL completa del perfil de LinkedIn.
youtubestringURL completa del canal de YouTube.
tiktokstringURL completa del perfil de TikTok.

Errores

CódigoHTTPCuándo se activa
INSUFFICIENT_BALANCE402Fondos insuficientes.
INVALID_TIER400No se encontró ningún tier con esa clave.
VALIDATION_ERROR400Cuerpo de solicitud inválido.
POST/api/v1/whites
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": "[email protected]",
    "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"
  }'
200OK
{
  "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"
    }
  }
}

Obtener un white

GET/api/v1/whites/{id}

Obtener el estado actual de un trabajo de generación.

GET/api/v1/whites/job-uuid-...
curl https://app.piv.day/api/v1/whites/job-uuid-... \
  -H "Authorization: Bearer YOUR_API_KEY"
200OK
{
  "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"
    }
  }
}

Descargar archivo

GET/api/v1/whites/{id}/download

Obtén un enlace firmado de corta duración al archivo terminado de la white-page. El enlace es válido ~5 minutos (ver expires_at). Si expiró, llama a /download de nuevo — emitiremos uno nuevo. Si la white-page aún no está generada, devuelve 409 NOT_READY.

Parámetros de consulta

CampoTipoDescripción
formatstringFormato del archivo. Por defecto php.

Errores

CódigoHTTPCuándo se activa
NOT_READY409La white-page aún se está generando — reintenta después de white.completed.
GET/api/v1/whites/job-uuid-.../download
curl "https://app.piv.day/api/v1/whites/job-uuid-.../download?format=php" \
  -H "Authorization: Bearer YOUR_API_KEY"
200OK
{
  "success": true,
  "data": {
    "url": "https://strg.piv.day/download/<user_id>/<job_id>?format=php&token=<hmac>&filename=<name>.zip",
    "filename": "example.com_2026-05-28_DE_en.zip",
    "format": "php",
    "expires_at": "2026-05-28T14:46:00Z"
  }
}

Cambiar dominio y contactos

POST/api/v1/whites/{id}/config

Actualiza los datos de contacto de la empresa en la white-page sin regenerarla.

POST/api/v1/whites/job-uuid-.../config
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": "[email protected]",
    "phone": "+49 30 123456",
    "address": "Berliner Str. 1, Berlin",
    "legal": "My Brand GmbH"
  }'
Documentación

Webhooks

Suscríbete a los eventos de la plataforma: SMS entrantes, sitios listos, pedidos por vencer. La URL de notificaciones se configura en el perfil de la clave API.

Cómo llegan

Enviamos un POST simple con cuerpo JSON a tu URL. La estructura es la misma para todos los eventos: event_type, timestamp y un bloque data. Tu servidor debe responder con cualquier 2xx en 5 segundos.

Si falla la entrega

En caso de no-2xx o timeout — hasta 3 reintentos con espera de 1s / 2s / 4s. El historial completo de entregas está en la página de claves API en el dashboard. Si los tres fallan, el evento se marca como failed y puede reenviarse manualmente.

Seguridad

Usa un endpoint HTTPS. Cada solicitud llega con el encabezado User-Agent: piv.day-webhook/1.0. La URL del webhook se configura en el perfil de la clave API.

formato de solicitud
POST <your webhook URL>
Content-Type: application/json
User-Agent: piv.day-webhook/1.0

{
  "event_type": "<event identifier>",
  "timestamp": "2026-05-22T12:34:56Z",
  "data": { ... }
}

Todos los eventos

EventoCuándo se activa
sms.receivedUn remitente de confianza acaba de enviar un SMS a uno de tus números.
sms.status_updatedUn SMS saliente cambió de estado — entregado, fallido, etc.
number.restore_completedUn Restore por lotes finalizó — el resumen final llega aquí.
verify.completedLa verificación de la cuenta de Google finalizó correctamente.
verify.failedAlgo salió mal — Google no lo aceptó.
proxy.expires_soonQuedan aproximadamente tres días en el pedido de proxy.
domain.registeredEl pedido de registro finalizó correctamente — el dominio está activo.
domain.failedEl pedido no se completó — causa común: el nombre acaba de ser tomado.
domain.expires_soonQueda aproximadamente una semana antes de que venza el dominio.
white.completedLa tarea de generación del White finalizó correctamente.
white.failedLa tarea falló — los fondos se reembolsan al balance.

SMS entrante a tu número

sms.received

La mayoría de las veces son códigos de verificación de redes publicitarias. El payload incluye el texto sin procesar y un código detectado automáticamente (cuando está presente) para que puedas pasarlo directamente a tu flujo de trabajo sin parsear. Los mensajes de remitentes conocidos de spam no se reenvían.

payload
{
  "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"
  }
}

Estado del SMS enviado cambió

sms.status_updated

Útil cuando envías confirmaciones desde tu propio número y necesitas saber si realmente llegaron. Si el estado es failed, el código de error y el mensaje del operador están en el payload.

payload
{
  "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
  }
}

Restauración de números completada

number.restore_completed

Contiene dos listas: qué números volvieron y cuáles no. El monto reembolsado por los fallidos también está en el payload. Práctico para scripts que reintentan de forma inteligente.

payload
{
  "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
  }
}

Verificación Google QR exitosa

verify.completed

Si llegó un SMS con código durante el proceso, ya está aquí — no hace falta una solicitud adicional. captured_phone y captured_message contienen lo que envió Google.

payload
{
  "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"
  }
}

Verificación Google QR fallida

verify.failed

error_code indica qué ocurrió específicamente — timeout, rechazo, URL inválida. Las verificaciones fallidas se reembolsan al balance automáticamente.

payload
{
  "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 próximo a vencer

proxy.expires_soon

Diseñado para quienes no renuevan automáticamente: lo ves con anticipación y decides — extender o cerrar la campaña. Vincúlalo a POST /proxy/orders/{id}/renew para renovación totalmente automática.

payload
{
  "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"
  }
}

Dominio registrado

domain.registered

Si solicitaste Cloudflare y SSL al comprar, ambos ya están activos — cloudflare_enabled refleja el estado. Puedes agregar registros DNS o desplegar el sitio de inmediato.

payload
{
  "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 dominio fallido

domain.failed

El campo error tiene una razón legible por humanos. El costo se reembolsa al balance. Elige otro nombre e inténtalo de nuevo.

payload
{
  "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"
  }
}

Dominio próximo a vencer

domain.expires_soon

Útil cuando la renovación automática está desactivada: tienes tiempo de renovar manualmente antes de que el dominio entre en redención. El indicador auto_renew indica si es necesaria la intervención.

payload
{
  "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 generado

white.completed

El archivo está disponible vía GET /whites/{id}/download. Si el White tenía un dominio configurado, el sitemap y los contactos ya están vinculados — listo para desplegar.

payload
{
  "event_type": "white.completed",
  "timestamp": "2026-05-22T12:34:56Z",
  "data": {
    "job_id": "job-uuid-...",
    "name": "My White",
    "tier_key": "t1",
    "country": "DE"
  }
}

Generación de White fallida

white.failed

El campo error explica por qué. Inicia un nuevo trabajo vía POST /whites — sin pérdida de dinero.

payload
{
  "event_type": "white.failed",
  "timestamp": "2026-05-22T12:34:56Z",
  "data": {
    "job_id": "job-uuid-...",
    "name": "My White",
    "error": "Generation failed"
  }
}
Referencia

Códigos de error

Todos los errores siguen el mismo formato: estado HTTP + campo error.code + un mensaje legible en error.message.

CódigoHTTPCuándo se activa
UNAUTHORIZED401Clave ausente, vencida o revocada.
INSUFFICIENT_PERMISSIONS403La clave no tiene el scope requerido para esta acción.
PERMISSION_DENIED403El acceso a nivel de cuenta no permite esta acción (p. ej., función deshabilitada).
VALIDATION_ERROR400Cuerpo de la solicitud inválido. El mensaje explica qué campo falló y por qué.
NUMBER_NOT_FOUND404El número no existe o no pertenece a la cuenta.
NUMBER_EXPIRED403El número ha vencido — use Restore (dentro de los 7 días) o adquiera uno nuevo.
NUMBER_NOT_ACTIVE400El número se encuentra en un estado que no permite esta operación.
INSUFFICIENT_BALANCE402Fondos insuficientes para realizar esta operación.
INVALID_MESSAGE_FORMAT400El cuerpo del SMS es demasiado largo o contiene caracteres no permitidos.
COUNTRY_NOT_AVAILABLE400El país no está disponible para compra o renovación.
NO_NUMBERS_AVAILABLE400No hay números disponibles en el país seleccionado en este momento.
NO_RESTORABLE_NUMBERS404Ninguno de los números proporcionados puede ser restaurado.
RATE_LIMITED429Se superó el rate limit. Espere el tiempo indicado en el encabezado Retry-After.
INTERNAL_ERROR500Algo falló de nuestro lado. Si persiste, contacte al soporte.
Ejemplo de error
{
  "success": false,
  "error": {
    "code": "INSUFFICIENT_BALANCE",
    "message": "Not enough balance: required $5.00, available $1.20"
  }
}

¿Encontraste un error o necesitas un endpoint que no está aquí? El soporte responde en Telegram en menos de una hora en horario laboral.

Contactar soporte
piv.day Documentación del API — números, dominios, proxies, whites