Griito API

Documentación completa para integrar llamadas automatizadas en tu aplicación.

Base URL

https://api.griito.com

Formato de envío

Todas las solicitudes usan application/x-www-form-urlencoded, excepto el endpoint /audios que requiere multipart/form-data.

Todas las respuestas son JSON.

Autenticación requerida: Todos los endpoints requieren el header Authorization: Bearer {token}, excepto /register, /oauth/token y los de recuperación de contraseña.

Autenticación

POST /register

Crea una nueva cuenta de usuario.

ParámetroTipoRequeridoDescripción
client_idstringID de cliente OAuth
client_secretstringSecret de cliente OAuth
namestringNombre del usuario
emailstringCorreo electrónico
passwordstringContraseña
curl -X POST https://api.griito.com/register \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "client_secret=YOUR_CLIENT_SECRET" \
  -d "name=Juan Pérez" \
  -d "email=juan@ejemplo.com" \
  -d "password=mi_password_seguro"

Response

{
  "message": "user created",
  "user_id": 42
}

POST /oauth/token

Obtiene un token de acceso OAuth 2.0.

ParámetroTipoRequeridoDescripción
grant_typestringSiempre password
client_idstringID de cliente OAuth
client_secretstringSecret de cliente OAuth
usernamestringEmail del usuario
passwordstringContraseña del usuario
scopestringSiempre *
curl -X POST https://api.griito.com/oauth/token \
  -d "grant_type=password" \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "client_secret=YOUR_CLIENT_SECRET" \
  -d "username=juan@ejemplo.com" \
  -d "password=mi_password_seguro" \
  -d "scope=*"

Response

{
  "token_type": "Bearer",
  "expires_in": 31536000,
  "access_token": "eyJ0eXAiOiJKV1QiLCJhbGci...",
  "refresh_token": "def50200ae5b0..."
}
Uso del token: Incluye el header en todas las solicitudes autenticadas:
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGci...

Recuperación de contraseña

Flujo de dos pasos para que un usuario recupere el acceso a su cuenta. Ambos endpoints son públicos: no requieren token Bearer.

Cómo funciona: el paso 1 genera un código aleatorio de un solo uso y lo envía por correo al usuario. El paso 2 valida ese código y establece la nueva contraseña. El código se invalida al usarlo o al solicitar uno nuevo.
Usa POST. Ambos endpoints aceptan POST y GET. Con GET los parámetros viajan en la URL y quedan escritos en texto plano en los logs del servidor — incluidos tu client_secret y la contraseña nueva. Con POST van en el cuerpo de la solicitud y no se registran. GET se mantiene solo por compatibilidad con clientes antiguos.

POST /users/forgotpassword

Inicia el proceso: envía al correo del usuario un enlace con el código de recuperación.

ParámetroTipoRequeridoDescripción
emailstringCorreo registrado del usuario
client_idstringID de cliente OAuth
client_secretstringSecret de cliente OAuth
redirect_tostringNoURL de retorno para tu aplicación
curl -X POST https://api.griito.com/users/forgotpassword \
  -d "email=juan@ejemplo.com" \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "client_secret=YOUR_CLIENT_SECRET"

Response

{
  "message": "An email has been sent"
}
Privacidad: la respuesta es siempre 200, exista o no el correo en el sistema. Esto impide usar el endpoint para descubrir qué correos están registrados.

Errores

HTTPCódigoDescripción
42217Falta el parámetro email
40131client_id o client_secret inválidos

Correo recibido por el usuario

El mensaje incluye un botón que apunta a la página de restablecimiento con los datos ya cargados:

https://www.griito.com/comenzar/reset.html?email={email}&code={code}

POST /users/resetpassword

Valida el código recibido y establece la nueva contraseña.

ParámetroTipoRequeridoDescripción
codestringCódigo enviado al correo del usuario
emailstringSí*Correo del usuario
user_idintegerSí*ID del usuario, alternativa a email
npwdstringNueva contraseña, mínimo 6 caracteres

* Debes enviar email o user_id. Si envías ambos, se usa user_id. Este endpoint no requiere client_id ni client_secret.

curl -X POST https://api.griito.com/users/resetpassword \
  -d "email=juan@ejemplo.com" \
  -d "code=a1b2c3d4e5f6..." \
  -d "npwd=mi_nueva_password"

