# API Keys

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 a `sk_live_*` — ambos son **modo live**. Las nuevas keys generadas usan `sk_live_*` por consistencia, pero las `sk_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_total` del 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 flag `is_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 `_dev` no está configurada, el evento simplemente no se entrega — **no** se hace fallback al `webhook_url` de 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

1. Ingresa al dashboard de ReallyQuickEmails.
2. Navega al proyecto donde deseas obtener las credenciales.
3. Abre **Configuración → Integraciones**.
4. En la sección **API Keys** encontrarás:
   * **Producción** (Live) — `sk_live_*` (o `sk_proj_*` si fue creada antes de la migración).
   * **Test** — `sk_test_*`. Generable/regenerable independientemente de la 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
```

```bash
# 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 `mode` ni 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:

```json
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-Key` se 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:

```bash
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:

```json
{
  "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:

```bash
# .env
RQE_LIVE_KEY=sk_live_tu_secret_key
RQE_TEST_KEY=sk_test_tu_test_key
```

```javascript
// 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 `.env` a tu `.gitignore`** para 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.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://reallyquickemails.gitbook.io/reallyquickemails-docs/guias/api-keys.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
