RQE Docs
Conceptos

Modos Live y Test

Cómo funciona la separación de tráfico productivo y de desarrollo. Prefijos de keys, routing de webhooks, supresión, idempotency.

ReallyQuickEmails separa tráfico productivo y de desarrollo a través del prefijo de la API key, no de un parámetro del request. Esto evita errores típicos donde un dev olvida un flag y manda emails reales desde staging.

El modelo

LiveTest
Prefijo de keysk_proj_* o sk_live_*sk_test_*
Cuota mensualcuenta normalskip — no consume
Activityis_test=falseis_test=true (filtrable)
Webhook outboundwebhook_urlwebhook_url_dev
Webhook inbound (replies)inbound_webhook_urlinbound_webhook_url_dev
Envío real vía SESsí, también (modelo Resend)
Rate limits SEScomparte cuota AWScomparte cuota AWS
Suppression listcompartecomparte

Test mode SÍ envía emails reales

La elección fue deliberada: queremos que pruebes deliverability, render visual y comportamiento de los clientes de email igual que en producción. La diferencia está en contabilidad y routing, no en el envío en sí.

Cómo se decide el modo

El modo viaja en la key. No hay parámetro mode en el body, ni headers especiales, ni flag por endpoint:

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": "cliente@empresa.com",
    "sender_email": "noreply@tudominio.com",
    "subject": "Confirmación de pedido",
    "html_body": "<p>Tu pedido fue confirmado.</p>"
  }'

req.isTestMode = false → activity con is_test=false → webhook a project.webhook_url

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@empresa.com",
    "sender_email": "noreply@tudominio.com",
    "subject": "QA — confirmación",
    "html_body": "<p>Test desde staging.</p>"
  }'

req.isTestMode = true → activity con is_test=true → webhook a project.webhook_url_dev → skip counter mensual

Webhook routing

Cada proyecto tiene cuatro URLs configurables (en pares outbound/inbound, una para cada modo):

webhook_url — recibe eventos de sk_live_* / sk_proj_*
webhook_url_dev — recibe eventos de sk_test_*
inbound_webhook_url — recibe replies de envíos live
inbound_webhook_url_dev — recibe replies de envíos test

Si la URL _dev está vacía

No hay fallback cross-mode

Si tu proyecto no tiene webhook_url_dev configurada y enviás con sk_test_*, los eventos quedan en DB (tabla email_events, activity con is_test=true) pero no se entregan al webhook_url de live. Es deliberado para evitar contaminar tu sistema productivo con tráfico de pruebas.

is_test en el payload

Todos los webhooks (outbound e inbound) incluyen is_test: boolean en el body. Eso te permite, si querés, recibir todo en una sola URL (webhook_url) y filtrar lado-cliente, dejando webhook_url_dev vacío:

{
  "event": "email.delivered",
  "is_test": true,
  "data": { "...": "..." }
}

Pero mantenerlas separadas es lo recomendado para evitar accidentes operativos.

Caso de uso: setup multi-environment

# .env.local
RQE_API_KEY=sk_test_tu_test_key

Tu app local usa sk_test_. Los emails que mandes durante desarrollo:

  • Llegan al inbox real (testeás render, deliverability)
  • No cuentan contra tu cuota
  • No mezclan métricas con prod
  • Webhooks (si configurás webhook_url_dev apuntando a un ngrok o servicio de testing) funcionan idéntico
# Variables del ambiente staging
RQE_API_KEY=sk_test_tu_test_key

Mismo sk_test_* que local. Tu staging environment manda emails reales pero contabilizados como test. Si tenés webhook listener en tu staging, configurá webhook_url_dev apuntando a esa URL.

# Variables del ambiente prod
RQE_API_KEY=sk_live_tu_live_key

Producción usa sk_live_* (o el legacy sk_proj_*). Cuota mensual cuenta. Webhooks a webhook_url (production listener).

Tu código no necesita saber el modo

La elección de modo es solo cuestión de qué env var lees. Los call sites a la API son idénticos. Esto deja el switch en infra (Render/Vercel envs) y no en código, donde es más fácil olvidar un flag.

Casos extremos

Suppression list

Es compartida entre live y test. Si un destinatario se dio de baja por un envío live, los envíos test al mismo recipient también se omiten (response 200 con skipped: true). Esto previene que tests de QA reactiven la entrega a usuarios que ya no quieren tus emails.

Rate limits SES

Live y test comparten la cuota AWS de tu cuenta SES (16/seg, 106k/día por default). Un spike de tests también afecta tu envío productivo.

Regenerar keys

Live y test se regeneran independientemente desde el dashboard. Regenerar la live no afecta la test, y viceversa. La key anterior queda invalidada al instante.

Próximos pasos

  • API Keys — referencia completa con ejemplos de idempotency y dry-run.
  • Webhooks — formato de payload y verificación HMAC.
  • Quickstart — primer envío end-to-end con sk_test_*.

On this page