Saltar al contenido
WbizTool

API v2 (beta)

Pasar de v1 a v2

La API v2 hace lo mismo que la v1, con claves más seguras, un solo estilo de URL, códigos de estado HTTP reales y webhooks JSON firmados. Esta página relaciona cada endpoint y campo de la v1 con su equivalente en la v2. Lo que es nuevo en la propia v2 está en el resumen.

Lo que cambia en todas partes#

  • Claves: el client_id + api_key de la v1 se convierten en una sola cabecera, Authorization: Bearer wbz_live_…. Crea una clave v2 en Configuración → Claves API, en la tarjeta Claves API v2, solo con los permisos que necesite la app. Las claves v1 no funcionan en la v2, y las claves v2 no funcionan en la v1.
  • Solo JSON: sin campos de formulario. Los archivos se suben a POST /media (multipart) y se envían con media_id.
  • Métodos y URL: GET para leer, POST para crear, PATCH para cambiar, DELETE para cancelar o eliminar, bajo https://wbiztool.com/api/v2.
  • Códigos de estado HTTP en lugar de "status": 0 o 1 (consulta Respuestas y errores).
  • Números de teléfono en formato internacional con +, sin country_code.
  • Horas en ISO 8601 con desfase, en lugar de campos separados de fecha, hora y zona horaria.
  • Webhooks: son endpoints que añades una sola vez para el espacio de trabajo, con eventos JSON firmados, en lugar de una URL webhook en cada mensaje.

Endpoint por endpoint#

Las rutas de v2 son relativas a https://wbiztool.com/api/v2.

Enviar, campo por campo#

v1v2Notas
client_id + api_key (cuerpo o Authorization: Bearer)Authorization: Bearer wbz_live_…Una clave v2 nueva; sin client_id
phone + country_codeto.phoneUn número en E.164 con +: "9876543210" con "country_code": "91" pasa a ser {"phone": "+919876543210"}. No se añade ningún código de país por ti
phone con un @username (Telegram)to.username@name, t.me/name o tg: y un id, desde una cuenta de Telegram
group_nameto.groupEl nombre exacto del grupo
(no existe en v1)to.contact_idUn contacto guardado
whatsapp_clientfromEl id del número; opcional cuando hay un solo número conectado, como antes
msg (o message)textHasta 3.000 caracteres, como antes
msg_type 0, 1, 2ningunoUn mensaje con media es un mensaje multimedia; media.type (image o file) cuando el enlace no lo indica
img_url / file_urlmedia.urlUn enlace público http(s)
file (subido en la misma solicitud)media.media_idSúbelo primero y luego envía el id tantas veces como quieras
file_namemedia.file_namePara archivos
date + time + timezone de schedule_msg/send_atUna sola hora con su desfase: 24/12/2026, 10:30 y Asia/Kolkata pasan a ser "2026-12-24T10:30:00+05:30"
expire_after_secondsexpires_atUna hora, no una duración: ahora más los segundos, con su desfase
webhookendpoints de webhookSe añaden una sola vez con POST /webhooks, para todos los mensajes del espacio de trabajo
msg_id en la respuestaidSe devuelve el propio Message, con su status

El mismo envío en v1 y en v2:

# v1
curl -X POST https://wbiztool.com/api/v1/send_msg/ \
  -H "Authorization: Bearer YOUR_V1_KEY" \
  -H "Content-Type: application/json" \
  -d '{"whatsapp_client": 101, "msg_type": 1, "country_code": "91", "phone": "9876543210",
       "img_url": "https://example.com/offers/diwali-sale.jpg", "msg": "Our Diwali sale starts today",
       "expire_after_seconds": 3600}'

# v2
curl -X POST https://wbiztool.com/api/v2/messages \
  -H "Authorization: Bearer $WBIZTOOL_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: diwali-9876543210" \
  -d '{"from": 101, "to": {"phone": "+919876543210"},
       "media": {"url": "https://example.com/offers/diwali-sale.jpg"}, "text": "Our Diwali sale starts today",
       "expires_at": "2026-10-20T11:30:00+05:30"}'

