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

# Firma de solicitudes

> HMAC-SHA256 para la API de integraciones

Además del Bearer, cada request a `/integrations/v1` debe incluir una firma HMAC-SHA256 calculada con la misma llave API.

## Headers

```http theme={null}
Cobrix-Timestamp: 1784044800
Cobrix-Signature: v1=HEXADECIMAL_HMAC_SHA256
```

`Cobrix-Timestamp` usa segundos Unix y debe estar dentro de una ventana de cinco minutos.

## Cadena firmada

```text theme={null}
{timestamp}.{METHOD}.{path_with_query}.{raw_body}
```

* `METHOD` en mayúsculas.
* `path_with_query` comienza en `/integrations/v1` e incluye el query string en su orden original.
* `raw_body` es el cuerpo exacto enviado. En `GET` es una cadena vacía.
* La firma se envía como `v1={hex}`.

```javascript Node.js theme={null}
import crypto from 'node:crypto'

function signRequest({ secret, timestamp, method, path, rawBody = '' }) {
  const payload = `${timestamp}.${method.toUpperCase()}.${path}.${rawBody}`
  const signature = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex')
  return `v1=${signature}`
}
```

```python Python theme={null}
import hashlib, hmac

def sign_request(secret, timestamp, method, path, raw_body=''):
    payload = f'{timestamp}.{method.upper()}.{path}.{raw_body}'
    digest = hmac.new(secret.encode(), payload.encode(), hashlib.sha256).hexdigest()
    return f'v1={digest}'
```

## Errores de firma

| Código                       | Causa                                          |
| ---------------------------- | ---------------------------------------------- |
| `missing_timestamp`          | No se envió `Cobrix-Timestamp`.                |
| `timestamp_out_of_tolerance` | El timestamp está fuera de cinco minutos.      |
| `missing_signature`          | No se envió una firma `v1`.                    |
| `invalid_signature`          | El método, ruta, cuerpo o secreto no coincide. |

<Warning>
  Firma el JSON antes de enviarlo y usa ese mismo texto como body. Volver a serializarlo puede cambiar espacios u orden y producir una firma inválida.
</Warning>
