API Keys
Live vs Test keys, idempotency, dry run, mejores prácticas de seguridad.
ReallyQuickEmails utiliza Secret Keys con prefijo para autenticar todas las solicitudes a la API. Cada proyecto tiene dos keys distintas: una para tráfico productivo (Live) y otra para desarrollo (Test).
Live vs Test
| Modo | Prefijo | Cuándo usarla | Comportamiento |
|---|---|---|---|
| Live | sk_proj_* o sk_live_* | Tráfico productivo: clientes reales, emails reales, métricas reales | Cuenta contra tu cuota mensual. Webhook outbound dispara a webhook_url. Inbound replies a inbound_webhook_url. |
| Test | sk_test_* | Desarrollo, staging, sandbox, suites E2E | Envía emails reales vía SES (modelo Resend), pero no consume cuota mensual. Activity queda marcada con is_test=true y se filtra del dashboard. Webhooks van a webhook_url_dev / inbound_webhook_url_dev. |
sk_proj_*es el prefijo histórico (legacy live). Funciona idéntico ask_live_*— ambos son modo live. Las nuevas keys generadas usansk_live_*por consistencia, pero lassk_proj_*existentes siguen siendo válidas indefinidamente.
Comportamiento detallado de Test Mode
Las keys sk_test_* te permiten desarrollar e iterar sin contaminar tus métricas productivas:
- Envíos reales vía SES: el email llega al inbox del destinatario igual que en live. Esto es deliberado para que pruebes deliverability, render visual y comportamiento de los clientes de email.
- Skip de counters/quota: el envío no incrementa
emails_sent_totaldel proyecto ni cuenta contra el límite mensual del plan. - Activity con
is_test=true: cada send queda registrado en la tabla de actividad con la flagis_test. El dashboard filtra estos registros automáticamente cuando el toggle Live/Test está en modo Live. - Webhooks separados: tanto los eventos outbound (delivered, bounced, opened, clicked) como los inbound replies se enrutan a las URLs
*_dev. Si la URL_devno está configurada, el evento simplemente no se entrega — no se hace fallback alwebhook_urlde live. - Toggle en dashboard: el sidebar tiene un switch global Live/Test que filtra Activity, Campaigns y métricas según el modo seleccionado.
Donde encontrar tus Secret Keys
- Ingresa al dashboard de ReallyQuickEmails.
- Navega al proyecto donde deseas obtener las credenciales.
- Abre Configuración → Integraciones.
- En la sección API Keys encontrarás:
- Producción (Live) —
sk_live_*(osk_proj_*si fue creada antes de la migración). - Test —
sk_test_*. Generable/regenerable independientemente de la live.
- Producción (Live) —
Cada key tiene controles separados de mostrar/copiar/regenerar. Regenerar la live no afecta la test, y viceversa.
Uso
Pasa la key como Bearer token en el header Authorization:
Authorization: Bearer sk_live_tu_secret_key# Live
curl -X POST https://api.reallyquickemails.com/v1/send-email \
-H "Authorization: Bearer sk_live_tu_secret_key" \
-H "Content-Type: application/json" \
-d '{
"recipient_email": "destinatario@ejemplo.com",
"sender_email": "noreply@tudominio.com",
"subject": "Hola",
"html_body": "<h1>Hola!</h1>"
}'
# Test (mismo endpoint, solo cambia el prefijo de la key)
curl -X POST https://api.reallyquickemails.com/v1/send-email \
-H "Authorization: Bearer sk_test_tu_test_key" \
-H "Content-Type: application/json" \
-d '{
"recipient_email": "qa@tudominio.com",
"sender_email": "noreply@tudominio.com",
"subject": "Smoke test",
"html_body": "<p>Test desde staging</p>"
}'Importante: todos los endpoints de la API aceptan ambos prefijos. El backend determina el modo del envío únicamente por el prefijo de la key — no existe un parámetro
modeni headers especiales para forzar un modo distinto.
Errores de prefijo inválido
Si pasas una key con un prefijo desconocido (ej. sk_dev_, pk_*, etc.), recibes:
HTTP 401 Unauthorized
{ "error": "Invalid API key prefix. Expected sk_proj_*, sk_live_* or sk_test_*." }Idempotency
Todos los endpoints de envío (/v1/send-email, /v1/send-batch, /v1/send-template-email) soportan idempotencia opcional vía header Idempotency-Key:
Idempotency-Key: cualquier-string-único-tuyo-max-128-chars- Un request con
Idempotency-Keyse cachea en Redis por 24 horas, scoped a(project_id, idempotency_key). - Si llega un request idéntico con la misma key dentro de la ventana, RQE devuelve la respuesta cacheada del primer request, con header
Idempotency-Replayed: true. - Útil para retries de red sin riesgo de doble envío. Funciona idéntico en live y test.
- Fail-open: si Redis está caído, el request procesa normalmente sin idempotencia.
Dry Run
Para validar payload + variables sin enviar el email, agrega dry_run: true al body:
curl -X POST https://api.reallyquickemails.com/v1/send-email \
-H "Authorization: Bearer sk_test_tu_test_key" \
-H "Content-Type: application/json" \
-d '{
"recipient_email": "destinatario@ejemplo.com",
"sender_email": "noreply@tudominio.com",
"subject": "Hola {{nombre}}",
"html_body": "<h1>Hola {{nombre}}</h1>",
"data": { "nombre": "María" },
"dry_run": true
}'Respuesta:
{
"dry_run": true,
"test_mode": true,
"would_send": {
"to": ["destinatario@ejemplo.com"],
"from": "noreply@tudominio.com",
"subject": "Hola María",
"html_preview": "<h1>Hola María</h1>",
"variables_used": ["nombre"]
}
}No se toca SES, no se encola job, no se inserta activity. Útil para CI o validar templates antes de un blast.
Seguridad
- Nunca expongas tus Secret Keys en código del lado del cliente (frontend, apps móviles, repos públicos). Las keys deben usarse exclusivamente desde backend.
- Variables de entorno — almacena en
.env, nunca hardcodeadas:
# .env
RQE_LIVE_KEY=sk_live_tu_secret_key
RQE_TEST_KEY=sk_test_tu_test_key// Ejemplo Node.js — usar la key correcta según el ambiente
const apiKey = process.env.NODE_ENV === 'production'
? process.env.RQE_LIVE_KEY
: process.env.RQE_TEST_KEY;
const response = await fetch("https://api.reallyquickemails.com/v1/send-email", {
method: "POST",
headers: {
"Authorization": `Bearer ${apiKey}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
recipient_email: "cliente@ejemplo.com",
sender_email: "noreply@tudominio.com",
subject: "Hola",
html_body: "<h1>Hola!</h1>",
}),
});- Rota tus keys periódicamente. Si sospechas que una fue comprometida, regenera desde el dashboard inmediatamente. La key anterior queda invalidada en el momento.
- Agrega
.enva tu.gitignorepara evitar que las credenciales se suban al repositorio. - Mantén live y test aisladas entre ambientes. Pasar accidentalmente la
sk_live_*en staging puede contaminar métricas y consumir cuota.