API REST
La API REST de Frihet permite acceder y manipular los recursos de tu cuenta de forma programatica. Toda la comunicacion se realiza sobre HTTPS y las respuestas son JSON.
URL base
https://api.frihet.io/v1
Todos los endpoints descritos en esta pagina son relativos a esta URL base.
Autenticacion
Cada peticion debe incluir una API key en la cabecera X-API-Key. Las claves se crean desde Configuracion > API en el panel de Frihet.
Las claves tienen el prefijo fri_ seguido de 32 bytes aleatorios codificados en base64url. Ejemplo: fri_aBcDeFgHiJkLmNoPqRsTuVwXyZ012345678.
curl https://api.frihet.io/v1/clients \
-H "X-API-Key: fri_tu-clave-aqui"
Alternativamente, puedes enviar la clave como Bearer token en la cabecera Authorization:
curl https://api.frihet.io/v1/clients \
-H "Authorization: Bearer fri_tu-clave-aqui"
Seguridad de las claves
- La clave en texto plano solo se muestra una vez, en el momento de la creacion. No se puede recuperar despues.
- El servidor almacena un hash SHA-256 de la clave. Incluso en caso de brecha de datos, la clave original no es recuperable.
- Puedes crear claves con fecha de expiracion configurable.
- Si sospechas que una clave ha sido comprometida, revocala inmediatamente desde el panel.
Rate limiting
Cada clave API tiene un limite de 100 peticiones por minuto. Si se excede, la API responde con un codigo 429:
{
"error": "Rate limit exceeded",
"message": "Maximum 100 requests per minute",
"retryAfter": 60
}
Cabeceras de respuesta recomendadas para gestionar el limite:
- Si recibes un
429, espera el numero de segundos indicado enretryAfterantes de reintentar. - Distribuye las peticiones en el tiempo en lugar de enviar rafagas.
Tamano de peticion
El cuerpo de las peticiones POST y PUT no puede exceder 1 MB. Peticiones mayores reciben un codigo 413.
Recursos
Facturas (/invoices)
Listar facturas
GET /v1/invoices
Parametros de consulta:
| Parametro | Tipo | Por defecto | Descripcion |
|---|---|---|---|
limit | integer | 50 | Resultados por pagina (maximo 100) |
offset | integer | 0 | Numero de resultados a saltar |
Ejemplo:
curl "https://api.frihet.io/v1/invoices?limit=10&offset=0" \
-H "X-API-Key: fri_tu-clave-aqui"
Respuesta (200):
{
"data": [
{
"id": "abc123",
"clientName": "Acme S.L.",
"items": [
{ "description": "Consultoria", "quantity": 10, "unitPrice": 75 }
],
"status": "paid",
"total": 750,
"createdAt": "2026-01-15T10:30:00.000Z",
"updatedAt": "2026-01-20T14:00:00.000Z"
}
],
"total": 42,
"limit": 10,
"offset": 0
}
Obtener factura
GET /v1/invoices/:id
curl https://api.frihet.io/v1/invoices/abc123 \
-H "X-API-Key: fri_tu-clave-aqui"
Respuesta (200):
{
"id": "abc123",
"clientName": "Acme S.L.",
"items": [
{ "description": "Consultoria", "quantity": 10, "unitPrice": 75 }
],
"status": "paid",
"total": 750,
"createdAt": "2026-01-15T10:30:00.000Z",
"updatedAt": "2026-01-20T14:00:00.000Z"
}
Crear factura
POST /v1/invoices
Campos requeridos:
| Campo | Tipo | Descripcion |
|---|---|---|
clientName | string | Nombre del cliente |
items | array | Lista de lineas de la factura |
Campos opcionales:
| Campo | Tipo | Descripcion |
|---|---|---|
status | string | Estado (draft, sent, paid) |
dueDate | string | Fecha de vencimiento (ISO 8601) |
notes | string | Notas internas |
taxRate | number | Tipo de IVA aplicable |
curl -X POST https://api.frihet.io/v1/invoices \
-H "X-API-Key: fri_tu-clave-aqui" \
-H "Content-Type: application/json" \
-d '{
"clientName": "Acme S.L.",
"items": [
{ "description": "Desarrollo web", "quantity": 40, "unitPrice": 60 }
],
"dueDate": "2026-03-01T00:00:00.000Z",
"notes": "Proyecto Q1 2026"
}'
Respuesta (201):
{
"id": "def456",
"clientName": "Acme S.L.",
"items": [
{ "description": "Desarrollo web", "quantity": 40, "unitPrice": 60 }
],
"dueDate": "2026-03-01T00:00:00.000Z",
"notes": "Proyecto Q1 2026",
"createdAt": "2026-02-12T09:00:00.000Z",
"updatedAt": "2026-02-12T09:00:00.000Z"
}
Actualizar factura
PUT /v1/invoices/:id
curl -X PUT https://api.frihet.io/v1/invoices/def456 \
-H "X-API-Key: fri_tu-clave-aqui" \
-H "Content-Type: application/json" \
-d '{
"clientName": "Acme S.L.",
"items": [
{ "description": "Desarrollo web", "quantity": 40, "unitPrice": 65 }
],
"status": "sent"
}'
Respuesta (200): Objeto de factura actualizado.
Eliminar factura
DELETE /v1/invoices/:id
curl -X DELETE https://api.frihet.io/v1/invoices/def456 \
-H "X-API-Key: fri_tu-clave-aqui"
Respuesta: 204 No Content
Gastos (/expenses)
Listar gastos
GET /v1/expenses
Acepta los mismos parametros de paginacion que facturas (limit, offset).
curl "https://api.frihet.io/v1/expenses?limit=20" \
-H "X-API-Key: fri_tu-clave-aqui"
Obtener gasto
GET /v1/expenses/:id
Crear gasto
POST /v1/expenses
Campos requeridos:
| Campo | Tipo | Descripcion |
|---|---|---|
description | string | Descripcion del gasto |
amount | number | Importe del gasto |
Campos opcionales:
| Campo | Tipo | Descripcion |
|---|---|---|
category | string | Categoria del gasto |
date | string | Fecha del gasto (ISO 8601) |
vendor | string | Proveedor |
taxDeductible | boolean | Si el gasto es deducible |
curl -X POST https://api.frihet.io/v1/expenses \
-H "X-API-Key: fri_tu-clave-aqui" \
-H "Content-Type: application/json" \
-d '{
"description": "Licencia Adobe Creative Cloud",
"amount": 59.99,
"category": "software",
"date": "2026-02-01T00:00:00.000Z",
"taxDeductible": true
}'
Respuesta (201):
{
"id": "exp789",
"description": "Licencia Adobe Creative Cloud",
"amount": 59.99,
"category": "software",
"date": "2026-02-01T00:00:00.000Z",
"taxDeductible": true,
"createdAt": "2026-02-12T09:15:00.000Z",
"updatedAt": "2026-02-12T09:15:00.000Z"
}
Actualizar gasto
PUT /v1/expenses/:id
Eliminar gasto
DELETE /v1/expenses/:id
Clientes (/clients)
Listar clientes
GET /v1/clients
Obtener cliente
GET /v1/clients/:id
Actualizar cliente
PUT /v1/clients/:id
Campos requeridos:
| Campo | Tipo | Descripcion |
|---|---|---|
name | string | Nombre del cliente |
Campos opcionales:
| Campo | Tipo | Descripcion |
|---|---|---|
email | string | Email de contacto |
phone | string | Telefono |
taxId | string | NIF/CIF |
address | object | Direccion (street, city, postalCode, country) |
curl -X PUT https://api.frihet.io/v1/clients/cli001 \
-H "X-API-Key: fri_tu-clave-aqui" \
-H "Content-Type: application/json" \
-d '{
"name": "Acme S.L.",
"email": "admin@acme.es",
"taxId": "B12345678"
}'
Eliminar cliente
DELETE /v1/clients/:id
Productos (/products)
Listar productos
GET /v1/products
Obtener producto
GET /v1/products/:id
Actualizar producto
PUT /v1/products/:id
Campos requeridos:
| Campo | Tipo | Descripcion |
|---|---|---|
name | string | Nombre del producto o servicio |
unitPrice | number | Precio unitario |
Campos opcionales:
| Campo | Tipo | Descripcion |
|---|---|---|
description | string | Descripcion |
unit | string | Unidad de medida (hora, unidad, mes) |
taxRate | number | Tipo de IVA aplicable |
sku | string | Referencia interna |
curl -X PUT https://api.frihet.io/v1/products/prod001 \
-H "X-API-Key: fri_tu-clave-aqui" \
-H "Content-Type: application/json" \
-d '{
"name": "Hora de consultoria",
"unitPrice": 75,
"unit": "hora",
"taxRate": 21
}'
Eliminar producto
DELETE /v1/products/:id
Presupuestos (/quotes)
Listar presupuestos
GET /v1/quotes
Obtener presupuesto
GET /v1/quotes/:id
Actualizar presupuesto
PUT /v1/quotes/:id
Campos requeridos:
| Campo | Tipo | Descripcion |
|---|---|---|
clientName | string | Nombre del cliente |
items | array | Lineas del presupuesto |
Campos opcionales:
| Campo | Tipo | Descripcion |
|---|---|---|
validUntil | string | Fecha de validez (ISO 8601) |
notes | string | Notas o condiciones |
status | string | Estado (draft, sent, accepted, rejected) |
Eliminar presupuesto
DELETE /v1/quotes/:id
Codigos de error
La API utiliza codigos HTTP estandar. Las respuestas de error incluyen un objeto JSON con los campos error y, opcionalmente, message.
| Codigo | Significado | Descripcion |
|---|---|---|
400 | Bad Request | Falta un campo requerido o el formato de los datos es incorrecto |
401 | Unauthorized | La API key no se ha proporcionado, es invalida o ha expirado |
403 | Forbidden | La API key no tiene permisos para acceder a este recurso |
404 | Not Found | El recurso solicitado no existe |
405 | Method Not Allowed | El metodo HTTP no esta soportado para este endpoint |
413 | Payload Too Large | El cuerpo de la peticion excede 1 MB |
429 | Too Many Requests | Se ha excedido el limite de 100 peticiones por minuto |
500 | Internal Server Error | Error interno del servidor |
Ejemplo de respuesta de error:
{
"error": "Invalid or expired API key"
}
Ejemplo con mensaje adicional:
{
"error": "Bad Request",
"message": "Missing required field: clientName"
}
Paginacion
Los endpoints de listado devuelven resultados paginados con la siguiente estructura:
{
"data": [],
"total": 142,
"limit": 50,
"offset": 0
}
total: numero total de registros disponibleslimit: numero de registros devueltos en esta pagina (maximo 100)offset: numero de registros saltados
Para obtener la siguiente pagina:
curl "https://api.frihet.io/v1/invoices?limit=50&offset=50" \
-H "X-API-Key: fri_tu-clave-aqui"
CORS
La API soporta CORS para peticiones desde el navegador. Los origenes permitidos son:
https://app.frihet.iohttps://frihet.iohttps://www.frihet.io
Para integraciones server-to-server, CORS no es relevante. Si necesitas acceder a la API desde un dominio diferente en el navegador, utiliza un proxy en tu backend.
Buenas practicas
- Almacena la API key de forma segura. Nunca la incluyas en codigo frontend, repositorios publicos o logs.
- Gestiona el rate limiting. Implementa backoff exponencial si recibes un
429. - Usa paginacion. No pidas todos los registros de golpe; itera con
limityoffset. - Verifica los codigos de respuesta. No asumas que todas las peticiones seran exitosas.
- Rota las claves periodicamente. Crea una nueva clave, actualiza tu integracion y revoca la anterior.
- Usa HTTPS siempre. Todas las peticiones a la API deben ser sobre HTTPS.