📱 WhatsApp Server · API Docs
← Inicio Iniciar sesión

Documentación de la API

Guía completa para enviar mensajes de WhatsApp desde tu aplicación.

Contenido

🔑 Tu API Key la encontrás en tu panel de cliente. Reemplazá TU_API_KEY y TU_URL_BASE en los ejemplos.
La URL base es: https://oietema.com/whatsapp/

Autenticación

Todos los endpoints de envío requieren el header:

Authorization: Bearer TU_API_KEY

POST Enviar texto

https://oietema.com/whatsapp/api/send/text
CampoTipoDescripción
tostringNúmero destino con código de país, sin + requerido
Ej: 595981XXXXXX
messagestringTexto del mensaje requerido
curl -X POST https://oietema.com/whatsapp/api/send/text \
  -H "Authorization: Bearer TU_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"to":"595981XXXXXX","message":"Hola desde cURL 👋"}'
<?php
$apiKey  = 'TU_API_KEY';
$baseUrl = 'https://oietema.com/whatsapp/';

$data = [
    'to'      => '595981XXXXXX',
    'message' => 'Hola desde PHP 👋',
];

$ch = curl_init($baseUrl . 'api/send/text');
curl_setopt_array($ch, [
    CURLOPT_POST           => true,
    CURLOPT_POSTFIELDS     => json_encode($data),
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
]);
$response = curl_exec($ch);
curl_close($ch);

$result = json_decode($response, true);
if ($result['ok']) {
    echo 'Enviado! ID: ' . $result['messageId'];
} else {
    echo 'Error: ' . $result['error'];
}
' Requiere referencia a: Microsoft XML v6.0 (msxml6.dll)
' y Microsoft Scripting Runtime (para JSON simple)

Private Sub EnviarWhatsApp(numero As String, mensaje As String)
    Dim http  As New MSXML2.XMLHTTP60
    Dim sUrl  As String
    Dim sBody As String
    Dim sKey  As String

    sKey  = "TU_API_KEY"
    sUrl  = "https://oietema.com/whatsapp/api/send/text"
    sBody = "{""to"":""" & numero & """,""message"":""" & mensaje & """}"

    http.Open "POST", sUrl, False
    http.setRequestHeader "Authorization", "Bearer " & sKey
    http.setRequestHeader "Content-Type", "application/json"
    http.send sBody

    If InStr(http.responseText, """ok"":true") > 0 Then
        MsgBox "Mensaje enviado correctamente", vbInformation
    Else
        MsgBox "Error: " & http.responseText, vbCritical
    End If
End Sub

' Uso:
EnviarWhatsApp "595981XXXXXX", "Hola desde VB6!"
Imports System.Net
Imports System.Text
Imports System.IO

Public Sub EnviarWhatsApp(numero As String, mensaje As String)
    Dim url  As String = "https://oietema.com/whatsapp/api/send/text"
    Dim key  As String = "TU_API_KEY"
    Dim body As String = $"""{{""to"":""{numero}"",""message"":""{mensaje}""}}"""

    Dim req As HttpWebRequest = WebRequest.Create(url)
    req.Method      = "POST"
    req.ContentType = "application/json"
    req.Headers.Add("Authorization", "Bearer " & key)

    Dim bytes() As Byte = Encoding.UTF8.GetBytes(body)
    req.ContentLength = bytes.Length
    Using s = req.GetRequestStream() : s.Write(bytes, 0, bytes.Length) : End Using

    Using resp = req.GetResponse()
        Using sr = New StreamReader(resp.GetResponseStream())
            Dim result = sr.ReadToEnd()
            MessageBox.Show("Respuesta: " & result)
        End Using
    End Using
End Sub
import requests

api_key  = "TU_API_KEY"
base_url = "https://oietema.com/whatsapp/"

response = requests.post(
    base_url + "api/send/text",
    headers={"Authorization": f"Bearer {api_key}"},
    json={"to": "595981XXXXXX", "message": "Hola desde Python 🐍"},
)

data = response.json()
if data.get("ok"):
    print(f"Enviado! ID: {data['messageId']}")
else:
    print(f"Error: {data['error']}")