Response

{
  "message": "user password updated",
  "data": { "id": 42, "name": "Juan Pérez", "email": "juan@ejemplo.com" }
}

Errores

HTTPCódigoDescripción
42217Faltan parámetros obligatorios
4227Contraseña menor a 6 caracteres
40330El código no corresponde al usuario, o ya fue utilizado

Flujo completo

# 1. Solicitar el correo de recuperación
curl -X POST https://api.griito.com/users/forgotpassword \
  -d "email=juan@ejemplo.com" \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "client_secret=YOUR_CLIENT_SECRET"

# 2. El usuario abre el enlace del correo y define su nueva contraseña
curl -X POST https://api.griito.com/users/resetpassword \
  -d "email=juan@ejemplo.com" \
  -d "code=CODIGO_DEL_CORREO" \
  -d "npwd=mi_nueva_password"

# 3. Iniciar sesión con la nueva contraseña
curl -X POST https://api.griito.com/oauth/token \
  -d "grant_type=password" \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "client_secret=YOUR_CLIENT_SECRET" \
  -d "username=juan@ejemplo.com" \
  -d "password=mi_nueva_password" \
  -d "scope=*"
import requests

BASE = "https://api.griito.com"

# 1. Solicitar el correo de recuperación
requests.post(f"{BASE}/users/forgotpassword", data={
    "email": "juan@ejemplo.com",
    "client_id": "YOUR_CLIENT_ID",
    "client_secret": "YOUR_CLIENT_SECRET"
})

# 2. El usuario abre el enlace del correo y define su nueva contraseña
resp = requests.post(f"{BASE}/users/resetpassword", data={
    "email": "juan@ejemplo.com",
    "code": "CODIGO_DEL_CORREO",
    "npwd": "mi_nueva_password"
})
print(resp.json())
<?php
$base = "https://api.griito.com";

function post($url, $data) {
    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_POST           => true,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POSTFIELDS     => http_build_query($data)
    ]);
    $res = curl_exec($ch);
    curl_close($ch);
    return json_decode($res, true);
}

// 1. Solicitar el correo de recuperación
post("$base/users/forgotpassword", [
    "email"         => "juan@ejemplo.com",
    "client_id"     => "YOUR_CLIENT_ID",
    "client_secret" => "YOUR_CLIENT_SECRET"
]);

// 2. El usuario abre el enlace del correo y define su nueva contraseña
$result = post("$base/users/resetpassword", [
    "email" => "juan@ejemplo.com",
    "code"  => "CODIGO_DEL_CORREO",
    "npwd"  => "mi_nueva_password"
]);

print_r($result);
const BASE = "https://api.griito.com";

const FORM = { "Content-Type": "application/x-www-form-urlencoded" };

// 1. Solicitar el correo de recuperación
await fetch(`${BASE}/users/forgotpassword`, {
  method: "POST",
  headers: FORM,
  body: new URLSearchParams({
    email: "juan@ejemplo.com",
    client_id: "YOUR_CLIENT_ID",
    client_secret: "YOUR_CLIENT_SECRET"
  })
});

// 2. El usuario abre el enlace del correo y define su nueva contraseña
const resp = await fetch(`${BASE}/users/resetpassword`, {
  method: "POST",
  headers: FORM,
  body: new URLSearchParams({
    email: "juan@ejemplo.com",
    code: "CODIGO_DEL_CORREO",
    npwd: "mi_nueva_password"
  })
});
console.log(await resp.json());

Usuario

GET /user

Obtiene los datos del usuario autenticado.

curl https://api.griito.com/user \
  -H "Authorization: Bearer YOUR_TOKEN"

Response

{
  "id": 42,
  "name": "Juan Pérez",
  "email": "juan@ejemplo.com",
  "callerid": "+56912345678",
  "maxrcp": 1000,
  "plan_id": 2,
  "country": "CL",
  "created_at": "2024-01-15T10:30:00.000000Z"
}

PATCH /user

Actualiza datos del usuario. Todos los parámetros son opcionales.

ParámetroTipoDescripción
namestringNuevo nombre
emailstringNuevo email
passwordstringNueva contraseña
curl -X PATCH https://api.griito.com/user \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -d "name=Juan Actualizado"

