Saltar al contenido principal

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 en retryAfter antes 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:

ParametroTipoPor defectoDescripcion
limitinteger50Resultados por pagina (maximo 100)
offsetinteger0Numero 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:

CampoTipoDescripcion
clientNamestringNombre del cliente
itemsarrayLista de lineas de la factura

Campos opcionales:

CampoTipoDescripcion
statusstringEstado (draft, sent, paid)
dueDatestringFecha de vencimiento (ISO 8601)
notesstringNotas internas
taxRatenumberTipo 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:

CampoTipoDescripcion
descriptionstringDescripcion del gasto
amountnumberImporte del gasto

Campos opcionales:

CampoTipoDescripcion
categorystringCategoria del gasto
datestringFecha del gasto (ISO 8601)
vendorstringProveedor
taxDeductiblebooleanSi 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:

CampoTipoDescripcion
namestringNombre del cliente

Campos opcionales:

CampoTipoDescripcion
emailstringEmail de contacto
phonestringTelefono
taxIdstringNIF/CIF
addressobjectDireccion (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:

CampoTipoDescripcion
namestringNombre del producto o servicio
unitPricenumberPrecio unitario

Campos opcionales:

CampoTipoDescripcion
descriptionstringDescripcion
unitstringUnidad de medida (hora, unidad, mes)
taxRatenumberTipo de IVA aplicable
skustringReferencia 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:

CampoTipoDescripcion
clientNamestringNombre del cliente
itemsarrayLineas del presupuesto

Campos opcionales:

CampoTipoDescripcion
validUntilstringFecha de validez (ISO 8601)
notesstringNotas o condiciones
statusstringEstado (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.

CodigoSignificadoDescripcion
400Bad RequestFalta un campo requerido o el formato de los datos es incorrecto
401UnauthorizedLa API key no se ha proporcionado, es invalida o ha expirado
403ForbiddenLa API key no tiene permisos para acceder a este recurso
404Not FoundEl recurso solicitado no existe
405Method Not AllowedEl metodo HTTP no esta soportado para este endpoint
413Payload Too LargeEl cuerpo de la peticion excede 1 MB
429Too Many RequestsSe ha excedido el limite de 100 peticiones por minuto
500Internal Server ErrorError 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 disponibles
  • limit: 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.io
  • https://frihet.io
  • https://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

  1. Almacena la API key de forma segura. Nunca la incluyas en codigo frontend, repositorios publicos o logs.
  2. Gestiona el rate limiting. Implementa backoff exponencial si recibes un 429.
  3. Usa paginacion. No pidas todos los registros de golpe; itera con limit y offset.
  4. Verifica los codigos de respuesta. No asumas que todas las peticiones seran exitosas.
  5. Rota las claves periodicamente. Crea una nueva clave, actualiza tu integracion y revoca la anterior.
  6. Usa HTTPS siempre. Todas las peticiones a la API deben ser sobre HTTPS.