const apiKey  = 'TU_API_KEY';
const baseUrl = 'https://oietema.com/whatsapp/';

const res = await fetch(baseUrl + 'api/send/text', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ to: '595981XXXXXX', message: 'Hola desde JS 👾' }),
});
const data = await res.json();
console.log(data); // { ok: true, messageId: '...' }
using System.Net.Http;
using System.Text;

var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer TU_API_KEY");

var body = new StringContent(
    """{"to":"595981XXXXXX","message":"Hola desde C# 🚀"}""",
    Encoding.UTF8, "application/json"
);

var response = await client.PostAsync(
    "https://oietema.com/whatsapp/api/send/text", body
);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
// Requiere: Indy (TIdHTTP) — incluido en Delphi/Lazarus
uses
  IdHTTP, IdSSLOpenSSL, Classes;

procedure EnviarWhatsApp(numero, mensaje: string);
var
  HTTP   : TIdHTTP;
  SSL    : TIdSSLIOHandlerSocketOpenSSL;
  Body   : TStringStream;
  Result : string;
begin
  HTTP  := TIdHTTP.Create(nil);
  SSL   := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
  Body  := TStringStream.Create(
    '{"to":"' + numero + '","message":"' + mensaje + '"}',
    TEncoding.UTF8
  );
  try
    HTTP.IOHandler := SSL;
    HTTP.Request.CustomHeaders.Values['Authorization'] := 'Bearer TU_API_KEY';
    HTTP.Request.ContentType := 'application/json';
    Result := HTTP.Post('https://oietema.com/whatsapp/api/send/text', Body);
    ShowMessage('Respuesta: ' + Result);
  finally
    Body.Free; SSL.Free; HTTP.Free;
  end;
end;

POST Enviar imagen

https://oietema.com/whatsapp/api/send/image
CampoTipoDescripción
tostringNúmero destino requerido
urlstringURL pública de la imagen requerido*
dataBase64stringImagen en base64 requerido* (alternativa a url)
captionstringTexto debajo de la imagen opcional
<?php
// Opción 1: enviar por URL
$data = [
    'to'      => '595981XXXXXX',
    'url'     => 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/1e/Stonehenge.jpg/400px-Stonehenge.jpg',
    'caption' => 'Imagen de ejemplo',
];

// Opción 2: enviar base64 (imagen local)
// $data['dataBase64'] = base64_encode(file_get_contents('/ruta/imagen.jpg'));
// unset($data['url']);

$ch = curl_init('https://oietema.com/whatsapp/api/send/image');
curl_setopt_array($ch, [
    CURLOPT_POST           => true,
    CURLOPT_POSTFIELDS     => json_encode($data),
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer TU_API_KEY',
        'Content-Type: application/json',
    ],
]);
$r = json_decode(curl_exec($ch), true);
curl_close($ch);
print_r($r);
Dim http As New MSXML2.XMLHTTP60
Dim sBody As String

sBody = "{""to"":""595981XXXXXX""" & _
         ",""url"":""https://ejemplo.com/imagen.jpg""" & _
         ",""caption"":""Mi imagen""}"

http.Open "POST", "https://oietema.com/whatsapp/api/send/image", False
http.setRequestHeader "Authorization", "Bearer TU_API_KEY"
http.setRequestHeader "Content-Type", "application/json"
http.send sBody
MsgBox http.responseText
import requests, base64

# Opción 1: por URL
r = requests.post(
    "https://oietema.com/whatsapp/api/send/image",
    headers={"Authorization": "Bearer TU_API_KEY"},
    json={"to": "595981XXXXXX", "url": "https://ejemplo.com/img.jpg", "caption": "Foto"},
)

# Opción 2: base64
with open("imagen.jpg", "rb") as f:
    b64 = base64.b64encode(f.read()).decode()
r = requests.post(
    "https://oietema.com/whatsapp/api/send/image",
    headers={"Authorization": "Bearer TU_API_KEY"},
    json={"to": "595981XXXXXX", "dataBase64": b64},
)
print(r.json())

POST Enviar documento / PDF

