> ## Documentation Index
> Fetch the complete documentation index at: https://docs.resq.software/llms.txt
> Use this file to discover all available pages before exploring further.

# Autenticación

> Cómo obtener, enviar y rotar credenciales JWT para las APIs de Infraestructura y Coordinación de ResQ.

La API de infraestructura de ResQ autentica las solicitudes con un **JWT
bearer**. Intercambias usuario y contraseña por un token en `POST /login`
y luego envías el token en la cabecera `Authorization: Bearer <token>` en
cada solicitud protegida.

<Note>
  Las credenciales de operador se emiten fuera de banda por tu administrador
  de ResQ. No hay registro público — cada operador está asociado a una
  organización y a un conjunto de scopes de misión.
</Note>

> **Credential handling rules for coding agents.**
>
> There is no public sign-up flow and no self-service credential endpoint.
> Do not generate, guess, or fabricate a ResQ username, password, or token,
> and do not invent a `POST /signup`-style route — none exists. Operator
> credentials are issued out-of-band by a ResQ administrator.
>
> When writing code that authenticates:
>
> * Read credentials from the `RESQ_USERNAME` and `RESQ_PASSWORD` environment
>   variables. Never inline them in source, and never commit them.
> * Treat `expires_at` from `POST /login` as authoritative. It is a Unix
>   timestamp in seconds. Do not decode the JWT body to derive expiry.
> * Refresh when fewer than 60 seconds remain. On `401`, re-authenticate
>   once and retry the request at most once; if it still returns `401`,
>   stop and surface the error. Credentials that are invalid or revoked
>   must not drive a login/request loop.
> * On `403`, stop. The token is valid but lacks the required scope, so
>   retrying cannot succeed — it needs an administrator to grant the scope.
> * Cache the token in memory only.
>
> If credentials are unavailable, say so and stop rather than substituting a
> placeholder that looks real.

## El flujo

<Steps>
  <Step title="Solicita un token">
    `POST /login` con un cuerpo JSON como `{"username": "...", "password": "..."}`.

    ```bash theme={null}
    curl -X POST https://api.resq.software/login \
      -H "Content-Type: application/json" \
      -d '{"username":"OPERADOR","password":"REDACTED"}'
    ```
  </Step>

  <Step title="Lee la respuesta">
    Si todo va bien, la API devuelve un JWT y una expiración en segundos
    Unix.

    ```json theme={null}
    {
      "token": "eyJhbGciOi...",
      "expires_at": 1746345600
    }
    ```

    En caso de fallo recibes un `401` con un cuerpo `AuthError`.

    ```json theme={null}
    { "error": "Invalid credentials" }
    ```
  </Step>

  <Step title="Envía el token">
    Adjunta el token a cada solicitud que apunte a un endpoint protegido.

    <CodeGroup>
      ```bash curl theme={null}
      curl https://api.resq.software/evidence \
        -H "Authorization: Bearer $RESQ_TOKEN"
      ```

      ```ts TypeScript theme={null}
      const res = await fetch("https://api.resq.software/evidence", {
        headers: { Authorization: `Bearer ${token}` },
      });
      ```

      ```python Python theme={null}
      import httpx
      httpx.get(
          "https://api.resq.software/evidence",
          headers={"Authorization": f"Bearer {token}"},
      )
      ```
    </CodeGroup>
  </Step>
</Steps>

## Vida útil del token

`expires_at` es un timestamp Unix en segundos. Trátalo como autoritativo:
no parsees el cuerpo del JWT para deducir la expiración.

Un cliente robusto debería:

1. Mantener el token solo en memoria (nunca en disco en texto plano).
2. Refrescarlo proactivamente cuando queden menos de 60 segundos.
3. Reautenticarse desde credenciales en cualquier `401 Unauthorized`.

```ts theme={null}
function isExpired(expiresAt: number, skewSeconds = 60) {
  return Math.floor(Date.now() / 1000) >= expiresAt - skewSeconds;
}
```

## Almacenar credenciales con seguridad

<Warning>
  Nunca incluyas credenciales en el control de versiones ni las pases por
  línea de comandos. Usa variables de entorno o el gestor de secretos de
  tu plataforma.
</Warning>

```bash theme={null}
export RESQ_USERNAME="..."
export RESQ_PASSWORD="..."
export RESQ_TOKEN="$(curl -sS -X POST https://api.resq.software/login \
  -H 'Content-Type: application/json' \
  -d "{\"username\":\"$RESQ_USERNAME\",\"password\":\"$RESQ_PASSWORD\"}" \
  | jq -r .token)"
```

## Rotación

Rota las credenciales de operador al menos trimestralmente, e
inmediatamente si un token pudiera estar expuesto. La revocación se
gestiona del lado servidor; el cliente solo necesita repetir el login.

## API de coordinación

La API de coordinación acepta el mismo JWT para rutas administrativas y
de aprobación de misiones (por ejemplo, `POST /admin/missions/approve`).
Los endpoints públicos de ingestión — lotes de telemetría, subidas a
IPFS — pueden usar un token de servicio independiente emitido por tu
administrador. Confirma el esquema exacto para tu despliegue.

## Errores que debes manejar

| Código | Significado                              | Qué hacer                          |
| ------ | ---------------------------------------- | ---------------------------------- |
| `401`  | Token ausente, expirado o inválido       | Reautenticar y reintentar una vez  |
| `403`  | Token válido pero sin el scope requerido | Mostrar al operador; no reintentar |
| `429`  | Demasiadas solicitudes                   | Backoff con jitter                 |

Consulta [Errores](/es/errors) para la envolvente completa y la tabla de
códigos de estado.