GET /credits

Consulta los créditos disponibles del usuario.

curl https://api.griito.com/credits \
  -H "Authorization: Bearer YOUR_TOKEN"

Response

{
  "credits": 150.50
}

Caller ID

El Caller ID es el número que se muestra al destinatario cuando recibe tus llamadas. Para usar un número propio hay que verificar que te pertenece, en dos pasos.

Cómo funciona: el paso 1 genera un código de 4 dígitos y llama al número indicado para dictarlo por voz (lo repite dos veces). El paso 2 confirma ese código y activa el número como Caller ID de tu cuenta.
La llamada de verificación no consume créditos. Se registra como una llamada tipo 2 (TTS) con costo 0 y el batch callerid_verification.

POST /user/callerid

Inicia la verificación: genera el código y dispara la llamada al número.

ParámetroTipoRequeridoDescripción
recipientsstringNúmero a verificar. Se ignoran los caracteres no numéricos, y a los números internacionales se les antepone 00 automáticamente
curl -X POST https://api.griito.com/user/callerid \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -d "recipients=+56912345678"

Response

{
  "success": true,
  "text": "Código enviado al teléfono",
  "data": 1024
}

data es el ID del registro de validación. El código en sí no viaja en la respuesta: solo se entrega por voz en la llamada.

Errores

HTTPCódigoDescripción
42217Falta el parámetro recipients
500{"success": false, "message": "TTS generation failed"} si no se pudo generar el audio

POST /user/callerid/code

Confirma el código dictado en la llamada y activa el Caller ID.

ParámetroTipoRequeridoDescripción
codestringLos 4 dígitos dictados, sin espacios (ej: 4821)
curl -X POST https://api.griito.com/user/callerid/code \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -d "code=4821"

Response

{
  "success": true,
  "text": "CallerID Activado"
}

Al activarse, el número queda guardado en el campo callerid de tu usuario y puedes verlo con GET /user.

Errores

HTTPCódigoDescripción
42217Falta el parámetro code
40324El código no coincide
Se valida siempre contra el último código generado. Si pides una verificación nueva antes de confirmar la anterior, la anterior deja de servir. El código no expira por tiempo.

Flujo completo

# 1. Pedir la llamada de verificación
curl -X POST https://api.griito.com/user/callerid \
  -H "Authorization: Bearer $TOKEN" \
  -d "recipients=+56912345678"

# 2. Atender la llamada, anotar los 4 dígitos y confirmarlos
curl -X POST https://api.griito.com/user/callerid/code \
  -H "Authorization: Bearer $TOKEN" \
  -d "code=4821"

# 3. Comprobar que quedó activo
curl https://api.griito.com/user \
  -H "Authorization: Bearer $TOKEN"
import requests

BASE = "https://api.griito.com"
headers = {"Authorization": f"Bearer {token}"}

# 1. Pedir la llamada de verificación
requests.post(f"{BASE}/user/callerid", headers=headers,
              data={"recipients": "+56912345678"})

# 2. Atender la llamada y confirmar los 4 dígitos
code = input("Código dictado en la llamada: ")
resp = requests.post(f"{BASE}/user/callerid/code", headers=headers,
                     data={"code": code})
print(resp.json())

# 3. Comprobar que quedó activo
print(requests.get(f"{BASE}/user", headers=headers).json()["callerid"])
<?php
$base = "https://api.griito.com";

function post($url, $token, $data) {
    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_POST           => true,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER     => ["Authorization: Bearer $token"],
        CURLOPT_POSTFIELDS     => http_build_query($data)
    ]);
    $res = curl_exec($ch);
    curl_close($ch);
    return json_decode($res, true);
}

// 1. Pedir la llamada de verificación
post("$base/user/callerid", $token, ["recipients" => "+56912345678"]);

// 2. Atender la llamada y confirmar los 4 dígitos
$result = post("$base/user/callerid/code", $token, ["code" => "4821"]);

print_r($result);
const BASE = "https://api.griito.com";
const headers = {
  Authorization: `Bearer ${token}`,
  "Content-Type": "application/x-www-form-urlencoded"
};

// 1. Pedir la llamada de verificación
await fetch(`${BASE}/user/callerid`, {
  method: "POST",
  headers,
  body: new URLSearchParams({ recipients: "+56912345678" })
});

