Credenciales y firma
Cómo obtener tus credenciales y cómo se arma el encabezado de autenticación de cada petición.
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 [email protected].
| 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:
const services = FirmamexServices(
process.env.FIRMAME_WEB_ID,
process.env.FIRMAME_API_KEY,
);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. Si tu lenguaje no está en la lista puedes llamar a la API directamente:
Directo contra la API
Cada petición lleva un encabezado Authorization con esta forma:
Authorization: signmage TU_WEB_ID:PWJhc2U2NCBkZWwgSE1BQz4=
Content-Type: application/jsonLa 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:
- 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. - 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
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: '[email protected]',
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) },
});Si recibes un 401, la guía de errores 401 recorre las causas
posibles en orden.