cURL
Enviar correo en texto plano
curl -X POST "https://api.yolani.co/api/mail/v1/miempresa.com/messages" \
-H "Authorization: Bearer yk-TU_API_KEY_AQUI" \
-F "from=ventas@miempresa.com" \
-F "to=cliente@ejemplo.com" \
-F "subject=Confirmación de pedido" \
-F "text=Gracias por tu compra. Tu pedido ha sido recibido correctamente."
Enviar correo con adjunto
curl -X POST "https://api.yolani.co/api/mail/v1/miempresa.com/messages" \
-H "Authorization: Bearer yk-TU_API_KEY_AQUI" \
-F "from=Nombre <ventas@miempresa.com>" \
-F "to=cliente@ejemplo.com" \
-F "subject=Factura adjunta" \
-F "text=Adjunto encontrará su factura en PDF." \
-F "attachments=@/ruta/al/archivo/factura.pdf"
JavaScript / Node.js
const API_KEY = process.env.YOLANI_API_KEY;
const DOMAIN = 'miempresa.com';
async function enviarCorreo({ from, to, subject, text, html, attachments }) {
const formData = new FormData();
formData.append('from', from);
formData.append('to', to);
formData.append('subject', subject);
if (text) formData.append('text', text);
if (html) formData.append('html', html);
if (attachments?.length) {
for (const file of attachments) {
formData.append('attachments', file);
}
}
const response = await fetch(
`https://api.yolani.co/api/mail/v1/${DOMAIN}/messages`,
{
method: 'POST',
headers: {
Authorization: `Bearer ${API_KEY}`,
},
body: formData,
}
);
const data = await response.json();
if (!response.ok) {
throw new Error(data.error || `Error ${response.status}`);
}
return data;
}
// Uso: texto plano
enviarCorreo({
from: 'ventas@miempresa.com',
to: 'cliente@ejemplo.com',
subject: 'Confirmación de pedido',
text: 'Gracias por tu compra.',
})
.then((res) => console.log('Enviado:', res.id))
.catch((err) => console.error('Error:', err.message));
// Uso: con HTML
enviarCorreo({
from: 'ventas@miempresa.com',
to: 'cliente@ejemplo.com',
subject: 'Bienvenido',
html: '<h1>Bienvenido</h1><p>Gracias por registrarte.</p>',
})
.then((res) => console.log('Enviado:', res.id))
.catch((err) => console.error('Error:', err.message));
Python
import os
import requests
API_KEY = os.environ.get('YOLANI_API_KEY')
DOMAIN = 'miempresa.com'
BASE_URL = f'https://api.yolani.co/api/mail/v1/{DOMAIN}/messages'
def enviar_correo(from_addr, to_addr, subject, text=None, html=None, attachments=None):
headers = {
'Authorization': f'Bearer {API_KEY}'
}
data = {
'from': from_addr,
'to': to_addr,
'subject': subject,
}
if text:
data['text'] = text
if html:
data['html'] = html
files = []
if attachments:
for f in attachments:
files.append(('attachments', (os.path.basename(f), open(f, 'rb'))))
try:
response = requests.post(
BASE_URL,
headers=headers,
data=data,
files=files if files else None
)
result = response.json()
if response.status_code == 200:
return result
else:
raise Exception(result.get('error', f'Error {response.status_code}'))
finally:
for _, (_, f) in files:
f.close()
# Uso: texto plano
try:
res = enviar_correo(
from_addr='ventas@miempresa.com',
to_addr='cliente@ejemplo.com',
subject='Confirmación de pedido',
text='Gracias por tu compra.'
)
print('Enviado:', res['id'])
except Exception as e:
print('Error:', e)
# Uso: con adjunto
try:
res = enviar_correo(
from_addr='ventas@miempresa.com',
to_addr='cliente@ejemplo.com',
subject='Factura adjunta',
text='Adjunto encontrará su factura.',
attachments=['/ruta/factura.pdf']
)
print('Enviado:', res['id'])
except Exception as e:
print('Error:', e)
Manejo de errores
Independientemente del lenguaje, conviene manejar los códigos de error más comunes:
| Código | Acción sugerida |
|---|---|
| 400 | Revisar que from, to, subject y text/html estén presentes y sean válidos |
| 401 | Verificar que la API key sea correcta y no esté revocada |
| 403 | Confirmar que el dominio en la URL coincida con el dominio de la API key |
| 429 | Implementar backoff y reintentos; reducir la frecuencia de envío |
| 500 | Reintentar más tarde; si persiste, contactar soporte |