// 2. Atender la llamada y confirmar los 4 dígitos
const resp = await fetch(`${BASE}/user/callerid/code`, {
  method: "POST",
  headers,
  body: new URLSearchParams({ code: "4821" })
});
console.log(await resp.json());

Usarlo en tus llamadas

Una vez activado, basta con enviar el flag en POST /calls. El número no se pasa como parámetro: la API usa el que verificaste.

curl -X POST https://api.griito.com/calls \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -d "type=2" \
  -d "recipients=+56911111111" \
  -d "tts=Hola, te llamamos desde Griito." \
  -d "callerid=true"
No puedes llamarte a ti mismo. Si el destinatario coincide con tu Caller ID verificado, la API responde 422 con el código 45.

Audios

GET /audios

Lista todos los audios del usuario.

curl https://api.griito.com/audios \
  -H "Authorization: Bearer YOUR_TOKEN"

Response

{
  "data": [
    {
      "id": 1,
      "id_api": "abc123",
      "nombre_grabacion": "saludo_cliente",
      "fecha_creacion": "2024-06-01 14:30:00",
      "activo": 1,
      "descripcion": "Audio de bienvenida",
      "status": "ready"
    }
  ]
}

POST /audios

Sube un nuevo audio. Usa multipart/form-data. El servidor normaliza el archivo a WAV 8kHz mono automáticamente.

ParámetroTipoRequeridoDescripción
audiofileArchivo de audio (mp3, wav, ogg, etc.)
namestringNombre identificador del audio
descriptionstringNoDescripción del audio
curl -X POST https://api.griito.com/audios \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -F "audio=@/ruta/a/mi_audio.mp3" \
  -F "name=saludo_cliente" \
  -F "description=Audio de bienvenida para clientes"

Response

{
  "success": true,
  "text": "Audio guardado",
  "data": {
    "id": 5,
    "id_api": "xyz789",
    "nombre_grabacion": "saludo_cliente",
    "descripcion": "Audio de bienvenida para clientes"
  }
}

GET /audios/{id}

Obtiene el detalle de un audio específico, incluyendo la URL del archivo.

curl https://api.griito.com/audios/5 \
  -H "Authorization: Bearer YOUR_TOKEN"

DELETE /audios/{id}

Elimina un audio (soft delete).

curl -X DELETE https://api.griito.com/audios/5 \
  -H "Authorization: Bearer YOUR_TOKEN"

Llamadas

El recurso principal de la API. Permite crear, consultar, modificar y cancelar llamadas automatizadas.

Tipos de llamada

Tipo
Descripción
0
Audio unidireccional — Reproduce un audio pregrabado al destinatario
1
Audio con respuesta — Reproduce un audio y luego graba la respuesta del destinatario
2
TTS unidireccional — Convierte texto a voz y lo reproduce al destinatario
3
TTS con respuesta — Convierte texto a voz, lo reproduce y graba la respuesta

Estados de llamada

CódigoEstado
0Pendiente
1Completada
2Fallida

POST /calls

Crea una o más llamadas.

Parámetros comunes

ParámetroTipoRequeridoDescripción
typeintegerTipo de llamada (0, 1, 2 o 3)
recipientsstring | arrayNúmero(s) de teléfono destino
abridstring | arrayIdentificador libre para cada llamada
calltimestring | arrayNoFecha/hora ISO 8601 para programar
batch_idstringNoID de batch existente
batch_namestringNoNombre del batch
timezonestringNoZona horaria (default: UTC)

Parámetros para tipo 0 y 1 (audio)

ParámetroTipoRequeridoDescripción
audiointeger | arrayID del audio subido previamente

Parámetros para tipo 2 y 3 (TTS)

ParámetroTipoRequeridoDescripción
ttsstring | arrayTexto a convertir a voz (máx 500 caracteres)

Parámetros opcionales