Algunos comportamientos de la v1 desaparecen a propósito:

  • No se adivinan códigos de país. La v1 ponía country_code delante de un número (con 91, siempre delante de uno de 10 dígitos). La v2 toma el número tal como está escrito, con +.
  • No se descarga el archivo al llamar. La v1 descargaba img_url y file_url durante la solicitud. La v2 comprueba que el enlace es público y descarga el archivo cuando se envía el mensaje; un enlace incorrecto aparece como un mensaje failed.
  • No se guarda una fila fallida al rechazar. Cuando la v1 rechaza un envío por superar los 1.000 diarios, igualmente guarda el mensaje como fallido. La v2 no guarda nada cuando rechaza un envío.
  • Los campos desconocidos se rechazan en lugar de ignorarse.

Estados#

Los números y palabras de la v1 se convierten en un solo campo status:

v1status de v2
0 Created / Pendingqueued, o scheduled mientras su send_at está por llegar
1 Sentsent, delivered o read (los tics de WhatsApp)
2 Failedfailed
3 Cancelledcancelled
4 Expiredexpired

Los eventos de webhook son message.sent, message.failed, message.cancelled y message.expired, que corresponden a SENT, FAILED, CANCELLED y EXPIRED de la v1.

Respuestas y errores#

La v1 responde a muchos errores con HTTP 200 o 400 y "status": 0, y a los éxitos con "status": 1. La v2 usa el código de estado HTTP:

  • Éxito es 200, 201 (creado) o 202 (en cola), y el cuerpo es el propio objeto, como el Message. No hay envoltorio status: 1.
  • Errores son 4xx o 5xx con una sola forma: {"error": {"code", "message", "field", "docs", "request_id"}}. Decide según code, no según el message en inglés. Todos los códigos están en la página de errores.
# v1
result = response.json()
if result.get("status") == 1:
    msg_id = result["msg_id"]

# v2
if response.status_code == 202:
    message_id = response.json()["id"]
else:
    error = response.json()["error"]
    if error["code"] == "number_daily_cap_reached":
        ...  # try again tomorrow

Algunos mensajes de la v1 y sus códigos en la v2:

Mensaje de v1Código de v2
Auth Error: invalid api key401 invalid_api_key, api_key_revoked o api_key_expired
Invalid phone number / Invalid Contact Number "…"422 invalid_phone
Msg cant be null400 text_required
Message length is too long400 text_too_long
Invalid whatsapp client422 number_not_found
Invalid whatsapp client id.422 from_required
Not enough credits402 no_credits
Daily limit reached: …429 number_daily_cap_reached
Demo Account can not access apis403 demo_account
Account Disabled403 account_disabled
Invalid JSON format: …400 invalid_json

Webhooks#

En la v1, cada mensaje puede llevar una URL webhook que recibe un msg_id=…&status=SENT codificado como formulario. En la v2:

  1. Añade un endpoint una sola vez con POST /webhooks y guarda su secret.
  2. Recibe eventos JSON de todos los mensajes del espacio de trabajo, con el Message completo en data.message. Relaciónalos con tus registros por data.message.id.
  3. Comprueba la firma: el mismo esquema que en la v1 (WbizTool-Timestamp, WbizTool-Signature: v1=…), pero con el secreto propio del endpoint en lugar del del espacio de trabajo.
  4. Descarta los repetidos con WbizTool-Event-Id. Los reintentos continúan durante unas 23 horas, no 4 intentos en pocos minutos como en la v1, y las respuestas 4xx también se reintentan.

Los eventos de conexión de la v1 (webhook_url en whatsapp/connect/) aún no tienen evento en la v2: consulta GET /numbers/{id} en su lugar.

Lista de comprobación#

  1. Crea una clave v2 por app

    En Configuración → Claves API, solo con los permisos que necesite. Pruébala primero con una clave de prueba, que lo comprueba todo y no envía nada.

  2. Cambia las solicitudes

    URL y métodos nuevos, cuerpos JSON, to / from / text / media, números de teléfono con +, horas con desfase. Añade una Idempotency-Key a cada envío.

  3. Cambia el manejo de errores

    Comprueba el estado HTTP y luego error.code. Gestiona 429 esperando lo que indique Retry-After.

  4. Pasa los webhooks

    Añade un endpoint, comprueba las firmas con su secreto y descarta los repetidos por id de evento.

  5. Cambia y revoca

    Cuando la app funcione con la v2, elimina su clave v1 en Configuración → Claves API.

Relacionado#