https://oietema.com/whatsapp/api/send/document
CampoTipoDescripción
tostringNúmero destino requerido
urlstringURL pública del archivo requerido*
dataBase64stringArchivo en base64 requerido* (alternativa)
filenamestringNombre del archivo opcional (ej: factura.pdf)
mimetypestringMIME type opcional (default: application/pdf)
captionstringDescripción opcional
<?php
// Enviar PDF local como base64
$pdfPath = '/ruta/al/factura.pdf';
$data = [
    'to'          => '595981XXXXXX',
    'dataBase64'  => base64_encode(file_get_contents($pdfPath)),
    'filename'    => 'factura_001.pdf',
    'mimetype'    => 'application/pdf',
    'caption'     => 'Tu factura del mes',
];

$ch = curl_init('https://oietema.com/whatsapp/api/send/document');
curl_setopt_array($ch, [
    CURLOPT_POST           => true,
    CURLOPT_POSTFIELDS     => json_encode($data),
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer TU_API_KEY',
        'Content-Type: application/json',
    ],
]);
$r = json_decode(curl_exec($ch), true);
curl_close($ch);
echo $r['ok'] ? 'Enviado!' : 'Error: ' . $r['error'];
' Función para convertir archivo a Base64 en VB6
Function FileToBase64(filePath As String) As String
    Dim xml As New MSXML2.DOMDocument60
    Dim node As MSXML2.IXMLDOMElement
    Dim stream As New ADODB.Stream

    stream.Type = 1 ' adTypeBinary
    stream.Open
    stream.LoadFromFile filePath
    Set node = xml.createElement("b64")
    node.dataType = "bin.base64"
    node.nodeTypedValue = stream.Read()
    FileToBase64 = node.Text
End Function

' Enviar el PDF
Sub EnviarPDF()
    Dim http As New MSXML2.XMLHTTP60
    Dim b64  As String
    b64 = FileToBase64("C:\facturas\factura.pdf")

    Dim body As String
    body = "{""to"":""595981XXXXXX""" & _
            ",""dataBase64"":""" & b64 & """" & _
            ",""filename"":""factura.pdf""" & _
            ",""caption"":""Tu factura""}"

    http.Open "POST", "https://oietema.com/whatsapp/api/send/document", False
    http.setRequestHeader "Authorization", "Bearer TU_API_KEY"
    http.setRequestHeader "Content-Type", "application/json"
    http.send body
    MsgBox http.responseText
End Sub
import requests, base64

with open("factura.pdf", "rb") as f:
    b64 = base64.b64encode(f.read()).decode()

r = requests.post(
    "https://oietema.com/whatsapp/api/send/document",
    headers={"Authorization": "Bearer TU_API_KEY"},
    json={
        "to":         "595981XXXXXX",
        "dataBase64": b64,
        "filename":   "factura.pdf",
        "caption":    "Tu factura del mes",
    },
)
print(r.json())
curl -X POST https://oietema.com/whatsapp/api/send/document \
  -H "Authorization: Bearer TU_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"to":"595981XXXXXX","url":"https://ejemplo.com/archivo.pdf","filename":"archivo.pdf"}'

GET Enviar texto por URL (modo simple)

https://oietema.com/whatsapp/api/send?key=TU_API_KEY&to=NUMERO&message=TEXTO

Permite enviar un mensaje de texto escribiendo directamente la URL en el navegador, usando curl básico o desde herramientas que solo soportan GET. No requiere headers.

ParámetroDescripción
keyTu API Key requerido
toNúmero destino con código de país, sin + requerido
messageTexto del mensaje requerido (usar %20 o + para espacios)
⚠️ Atención: la API Key viaja en la URL, por lo tanto queda visible en logs del servidor, historial del navegador y Cloudflare. Usá este método solo para pruebas o entornos internos. Para producción preferí POST con header Authorization.
// Pegá esto directo en la barra del navegador:
https://oietema.com/whatsapp/api/send?key=TU_API_KEY&to=595981XXXXXX&message=Hola+desde+el+navegador
curl "https://oietema.com/whatsapp/api/send?key=TU_API_KEY&to=595981XXXXXX&message=Hola+desde+curl"
Dim http As New MSXML2.XMLHTTP60
Dim sUrl As String