ParámetroTipoDescripción
calleridstringEnvía "true" para que la llamada se muestre con tu número verificado. Ver Caller ID
force_scheduleboolForzar programación fuera de horario
adjust_scheduleboolAjustar automáticamente al próximo horario permitido
prevent_partial_errorboolEvitar envío parcial si algún destinatario falla validación
El número lo resuelve el backend. No hay que indicarlo en la solicitud: con callerid=true la API toma automáticamente el número que verificaste en Caller ID y lo usa como remitente. Solo se envía el flag.
Ojo con el valor: callerid se compara contra la cadena literal "true". Cualquier otro valor —1, yes, o un booleano JSON— se interpreta como desactivado y la llamada sale igual, sin error, pero sin tu número. Si envías el formulario como application/x-www-form-urlencoded, escribe callerid=true.

Ejemplo — Llamada tipo 0 (audio unidireccional):

curl -X POST https://api.griito.com/calls \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -d "type=0" \
  -d "recipients=+56912345678" \
  -d "audio=5" \
  -d "abrid=pedido_1001"

Response

{
  "success": true,
  "text": "Mensaje(s) Ingresado",
  "data": [101],
  "batch_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}

Ejemplo — Llamada tipo 2 (TTS unidireccional):

curl -X POST https://api.griito.com/calls \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -d "type=2" \
  -d "recipients=+56912345678" \
  -d "tts=Hola Juan, tu pedido número 1001 está listo para retiro."

GET /calls

Lista las llamadas del usuario con paginación.

curl https://api.griito.com/calls \
  -H "Authorization: Bearer YOUR_TOKEN"

GET /calls/{id}

Detalle de una llamada específica. Si es tipo 1 o 3, incluye response_audio con la URL de la grabación de respuesta.

curl https://api.griito.com/calls/101 \
  -H "Authorization: Bearer YOUR_TOKEN"

PATCH /calls/{id}

Modifica una llamada pendiente (ej: reprogramar).

ParámetroTipoDescripción
calldatestringNueva fecha/hora ISO 8601
estadointegerNuevo estado
curl -X PATCH https://api.griito.com/calls/101 \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -d "calldate=2025-03-15T14:00:00Z"

DELETE /calls/{id}

Cancela una llamada específica.

curl -X DELETE https://api.griito.com/calls/101 \
  -H "Authorization: Bearer YOUR_TOKEN"

DELETE /calls

Cancela múltiples llamadas.

ParámetroTipoDescripción
idinteger | arrayID o array de IDs a cancelar
curl -X DELETE https://api.griito.com/calls \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -d "id[]=101" \
  -d "id[]=102" \
  -d "id[]=103"

DELETE /calls/batch/{batch_id}

Cancela todas las llamadas de un batch.

curl -X DELETE https://api.griito.com/calls/batch/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
  -H "Authorization: Bearer YOUR_TOKEN"

DELETE /calls/pending/batch/{batch_id}

Cancela solo las llamadas pendientes (estado 0) de un batch.

curl -X DELETE https://api.griito.com/calls/pending/batch/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
  -H "Authorization: Bearer YOUR_TOKEN"

Envío masivo (batch)

Para enviar llamadas a múltiples destinatarios en una sola solicitud, los parámetros recipients, audio/tts, abrid y calltime pueden ser arrays del mismo largo.

Importante: Todos los arrays deben tener exactamente la misma cantidad de elementos. Cada posición del array corresponde a un destinatario.

Ejemplo — Envío masivo TTS personalizado a 3 destinatarios:

curl -X POST https://api.griito.com/calls \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -d "type=2" \
  -d "recipients[]=+56911111111" \
  -d "recipients[]=+56922222222" \
  -d "recipients[]=+56933333333" \
  -d "tts[]=Hola María, tu cita es mañana a las 10." \
  -d "tts[]=Hola Pedro, tu cita es mañana a las 11." \
  -d "tts[]=Hola Ana, tu cita es mañana a las 12." \
  -d "abrid[]=cita_maria" \
  -d "abrid[]=cita_pedro" \
  -d "abrid[]=cita_ana" \
  -d "batch_name=recordatorio_citas"

Response

{
  "success": true,
  "text": "Mensaje(s) Ingresado",
  "data": [201, 202, 203],
  "batch_id": "f1e2d3c4-b5a6-7890-fedc-ba0987654321"
}

Programación de llamadas

Parámetro calltime

Permite programar una llamada para una fecha y hora futura. Usa formato ISO 8601.

# Llamada programada para el 15 de marzo 2025 a las 14:00 UTC
-d "calltime=2025-03-15T14:00:00Z"

# Con zona horaria específica
-d "calltime=2025-03-15T11:00:00" \
-d "timezone=America/Santiago"

Parámetro timezone

Define la zona horaria para interpretar calltime. Por defecto es UTC. Acepta cualquier zona IANA válida (ej: America/Santiago, America/Mexico_City, Europe/Madrid).

Restricciones horarias

Las llamadas tienen restricciones de horario para proteger a los destinatarios. Si intentas crear una llamada fuera del horario permitido:

Códigos de error

Cuando una solicitud falla, la respuesta incluye un código numérico y un mensaje descriptivo.

{
  "success": false,
  "error_code": 22,
  "text": "Sin créditos disponibles"
}
CódigoDescripción
7Formato de contraseña inválido (mínimo 6 caracteres)
15Spam detectado
17Faltan datos fundamentales
22Sin créditos
23Créditos insuficientes
24Código de validación no coincide
28Demasiados destinatarios
30Credenciales incorrectas para recuperar contraseña
31Credenciales de cliente incorrectas
34recipients y abrid deben tener igual largo
35recipients y tts deben tener igual largo
42Costo no encontrado para el tipo
45No puedes llamarte a ti mismo
48TTS máximo 500 caracteres
52Llamada en horario restringido
53Teléfono mínimo 9 dígitos
58Audio no encontrado
65recipients y audio deben tener igual largo
68recipients y calltime deben tener igual largo

Ejemplos completos

Flujos completos de integración en distintos lenguajes.

Flujo completo: Auth → Subir audio → Llamada tipo 0

# 1. Obtener token
TOKEN=$(curl -s -X POST https://api.griito.com/oauth/token \
  -d "grant_type=password" \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "client_secret=YOUR_CLIENT_SECRET" \
  -d "username=juan@ejemplo.com" \
  -d "password=mi_password" \
  -d "scope=*" | jq -r '.access_token')

echo "Token: $TOKEN"

# 2. Subir audio
AUDIO_ID=$(curl -s -X POST https://api.griito.com/audios \
  -H "Authorization: Bearer $TOKEN" \
  -F "audio=@/ruta/a/mi_audio.mp3" \
  -F "name=aviso_despacho" \
  -F "description=Aviso de despacho de pedido" | jq -r '.data.id')

echo "Audio ID: $AUDIO_ID"

# 3. Crear llamada tipo 0
curl -X POST https://api.griito.com/calls \
  -H "Authorization: Bearer $TOKEN" \
  -d "type=0" \
  -d "recipients=+56912345678" \
  -d "audio=$AUDIO_ID" \
  -d "abrid=pedido_5001"
import requests

BASE = "https://api.griito.com"

# 1. Obtener token
token_resp = requests.post(f"{BASE}/oauth/token", data={
    "grant_type": "password",
    "client_id": "YOUR_CLIENT_ID",
    "client_secret": "YOUR_CLIENT_SECRET",
    "username": "juan@ejemplo.com",
    "password": "mi_password",
    "scope": "*"
})
token = token_resp.json()["access_token"]
headers = {"Authorization": f"Bearer {token}"}

# 2. Subir audio
with open("/ruta/a/mi_audio.mp3", "rb") as f:
    audio_resp = requests.post(f"{BASE}/audios", headers=headers,
        files={"audio": f},
        data={"name": "aviso_despacho", "description": "Aviso de despacho"}
    )
audio_id = audio_resp.json()["data"]["id"]
print(f"Audio ID: {audio_id}")

# 3. Crear llamada tipo 0
call_resp = requests.post(f"{BASE}/calls", headers=headers, data={
    "type": 0,
    "recipients": "+56912345678",
    "audio": audio_id,
    "abrid": "pedido_5001"
})
print(call_resp.json())
<?php
$base = "https://api.griito.com";

// 1. Obtener token
$ch = curl_init("$base/oauth/token");
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POSTFIELDS => http_build_query([
        "grant_type"    => "password",
        "client_id"     => "YOUR_CLIENT_ID",
        "client_secret" => "YOUR_CLIENT_SECRET",
        "username"      => "juan@ejemplo.com",
        "password"      => "mi_password",
        "scope"         => "*"
    ])
]);
$token = json_decode(curl_exec($ch), true)["access_token"];
curl_close($ch);

