# Credenciales y firma (https://devs.firmame.com/docs/autenticacion)

> Cómo obtener tus credenciales y cómo se arma el encabezado de autenticación de cada petición.

## Credenciales [#credenciales]

Tu cuenta tiene un par de credenciales de desarrollador. Si todavía no las tienes a la mano, debes poder generarlas dando click en tu usuario en el portal de Administración de usuarios de la cuenta. Si no tienes acceso a este portal, solicita las credenciales a tu administrador de cuetna

**Si no tienes cuenta, puedes obtener credenciales de prueba gratuitas**. Sólo envía un correo a [contacto@firmamex.com](mailto:contacto@firmamex.com).

|             | Qué es                                       | Cómo tratarla                                                                  |
| ----------- | -------------------------------------------- | ------------------------------------------------------------------------------ |
| **Web ID**  | Tu identificador público                     | Puede ir en configuración, en el repositorio, donde sea                        |
| **API key** | El secreto con el que se firma cada petición | Trátala como una contraseña: autoriza a solicitar firmas a nombre de tu cuenta |

Carga las dos desde variables de ambiente o desde tu gestor de secretos, nunca escritas en el código:

```js
const services = FirmamexServices(
  process.env.FIRMAME_WEB_ID,
  process.env.FIRMAME_API_KEY,
);
```

## Con un SDK [#con-un-sdk]

Es el camino corto: le pasas las credenciales al SDK y él arma la firma de cada petición.

Hay SDK para [Node, TypeScript, PHP, Python, .NET y Java](/docs/sdks). Si tu lenguaje no está en la lista puedes llamar a la API directamente:

## Directo contra la API [#directo-contra-la-api]

Cada petición lleva un encabezado `Authorization` con esta forma:

<Mermaid
  chart="graph LR
    A["signmage"] --> B["TU_WEB_ID"]
    B --> C[":"]
    C --> D["base64 del HMAC-SHA256"]

    style A fill:#0b66c9,color:#fff
    style B fill:#0b66c9,color:#fff
    style C fill:#64748b,color:#fff
    style D fill:#0b66c9,color:#fff"
/>

```
Authorization: signmage TU_WEB_ID:PWJhc2U2NCBkZWwgSE1BQz4=
Content-Type: application/json
```

La firma es `base64(HMAC-SHA256(TU_API_KEY, cadenaFirmada))`. Lo único que cambia entre peticiones es qué
va dentro de `cadenaFirmada`:

| Petición         | `cadenaFirmada`                                                                     |
| ---------------- | ----------------------------------------------------------------------------------- |
| `GET`            | La URI completa **incluyendo el query string**, exactamente como se envía           |
| `POST` con JSON  | El cuerpo JSON, re-serializado compacto (sin espacios ni salto de línea final)      |
| `POST` multipart | El SHA-256 en Base64 del archivo, que además se manda en el header `Content-SHA256` |

Dos temas importantes:

1. En `GET`, la URI se firma tal como se envía, así que **el orden y el encoding de los parámetros
   importan**. Construye la URL una sola vez y firma esa misma cadena.
2. En `POST`, la comparación se hace contra tu JSON re-serializado en forma compacta. Serializa una vez,
   firma esa cadena, y **manda exactamente esos bytes**.

### Ejemplo completo [#ejemplo-completo]

```js
import { createHmac } from 'node:crypto';

const WEB_ID = process.env.FIRMAME_WEB_ID;
const API_KEY = process.env.FIRMAME_API_KEY;

function authorization(signedString) {
  const hmac = createHmac('sha256', API_KEY).update(signedString, 'utf8').digest('base64');
  return `signmage ${WEB_ID}:${hmac}`;
}

// POST: se firma el cuerpo compacto, y se manda ese mismo cuerpo.
const body = JSON.stringify({
  url_doc: { url: 'https://ejemplo.com/contrato.pdf', name: 'contrato.pdf' },
  stickers: [
    {
      authority: 'EMAIL_LINK',
      data: 'firmante@dominio.com',
      page: 0,
      rect: { lx: 330, ly: 300, tx: 530, ty: 400 },
    },
  ],
});

await fetch('https://app.firmame.com/developers/json', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json', Authorization: authorization(body) },
  body,
});

// GET: se firma la ruta con su query string, tal cual.
const path = '/api/document?from=1640995200000&to=1641945600000';

await fetch(`https://app.firmame.com${path}`, {
  headers: { Authorization: authorization(path) },
});
```

<Callout>
  Si recibes un `401`, la guía de [errores 401](/docs/autenticacion/errores-401) recorre las causas
  posibles en orden.
</Callout>