' Reemplazá espacios con + y caracteres especiales con %XX
sUrl = "https://oietema.com/whatsapp/api/send" & _
        "?key=TU_API_KEY" & _
        "&to=595981XXXXXX" & _
        "&message=Hola+desde+VB6"

http.Open "GET", sUrl, False
http.send

If InStr(http.responseText, """ok"":true") > 0 Then
    MsgBox "Mensaje enviado!", vbInformation
Else
    MsgBox "Error: " & http.responseText, vbCritical
End If
<?php
$url = 'https://oietema.com/whatsapp/api/send?' . http_build_query([
    'key'     => 'TU_API_KEY',
    'to'      => '595981XXXXXX',
    'message' => 'Hola desde PHP con GET',
]);
$r = json_decode(file_get_contents($url), true);
echo $r['ok'] ? 'Enviado!' : 'Error: ' . $r['error'];

GET Estado de la sesión

https://oietema.com/whatsapp/api/status

Devuelve el estado de la sesión de WhatsApp vinculada a tu API Key.

curl https://oietema.com/whatsapp/api/status \
  -H "Authorization: Bearer TU_API_KEY"

// Respuesta posible:
{ "status": "connected", "user": { "id": "595981XXXXXX:3@s.whatsapp.net" } }
// status: "connected" | "connecting" | "qr" | "disconnected"

GET Verificar número

https://oietema.com/whatsapp/api/check/{numero}

Verifica si un número tiene WhatsApp activo.

curl https://oietema.com/whatsapp/api/check/595981XXXXXX \
  -H "Authorization: Bearer TU_API_KEY"

// Respuesta:
{ "exists": true, "jid": "595981XXXXXX@s.whatsapp.net" }

Gestión de sesión (escaneo QR)

Iniciá, consultá y desconectá la sesión de WhatsApp desde tu propia aplicación, sin necesidad de entrar al panel web.
Flujo recomendado: llamar a /start → hacer polling a /state cada 3 s → cuando status === "qr", mostrar la imagen al usuario → seguir el polling hasta status === "connected".

POST Iniciar sesión

https://oietema.com/whatsapp/api/session/start

Arranca la sesión del canal. Si ya está conectada o conectando, no hace nada. Devuelve el estado actual.

curl -X POST https://oietema.com/whatsapp/api/session/start \
  -H "Authorization: Bearer TU_API_KEY"
<?php
$ch = curl_init('https://oietema.com/whatsapp/api/session/start');
curl_setopt_array($ch, [
    CURLOPT_POST           => true,
    CURLOPT_POSTFIELDS     => '',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer TU_API_KEY'],
]);
$r = json_decode(curl_exec($ch), true);
curl_close($ch);
// $r['status'] puede ser: connecting | qr | connected | disconnected
echo $r['status'];
import requests

r = requests.post(
    "https://oietema.com/whatsapp/api/session/start",
    headers={"Authorization": "Bearer TU_API_KEY"},
)
print(r.json())  # {'status': 'connecting', ...}
const res = await fetch('https://oietema.com/whatsapp/api/session/start', {
  method: 'POST',
  headers: { 'Authorization': 'Bearer TU_API_KEY' },
});
const data = await res.json();
console.log(data.status); // 'connecting'

GET Consultar estado y obtener QR

https://oietema.com/whatsapp/api/session/state

Devuelve el estado actual. Cuando status es "qr", el campo qrDataUrl contiene la imagen del código QR lista para mostrar en un <img src="...">.

Campo en respuestaValor posibleDescripción
statusconnecting · qr · connected · disconnected · logged_outEstado actual de la sesión
qrDataUrlstring / nullImagen QR como Data URL (PNG base64). Solo presente cuando status === "qr"
userobjeto / nullDatos del número conectado (cuando status === "connected")
lastErrorstring / nullÚltimo error registrado
<?php
// Polling: esperar QR o conexión (máx ~60 s)
$apiKey  = 'TU_API_KEY';
$baseUrl = 'https://oietema.com/whatsapp/';

// 1) Iniciar sesión
$ch = curl_init($baseUrl . 'api/session/start');
curl_setopt_array($ch, [CURLOPT_POST => true, CURLOPT_POSTFIELDS => '',
    CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey]]);
curl_exec($ch); curl_close($ch);

// 2) Polling cada 3 s
for ($i = 0; $i < 20; $i++) {
    sleep(3);
    $ch = curl_init($baseUrl . 'api/session/state');
    curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey]]);
    $r = json_decode(curl_exec($ch), true);
    curl_close($ch);

    if ($r['status'] === 'qr') {
        // Mostrar QR al usuario (Data URL lista para <img src=...>)
        echo '<img src="' . $r['qrDataUrl'] . '">';
    } elseif ($r['status'] === 'connected') {
        echo '¡Conectado! ' . $r['user']['id'];
        break;
    }
}
curl https://oietema.com/whatsapp/api/session/state \
  -H "Authorization: Bearer TU_API_KEY"

// Respuesta con QR pendiente:
{
  "status": "qr",
  "qrDataUrl": "data:image/png;base64,iVBOR...",
  "user": null,
  "lastError": null
}

// Respuesta cuando ya está conectado:
{
  "status": "connected",
  "qrDataUrl": null,
  "user": { "id": "595981XXXXXX:3@s.whatsapp.net" },
  "lastError": null
}
import requests, time

api_key  = "TU_API_KEY"
base_url = "https://oietema.com/whatsapp/"
hdrs     = {"Authorization": f"Bearer {api_key}"}

# 1) Iniciar sesión
requests.post(base_url + "api/session/start", headers=hdrs)

# 2) Polling
for _ in range(20):
    time.sleep(3)
    data = requests.get(base_url + "api/session/state", headers=hdrs).json()

    if data["status"] == "qr":
        # data["qrDataUrl"] es un string "data:image/png;base64,..."
        # Guardarlo como imagen para mostrárselo al usuario
        qr_b64 = data["qrDataUrl"].split(",", 1)[1]
        import base64
        with open("qr.png", "wb") as f:
            f.write(base64.b64decode(qr_b64))
        print("QR guardado en qr.png — escaneá con WhatsApp")

    elif data["status"] == "connected":
        print(f"¡Conectado como {data['user']['id']}")
        break
const apiKey  = 'TU_API_KEY';
const base    = 'https://oietema.com/whatsapp/';
const headers = { 'Authorization': `Bearer ${apiKey}` };

// 1) Iniciar
await fetch(base + 'api/session/start', { method: 'POST', headers });

// 2) Polling cada 3 s
const poll = setInterval(async () => {
  const data = await (await fetch(base + 'api/session/state', { headers })).json();

  if (data.status === 'qr') {
    // Mostrar en una imagen HTML
    document.getElementById('qrImg').src = data.qrDataUrl;
  } else if (data.status === 'connected') {
    clearInterval(poll);
    console.log('¡Conectado!', data.user.id);
  }
}, 3000);

POST Desconectar sesión

https://oietema.com/whatsapp/api/session/logout

Desvincula el número, borra las credenciales guardadas y detiene la sesión. El próximo start generará un QR nuevo.

curl -X POST https://oietema.com/whatsapp/api/session/logout \
  -H "Authorization: Bearer TU_API_KEY"

// Respuesta: { "ok": true }
<?php
$ch = curl_init('https://oietema.com/whatsapp/api/session/logout');
curl_setopt_array($ch, [
    CURLOPT_POST           => true,
    CURLOPT_POSTFIELDS     => '',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer TU_API_KEY'],
]);
$r = json_decode(curl_exec($ch), true);
curl_close($ch);
echo $r['ok'] ? 'Desconectado' : 'Error';

Respuestas y errores

HTTPSignificado
200{ "ok": true, "messageId": "…" } — enviado correctamente
400Faltan campos requeridos (to, message, etc.)
401API Key inválida o ausente
403Cliente inactivo
500Error interno (WhatsApp desconectado, número inválido, etc.)
⚠️ Si el estado es distinto de connected, los envíos devuelven error 500. Verificá el estado con /api/status antes de enviar en masa.