// 2. Subir audio
$ch = curl_init("$base/audios");
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ["Authorization: Bearer $token"],
    CURLOPT_POSTFIELDS => [
        "audio"       => new CURLFile("/ruta/a/mi_audio.mp3"),
        "name"        => "aviso_despacho",
        "description" => "Aviso de despacho"
    ]
]);
$audioId = json_decode(curl_exec($ch), true)["data"]["id"];
curl_close($ch);

// 3. Crear llamada tipo 0
$ch = curl_init("$base/calls");
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ["Authorization: Bearer $token"],
    CURLOPT_POSTFIELDS => http_build_query([
        "type"       => 0,
        "recipients" => "+56912345678",
        "audio"      => $audioId,
        "abrid"      => "pedido_5001"
    ])
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);

print_r($result);
const BASE = "https://api.griito.com";
const fs = require("fs");

async function main() {
  // 1. Obtener token
  const tokenResp = await fetch(`${BASE}/oauth/token`, {
    method: "POST",
    headers: { "Content-Type": "application/x-www-form-urlencoded" },
    body: new URLSearchParams({
      grant_type: "password",
      client_id: "YOUR_CLIENT_ID",
      client_secret: "YOUR_CLIENT_SECRET",
      username: "juan@ejemplo.com",
      password: "mi_password",
      scope: "*"
    })
  });
  const { access_token: token } = await tokenResp.json();
  const headers = { Authorization: `Bearer ${token}` };

  // 2. Subir audio
  const form = new FormData();
  form.append("audio", new Blob([fs.readFileSync("/ruta/a/mi_audio.mp3")]), "mi_audio.mp3");
  form.append("name", "aviso_despacho");
  form.append("description", "Aviso de despacho");

  const audioResp = await fetch(`${BASE}/audios`, {
    method: "POST", headers, body: form
  });
  const { data: { id: audioId } } = await audioResp.json();
  console.log("Audio ID:", audioId);

  // 3. Crear llamada tipo 0
  const callResp = await fetch(`${BASE}/calls`, {
    method: "POST",
    headers: { ...headers, "Content-Type": "application/x-www-form-urlencoded" },
    body: new URLSearchParams({
      type: "0",
      recipients: "+56912345678",
      audio: String(audioId),
      abrid: "pedido_5001"
    })
  });
  console.log(await callResp.json());
}

main();

Ejemplo rápido: Llamada TTS (tipo 2, sin subir audio)

# Llamada TTS directa (asumiendo que ya tienes el token)
curl -X POST https://api.griito.com/calls \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -d "type=2" \
  -d "recipients=+56912345678" \
  -d "tts=Hola, le informamos que su pedido ha sido despachado y llegará mañana entre las 9 y las 13 horas." \
  -d "abrid=despacho_5001"
import requests

resp = requests.post("https://api.griito.com/calls",
    headers={"Authorization": "Bearer YOUR_TOKEN"},
    data={
        "type": 2,
        "recipients": "+56912345678",
        "tts": "Hola, le informamos que su pedido ha sido despachado y llegará mañana entre las 9 y las 13 horas.",
        "abrid": "despacho_5001"
    }
)
print(resp.json())
<?php
$ch = curl_init("https://api.griito.com/calls");
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ["Authorization: Bearer YOUR_TOKEN"],
    CURLOPT_POSTFIELDS => http_build_query([
        "type"       => 2,
        "recipients" => "+56912345678",
        "tts"        => "Hola, le informamos que su pedido ha sido despachado y llegará mañana entre las 9 y las 13 horas.",
        "abrid"      => "despacho_5001"
    ])
]);
print_r(json_decode(curl_exec($ch), true));
curl_close($ch);
const resp = await fetch("https://api.griito.com/calls", {
  method: "POST",
  headers: {
    "Authorization": "Bearer YOUR_TOKEN",
    "Content-Type": "application/x-www-form-urlencoded"
  },
  body: new URLSearchParams({
    type: "2",
    recipients: "+56912345678",
    tts: "Hola, le informamos que su pedido ha sido despachado y llegará mañana entre las 9 y las 13 horas.",
    abrid: "despacho_5001"
  })
});
console.log(await resp.json());