REST-API
Frihet REST-API lar deg programmatisk få tilgang til og manipulere kontoens ressurser. All kommunikasjon foregår over HTTPS og svarene er JSON.
Base-URL
https://api.frihet.io/v1
Alle endepunktene beskrevet på denne siden er relative til denne base-URL-en.
Oppdagelse: En GET-forespørsel til roten (https://api.frihet.io/) returnerer hovedlenkene uten behov for autentisering:
{
"name": "Frihet API",
"version": "1.0.0",
"docs": "https://docs.frihet.io/desarrolladores/api-rest",
"openapi": "https://api.frihet.io/openapi.yaml",
"mcp": "https://mcp.frihet.io",
"status": "https://status.frihet.io"
}
OpenAPI 3.1-spesifikasjonen er tilgjengelig på https://api.frihet.io/openapi.yaml.
Hvis du bruker TypeScript eller JavaScript, forenkler den offisielle SDK-en integrasjonen:
npm install @frihet/sdk
import Frihet from '@frihet/sdk';
const frihet = new Frihet({ apiKey: 'fri_...' });
const invoices = await frihet.invoices.list({ status: 'overdue' });
Repository: github.com/Frihet-io/frihet-sdk
Autentisering
Hver forespørsel må inkludere en API-nøkkel i X-API-Key-headeren. Nøkler opprettes fra Innstillinger > Utviklere > API-nøkler i Frihet-panelet.
Nøklene har prefikset fri_ etterfulgt av 32 tilfeldige bytes kodet i base64url. Eksempel: fri_aBcDeFgHiJkLmNoPqRsTuVwXyZ012345678.
curl https://api.frihet.io/v1/clients \
-H "X-API-Key: fri_tu-clave-aqui"
Alternativt kan du sende nøkkelen som en Bearer-token i Authorization-headeren:
curl https://api.frihet.io/v1/clients \
-H "Authorization: Bearer fri_tu-clave-aqui"
Nøkkel-sikkerhet
- Nøkkelen i klartekst vises kun én gang, ved opprettelsen. Den kan ikke gjenopprettes etterpå.
- Serveren lagrer en SHA-256 hash av nøkkelen. Selv i tilfelle datainnbrudd er den originale nøkkelen ikke gjenopprettelig.
- Du kan opprette nøkler med konfigurerbar utløpsdato.
- Hvis du mistenker at en nøkkel er kompromittert, tilbakekall den umiddelbart fra panelet.
Nøkkel-livssyklus
Opprett en nøkkel:
- Gå til Innstillinger > Utviklere > API-nøkler
- Klikk Opprett nøkkel
- Tilordne et beskrivende navn (for eksempel
regnskapsintegrasjon) - Valgfritt: angi en utløpsdato i dager. Hvis tom, utløper ikke nøkkelen
- Kopier nøkkelen umiddelbart -- du vil ikke kunne se den igjen
Utløp:
Nøkler med utløpsdato slutter automatisk å fungere når fristen er nådd. Forespørsler med en utløpt nøkkel mottar en 401 Unauthorized.
Tilbakekall:
Du kan tilbakekalle en nøkkel når som helst fra Innstillinger > Utviklere > API-nøkler. Tilbakekallingen er umiddelbar og irreversibel: pågående forespørsler med den nøkkelen vil feile fra det øyeblikket.
Nøkkel-rotasjon:
For å rotere en nøkkel uten å avbryte tjenesten:
- Opprett en ny nøkkel med samme omfang
- Oppdater integrasjonen din til å bruke den nye nøkkelen
- Verifiser at forespørslene fungerer korrekt
- Tilbakekall den forrige nøkkelen
Overvåking:
Hver nøkkel viser datoen for siste bruk i Innstillinger-panelet. Gå jevnlig gjennom inaktive nøkler og tilbakekall de som ikke lenger brukes.
Rate limiting
Hver API-nøkkel har en grense på 100 forespørsler per minutt. Hvis denne overskrides, svarer API-en med en 429-kode:
{
"error": "Rate limit exceeded",
"message": "Maximum 100 requests per minute",
"retryAfter": 60
}
Rate limiting-headere
Alle API-svar inkluderer headere slik at du kan administrere grensen proaktivt:
| Header | Beskrivelse | Eksempel |
|---|---|---|
X-RateLimit-Limit | Tillatte forespørsler per minutt | 100 |
X-RateLimit-Remaining | Gjenstående forespørsler i gjeldende vindu | 87 |
X-RateLimit-Reset | Unix tidsstempel (sekunder) for når vinduet tilbakestilles | 1709312400 |
Eksempel på svar med rate limiting-headere:
HTTP/1.1 200 OK
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 87
X-RateLimit-Reset: 1709312400
Content-Type: application/json
Håndtering av 429-kode:
Når du mottar en 429, bruk headerne til å beregne hvor lenge du skal vente før du prøver igjen:
async function fetchWithRateLimit(url, options) {
const response = await fetch(url, options);
if (response.status === 429) {
const resetTimestamp = response.headers.get('X-RateLimit-Reset');
const waitMs = (Number(resetTimestamp) * 1000) - Date.now();
await new Promise(resolve => setTimeout(resolve, Math.max(waitMs, 1000)));
return fetch(url, options);
}
return response;
}
Anbefalinger:
- Hvis du mottar en
429, vent til tidsstempelet angitt iX-RateLimit-Resetfør du prøver på nytt. - Overvåk
X-RateLimit-Remainingfor å bremse forespørslene før du når grensen. - Fordel forespørslene over tid i stedet for å sende ut i byger.
Forespørsel-størrelse
Kroppen i POST-, PUT- og PATCH-forespørsler kan ikke overskride 1 MB. Større forespørsler mottar en 413-kode.
Ressurser
API-en eksponerer 7 hovedressurser: invoices, expenses, clients, products, quotes, vendors og webhooks. Alle støtter komplette CRUD-operasjoner (GET, POST, PUT/PATCH, DELETE). I tillegg har kunder CRM-underkategorier: contacts, activities og notes.
Både PUT og PATCH godtar delvise oppdateringer. Du trenger ikke å sende hele ressursen -- bare feltene du ønsker å endre.
Fakturaer (/invoices)
List fakturaer
GET /v1/invoices
Spørreparametre:
| Parameter | Type | Standard | Beskrivelse |
|---|---|---|---|
limit | integer | 50 | Resultater per side (maksimalt 100) |
offset | integer | 0 | Antall resultater å hoppe over (maksimalt 10 000) |
status | string | -- | Filtrer etter status: utkast, sendt, betalt, forfalt, kansellert |
from | string | -- | Startdato (ISO 8601: YYYY-MM-DD). Filtrerer etter issueDate |
to | string | -- | Sluttdato (ISO 8601: YYYY-MM-DD). Filtrerer etter issueDate |
Eksempel:
curl "https://api.frihet.io/v1/invoices?limit=10&status=paid&from=2026-01-01&to=2026-03-31" \
-H "X-API-Key: fri_tu-clave-aqui"
Svar (200):
{
"data": [
{
"id": "abc123",
"clientName": "Acme S.L.",
"items": [
{ "description": "Consultoria", "quantity": 10, "unitPrice": 75 }
],
"status": "paid",
"issueDate": "2026-01-15",
"dueDate": "2026-02-15",
"taxRate": 21,
"notes": "",
"createdAt": "2026-01-15T10:30:00.000Z",
"updatedAt": "2026-01-20T14:00:00.000Z"
}
],
"total": 42,
"limit": 10,
"offset": 0
}
Hent faktura
GET /v1/invoices/:id
curl https://api.frihet.io/v1/invoices/abc123 \
-H "X-API-Key: fri_tu-clave-aqui"
Svar (200):
{
"id": "abc123",
"clientName": "Acme S.L.",
"items": [
{ "description": "Consultoria", "quantity": 10, "unitPrice": 75 }
],
"status": "paid",
"issueDate": "2026-01-15",
"dueDate": "2026-02-15",
"taxRate": 21,
"notes": "",
"createdAt": "2026-01-15T10:30:00.000Z",
"updatedAt": "2026-01-20T14:00:00.000Z"
}
Opprett faktura
POST /v1/invoices
Obligatoriske felt:
| Felt | Type | Beskrivelse |
|---|---|---|
clientName | string | Kundenavn (maks 10 000 tegn) |
items | array | Liste over fakturalinjer. Hver linje: { description, quantity, unitPrice } |
Valgfrie felt:
| Felt | Type | Beskrivelse |
|---|---|---|
status | string | utkast (standard), sendt, betalt, forfalt, kansellert |
issueDate | string | Utstedelsesdato (ISO 8601). Standard: i dag |
dueDate | string | Forfallsdato (ISO 8601) |
notes | string | Interne notater (maks 10 000 tegn) |
taxRate | number | Skatteprosent (0-100). Eks: 21 for 21% mva |
Struktur for hver linje (items[]):
| Felt | Type | Obligatorisk | Beskrivelse |
|---|---|---|---|
description | string | Ja | Beskrivelse av konseptet (maks 10 000 tegn) |
quantity | number | Ja | Antall |
unitPrice | number | Ja | Enhetspris |
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-01",
"taxRate": 21,
"notes": "Proyecto Q1 2026"
}'
Svar (201):
{
"id": "def456",
"clientName": "Acme S.L.",
"items": [
{ "description": "Desarrollo web", "quantity": 40, "unitPrice": 60 }
],
"status": "draft",
"issueDate": "2026-02-12",
"dueDate": "2026-03-01",
"taxRate": 21,
"notes": "Proyecto Q1 2026",
"createdAt": "2026-02-12T09:00:00.000Z",
"updatedAt": "2026-02-12T09:00:00.000Z"
}
Oppdater faktura (PUT eller PATCH)
PUT /v1/invoices/:id
PATCH /v1/invoices/:id
Du trenger bare å sende feltene du ønsker å endre. Felter som ikke er inkludert forblir uendret.
curl -X PATCH https://api.frihet.io/v1/invoices/def456 \
-H "X-API-Key: fri_tu-clave-aqui" \
-H "Content-Type: application/json" \
-d '{
"status": "sent",
"notes": "Enviada al cliente"
}'
Svar (200): Oppdatert fakturaobjekt.
Hvis du sender items, må du sende hele arrayet -- partielle oppdateringer av individuelle linjer er ikke tillatt.
Slett faktura
DELETE /v1/invoices/:id
curl -X DELETE https://api.frihet.io/v1/invoices/def456 \
-H "X-API-Key: fri_tu-clave-aqui"
Svar: 204 No Content
Last ned faktura i PDF
GET /v1/invoices/:id/pdf
Returnerer fakturaens PDF som application/pdf med Content-Disposition: attachment-headeren.
curl -o factura.pdf https://api.frihet.io/v1/invoices/abc123/pdf \
-H "X-API-Key: fri_tu-clave-aqui"
Send faktura via e-post
POST /v1/invoices/:id/send
Sender fakturaen til den spesifiserte mottakeren via Resend. Hvis fakturaen er i utkast-status, oppdateres den automatisk til sendt.
Felt:
| Felt | Type | Obligatorisk | Beskrivelse |
|---|---|---|---|
recipientEmail | string | Ja | E-postadresse til mottaker (maks 255 tegn) |
recipientName | string | Nei | Navn på mottaker (maks 200 tegn) |
customMessage | string | Nei | Egendefinert melding i e-postens brødtekst (maks 5 000 tegn) |
locale | string | Nei | E-postens språk: es (standard) eller en |
curl -X POST https://api.frihet.io/v1/invoices/abc123/send \
-H "X-API-Key: fri_tu-clave-aqui" \
-H "Content-Type: application/json" \
-d '{
"recipientEmail": "admin@acme.es",
"recipientName": "Departamento de Contabilidad",
"locale": "es"
}'
Svar (200):
{ "success": true, "messageId": "re_abc123..." }
Merk faktura som betalt
POST /v1/invoices/:id/paid
| Felt | Type | Obligatorisk | Beskrivelse |
|---|---|---|---|
paidDate | string | Nei | Betalingsdato (ISO 8601). Standard: i dag |
curl -X POST https://api.frihet.io/v1/invoices/abc123/paid \
-H "X-API-Key: fri_tu-clave-aqui" \
-H "Content-Type: application/json" \
-d '{ "paidDate": "2026-03-15" }'
Svar (200):
{ "success": true, "status": "paid", "paidAt": "2026-03-15" }
Utgifter (/expenses)
List utgifter
GET /v1/expenses
Spørreparametre:
| Parameter | Type | Standard | Beskrivelse |
|---|---|---|---|
limit | integer | 50 | Resultater per side (maksimalt 100) |
offset | integer | 0 | Antall resultater å hoppe over |
from | string | -- | Startdato (ISO 8601). Filtrerer etter date |
to | string | -- | Sluttdato (ISO 8601). Filtrerer etter date |
curl "https://api.frihet.io/v1/expenses?limit=20&from=2026-01-01" \
-H "X-API-Key: fri_tu-clave-aqui"
Svar (200):
{
"data": [
{
"id": "exp789",
"description": "Licencia Adobe Creative Cloud",
"amount": 59.99,
"category": "software",
"date": "2026-02-01",
"vendor": "Adobe Inc.",
"taxDeductible": true,
"createdAt": "2026-02-01T10:00:00.000Z",
"updatedAt": "2026-02-01T10:00:00.000Z"
}
],
"total": 15,
"limit": 20,
"offset": 0
}
Hent utgift
GET /v1/expenses/:id
Opprett utgift
POST /v1/expenses
Obligatoriske felt:
| Felt | Type | Beskrivelse |
|---|---|---|
description | string | Beskrivelse av utgiften (maks 10 000 tegn) |
amount | number | Utgiftsbeløp |
Valgfrie felt:
| Felt | Type | Beskrivelse |
|---|---|---|
category | string | Kategori for utgiften (maks 10 000 tegn) |
date | string | Utgiftsdato (ISO 8601). Standard: i dag |
vendor | string | Leverandør (maks 10 000 tegn) |
taxDeductible | boolean | Om utgiften er fradragsberettiget |
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-01",
"vendor": "Adobe Inc.",
"taxDeductible": true
}'
Svar (201):
{
"id": "exp789",
"description": "Licencia Adobe Creative Cloud",
"amount": 59.99,
"category": "software",
"date": "2026-02-01",
"vendor": "Adobe Inc.",
"taxDeductible": true,
"createdAt": "2026-02-12T09:15:00.000Z",
"updatedAt": "2026-02-12T09:15:00.000Z"
}
Oppdater utgift (PUT eller PATCH)
PUT /v1/expenses/:id
PATCH /v1/expenses/:id
curl -X PATCH https://api.frihet.io/v1/expenses/exp789 \
-H "X-API-Key: fri_tu-clave-aqui" \
-H "Content-Type: application/json" \
-d '{ "amount": 65.99, "taxDeductible": false }'
Svar (200): Oppdatert utgiftsobjekt.
Slett utgift
DELETE /v1/expenses/:id
Svar: 204 No Content
Kunder (/clients)
List kunder
GET /v1/clients
Godtar limit, offset, from og to (filtrerer etter createdAt).
curl "https://api.frihet.io/v1/clients?limit=50" \
-H "X-API-Key: fri_tu-clave-aqui"
Hent kunde
GET /v1/clients/:id
Opprett kunde
POST /v1/clients
Obligatoriske felt:
| Felt | Type | Beskrivelse |
|---|---|---|
name | string | Kundenavn (maks 10 000 tegn) |
Valgfrie felt:
| Felt | Type | Beskrivelse |
|---|---|---|
email | string | Kontakt-e-post |
phone | string | Telefon |
taxId | string | Org.nr/MVA-nr |
address | object | Adresse (se struktur nedenfor) |
Struktur for address:
| Felt | Type | Beskrivelse |
|---|---|---|
street | string | Gate og nummer |
city | string | By |
state | string | Provins eller stat |
postalCode | string | Postnummer |
country | string | Land |
Alle felt i address er valgfrie.
curl -X POST https://api.frihet.io/v1/clients \
-H "X-API-Key: fri_tu-clave-aqui" \
-H "Content-Type: application/json" \
-d '{
"name": "Acme S.L.",
"email": "admin@acme.es",
"taxId": "B12345678",
"address": {
"street": "Calle Gran Via 42",
"city": "Madrid",
"postalCode": "28013",
"country": "ES"
}
}'
Svar (201):
{
"id": "cli001",
"name": "Acme S.L.",
"email": "admin@acme.es",
"taxId": "B12345678",
"address": {
"street": "Calle Gran Via 42",
"city": "Madrid",
"postalCode": "28013",
"country": "ES"
},
"createdAt": "2026-02-12T09:30:00.000Z",
"updatedAt": "2026-02-12T09:30:00.000Z"
}
Oppdater kunde (PUT eller PATCH)
PUT /v1/clients/:id
PATCH /v1/clients/:id
curl -X PATCH https://api.frihet.io/v1/clients/cli001 \
-H "X-API-Key: fri_tu-clave-aqui" \
-H "Content-Type: application/json" \
-d '{ "phone": "+34 912 345 678" }'
Svar (200): Oppdatert kundeobjekt.
Slett kunde
DELETE /v1/clients/:id
Svar: 204 No Content
CRM: Kontaktpersoner, Aktiviteter og Notater
Kunder har tre underkategorier for å administrere CRM-relasjoner: kontaktpersoner, aktiviteter og notater. Alle endepunkter krever en gyldig clientId i URL-en.
Kontaktpersoner (/v1/clients/:id/contacts)
List kontakter
GET /v1/clients/:id/contacts
curl "https://api.frihet.io/v1/clients/cli001/contacts" \
-H "X-API-Key: fri_tu-clave-aqui"
Hent kontakt
GET /v1/clients/:id/contacts/:contactId
curl "https://api.frihet.io/v1/clients/cli001/contacts/con001" \
-H "X-API-Key: fri_tu-clave-aqui"
Opprett kontakt
POST /v1/clients/:id/contacts
Obligatoriske felt:
| Felt | Type | Beskrivelse |
|---|---|---|
name | string | Navn på kontaktperson |
Valgfrie felt:
| Felt | Type | Beskrivelse |
|---|---|---|
email | string | E-postadresse til kontakten |
phone | string | Telefon |
role | string | Tittel eller rolle (f.eks. "Økonomidirektør") |
isPrimary | boolean | Om dette er kundens primære kontakt |
curl -X POST https://api.frihet.io/v1/clients/cli001/contacts \
-H "X-API-Key: fri_tu-clave-aqui" \
-H "Content-Type: application/json" \
-d '{
"name": "Maria Garcia",
"email": "maria@acme.es",
"phone": "+34 612 345 678",
"role": "Directora financiera",
"isPrimary": true
}'
Svar (201):
{
"id": "con001",
"name": "Maria Garcia",
"email": "maria@acme.es",
"phone": "+34 612 345 678",
"role": "Directora financiera",
"isPrimary": true,
"createdAt": "2026-03-15T10:00:00.000Z",
"updatedAt": "2026-03-15T10:00:00.000Z"
}
Oppdater kontakt
PATCH /v1/clients/:id/contacts/:contactId
curl -X PATCH https://api.frihet.io/v1/clients/cli001/contacts/con001 \
-H "X-API-Key: fri_tu-clave-aqui" \
-H "Content-Type: application/json" \
-d '{ "role": "CEO" }'
Svar (200): Oppdatert kontaktobjekt.
Slett kontakt
DELETE /v1/clients/:id/contacts/:contactId
curl -X DELETE https://api.frihet.io/v1/clients/cli001/contacts/con001 \
-H "X-API-Key: fri_tu-clave-aqui"
Svar: 204 No Content
Aktiviteter (/v1/clients/:id/activities)
Aktivitetsloggen registrerer interaksjoner med en kunde. Systemaktiviteter (som invoice_created, quote_sent, osv.) genereres automatisk. Du kan også opprette manuelle aktiviteter.
Aktivitetene er uforanderlige. De kan ikke oppdateres eller slettes når de er opprettet.
List aktiviteter
GET /v1/clients/:id/activities
curl "https://api.frihet.io/v1/clients/cli001/activities" \
-H "X-API-Key: fri_tu-clave-aqui"
Hent aktivitet
GET /v1/clients/:id/activities/:activityId
curl "https://api.frihet.io/v1/clients/cli001/activities/act001" \
-H "X-API-Key: fri_tu-clave-aqui"
Opprett aktivitet
POST /v1/clients/:id/activities
Obligatoriske felt:
| Felt | Type | Beskrivelse |
|---|---|---|
type | string | Aktivitetstype: call, email, meeting eller task |
title | string | Beskrivende tittel på aktiviteten |
Valgfrie felt:
| Felt | Type | Beskrivelse |
|---|---|---|
description | string | Detaljert beskrivelse |
metadata | object | Tilleggsdata i fritt format |
Typene call, email, meeting og task er for manuelt opprettede aktiviteter. Systemtyper som invoice_created, quote_sent eller expense_linked genereres automatisk og kan ikke opprettes via API.
curl -X POST https://api.frihet.io/v1/clients/cli001/activities \
-H "X-API-Key: fri_tu-clave-aqui" \
-H "Content-Type: application/json" \
-d '{
"type": "call",
"title": "Llamada de seguimiento presupuesto Q2",
"description": "Comentamos las condiciones del presupuesto. Pendiente de confirmar.",
"metadata": {
"duration": "15min",
"outcome": "pending"
}
}'
Svar (201):
{
"id": "act001",
"type": "call",
"title": "Llamada de seguimiento presupuesto Q2",
"description": "Comentamos las condiciones del presupuesto. Pendiente de confirmar.",
"metadata": {
"duration": "15min",
"outcome": "pending"
},
"createdAt": "2026-03-15T14:30:00.000Z"
}
Notater (/v1/clients/:id/notes)
List notater
GET /v1/clients/:id/notes
curl "https://api.frihet.io/v1/clients/cli001/notes" \
-H "X-API-Key: fri_tu-clave-aqui"
Hent notat
GET /v1/clients/:id/notes/:noteId
curl "https://api.frihet.io/v1/clients/cli001/notes/note001" \
-H "X-API-Key: fri_tu-clave-aqui"
Opprett notat
POST /v1/clients/:id/notes
Obligatoriske felt:
| Felt | Type | Beskrivelse |
|---|---|---|
content | string | Innholdet i notatet |
curl -X POST https://api.frihet.io/v1/clients/cli001/notes \
-H "X-API-Key: fri_tu-clave-aqui" \
-H "Content-Type: application/json" \
-d '{
"content": "Cliente interesado en plan Business. Contactar en abril para renovacion."
}'
Svar (201):
{
"id": "note001",
"content": "Cliente interesado en plan Business. Contactar en abril para renovacion.",
"createdAt": "2026-03-15T16:00:00.000Z",
"updatedAt": "2026-03-15T16:00:00.000Z"
}
Oppdater notat
PATCH /v1/clients/:id/notes/:noteId
curl -X PATCH https://api.frihet.io/v1/clients/cli001/notes/note001 \
-H "X-API-Key: fri_tu-clave-aqui" \
-H "Content-Type: application/json" \
-d '{
"content": "Cliente interesado en plan Business. Reunion confirmada 5 de abril."
}'
Svar (200): Oppdatert notatobjekt.
Slett notat
DELETE /v1/clients/:id/notes/:noteId
curl -X DELETE https://api.frihet.io/v1/clients/cli001/notes/note001 \
-H "X-API-Key: fri_tu-clave-aqui"
Svar: 204 No Content
Produkter (/products)
List produkter
GET /v1/products
Godtar limit, offset, from og to (filtrerer etter createdAt).
Hent produkt
GET /v1/products/:id
Opprett produkt
POST /v1/products
Obligatoriske felt:
| Felt | Type | Beskrivelse |
|---|---|---|
name | string | Navn på produkt eller tjeneste (maks 10 000 tegn) |
unitPrice | number | Enhetspris |
Valgfrie felt:
| Felt | Type | Beskrivelse |
|---|---|---|
description | string | Beskrivelse (maks 10 000 tegn) |
taxRate | number | Skatteprosent (0-100) |
curl -X POST https://api.frihet.io/v1/products \
-H "X-API-Key: fri_tu-clave-aqui" \
-H "Content-Type: application/json" \
-d '{
"name": "Hora de consultoria",
"unitPrice": 75,
"description": "Consultoria estrategica",
"taxRate": 21
}'
Svar (201):
{
"id": "prod001",
"name": "Hora de consultoria",
"unitPrice": 75,
"description": "Consultoria estrategica",
"taxRate": 21,
"createdAt": "2026-02-12T10:00:00.000Z",
"updatedAt": "2026-02-12T10:00:00.000Z"
}
Oppdater produkt (PUT eller PATCH)
PUT /v1/products/:id
PATCH /v1/products/:id
curl -X PATCH https://api.frihet.io/v1/products/prod001 \
-H "X-API-Key: fri_tu-clave-aqui" \
-H "Content-Type: application/json" \
-d '{ "unitPrice": 85 }'
Svar (200): Oppdatert produktobjekt.
Slett produkt
DELETE /v1/products/:id
Svar: 204 No Content
Tilbud (/quotes)
List tilbud
GET /v1/quotes
Spørreparametre:
| Parameter | Type | Standard | Beskrivelse |
|---|---|---|---|
limit | integer | 50 | Resultater per side (maksimalt 100) |
offset | integer | 0 | Antall resultater å hoppe over |
status | string | -- | Filtrer etter status: utkast, sendt, akseptert, avvist, utløpt |
from | string | -- | Startdato (ISO 8601). Filtrerer etter issueDate |
to | string | -- | Sluttdato (ISO 8601). Filtrerer etter issueDate |
curl "https://api.frihet.io/v1/quotes?status=sent" \
-H "X-API-Key: fri_tu-clave-aqui"
Hent tilbud
GET /v1/quotes/:id
Opprett tilbud
POST /v1/quotes
Obligatoriske felt:
| Felt | Type | Beskrivelse |
|---|---|---|
clientName | string | Kundenavn (maks 10 000 tegn) |
items | array | Linjer i tilbudet. Hver linje: { description, quantity, unitPrice } |
Valgfrie felt:
| Felt | Type | Beskrivelse |
|---|---|---|
validUntil | string | Gyldig til dato (ISO 8601) |
notes | string | Notater eller betingelser (maks 10 000 tegn) |
status | string | utkast (standard), sendt, akseptert, avvist, utløpt |
curl -X POST https://api.frihet.io/v1/quotes \
-H "X-API-Key: fri_tu-clave-aqui" \
-H "Content-Type: application/json" \
-d '{
"clientName": "Design Studio SL",
"items": [
{ "description": "Desarrollo web", "quantity": 80, "unitPrice": 60 },
{ "description": "Diseno UX", "quantity": 20, "unitPrice": 55 }
],
"validUntil": "2026-04-01",
"notes": "Incluye 2 rondas de revision"
}'
Svar (201):
{
"id": "quo001",
"clientName": "Design Studio SL",
"items": [
{ "description": "Desarrollo web", "quantity": 80, "unitPrice": 60 },
{ "description": "Diseno UX", "quantity": 20, "unitPrice": 55 }
],
"status": "draft",
"validUntil": "2026-04-01",
"notes": "Incluye 2 rondas de revision",
"createdAt": "2026-02-12T11:00:00.000Z",
"updatedAt": "2026-02-12T11:00:00.000Z"
}
Oppdater tilbud (PUT eller PATCH)
PUT /v1/quotes/:id
PATCH /v1/quotes/:id
Slett tilbud
DELETE /v1/quotes/:id
Svar: 204 No Content
Last ned tilbud i PDF
GET /v1/quotes/:id/pdf
Fungerer på samme måte som /invoices/:id/pdf. Returnerer application/pdf.
curl -o presupuesto.pdf https://api.frihet.io/v1/quotes/quo001/pdf \
-H "X-API-Key: fri_tu-clave-aqui"
Send tilbud via e-post
POST /v1/quotes/:id/send
Samme felt som /invoices/:id/send (recipientEmail, recipientName, customMessage, locale). Hvis tilbudet er i utkast-status, oppdateres det automatisk til sendt.
Batchoperasjoner (/batch)
Alle hovedressurser støtter batch-oppretting. Send et array med opptil 50 elementer i en enkelt forespørsel.
POST /v1/{resource}/batch
Støttede ressurser: invoices, expenses, clients, products, quotes
Forespørselens kropp:
{
"items": [
{ "clientName": "Acme SL", "items": [{ "description": "Hora consultoria", "quantity": 1, "unitPrice": 95 }] },
{ "clientName": "TechStart SL", "items": [{ "description": "Desarrollo web", "quantity": 8, "unitPrice": 60 }] }
]
}
curl -X POST https://api.frihet.io/v1/invoices/batch \
-H "X-API-Key: fri_tu-clave-aqui" \
-H "Content-Type: application/json" \
-d '{
"items": [
{ "clientName": "Acme SL", "items": [{ "description": "Consultoria", "quantity": 1, "unitPrice": 95 }] },
{ "clientName": "TechStart SL", "items": [{ "description": "Desarrollo", "quantity": 8, "unitPrice": 60 }] }
]
}'
Svar (207 Multi-Status):
{
"results": [
{ "status": 201, "data": { "id": "inv_001", "clientName": "Acme SL", "status": "draft" } },
{ "status": 201, "data": { "id": "inv_002", "clientName": "TechStart SL", "status": "draft" } }
],
"summary": { "total": 2, "succeeded": 2, "failed": 0 }
}
Hvis noen av elementene mislykkes valideringen, opprettes resten likevel. Individuelle feil returneres i results-arrayet:
{
"results": [
{ "status": 201, "data": { "id": "inv_001", "clientName": "Acme SL" } },
{ "status": 400, "error": { "message": "Missing required field: items" } }
],
"summary": { "total": 2, "succeeded": 1, "failed": 1 }
}
Grenser:
| Konsept | Grense |
|---|---|
| Elementer per batch | Maks 50 |
| Forespørsel-størrelse | Maks 1 MB |
Idempotens
POST-forespørsler godtar en Idempotency-Key-header for å forhindre duplisert opprettelse av ressurser ved nettverksforsøk. Hvis samme nøkkel sendes innen de neste 24 timene, returnerer API-en det originale svaret uten å utføre operasjonen på nytt.
curl -X POST https://api.frihet.io/v1/invoices \
-H "X-API-Key: fri_tu-clave-aqui" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \
-d '{
"clientName": "Acme SL",
"items": [{ "description": "Consultoria", "quantity": 10, "unitPrice": 95 }]
}'
Oppførsel:
| Scenario | Resultat |
|---|---|
| Første forespørsel med nøkkelen | Ressursen opprettes normalt |
| Gjentatt forespørsel med samme nøkkel (innen 24 timer) | Den originale responsen returneres, uten duplisering |
| Samme nøkkel etter 24 timer | Behandles som en ny forespørsel |
Svar-header:
Når API-en oppdager en gjentatt nøkkel, inkluderer den X-Idempotent-Replayed: true-headeren slik at forbrukeren vet at svaret er en kopi.
HTTP/1.1 201 Created
X-Idempotent-Replayed: true
Content-Type: application/json
Krav:
- Nøkkelen må ha maksimalt 64 tegn
- Vi anbefaler å bruke UUID v4
- Gjelder kun for
POST-forespørsler (opprette ressurser)
Søk
Liste-endepunktene støtter fulltekstsøk ved hjelp av parameteren q:
curl "https://api.frihet.io/v1/invoices?q=acme" \
-H "X-API-Key: fri_tu-clave-aqui"
Søket gjelder for ressursens hovedtekstfelt (kundenavn, beskrivelse, notater, osv.). Det kan kombineres med eksisterende filtre (status, from, to).
Intelligens-endepunkter
Disse endepunktene gir aggregerte data og forretningskontekst. De er spesielt nyttige for AI-agenter og eksterne dashboards.
Forretningskontekst (/context)
GET /v1/context
Returnerer en komplett forretningsoversikt, designet for å gi AI-agenter den nødvendige konteksten for å ta informerte beslutninger. Inkluderer finansiell oppsummering, nylig aktivitet, varsler og skatteinnstillinger.
curl https://api.frihet.io/v1/context \
-H "X-API-Key: fri_tu-clave-aqui"
Svar (200):
{
"business": {
"name": "BRTHLS Studio",
"taxId": "12345678A",
"fiscalZone": "canarias",
"currency": "EUR"
},
"summary": {
"revenue": { "invoiced": 15000, "paid": 12000, "pending": 2000, "overdue": 1000 },
"expenses": { "total": 4500 },
"profit": 7500,
"counts": { "invoices": 25, "clients": 12, "products": 5 }
},
"recentActivity": [
{ "type": "invoice.created", "id": "inv_001", "description": "Faktura for Acme SL", "timestamp": "2026-03-18T10:00:00Z" },
{ "type": "expense.created", "id": "exp_042", "description": "Adobe Creative Cloud", "timestamp": "2026-03-17T14:30:00Z" }
],
"alerts": [
{ "type": "overdue", "count": 2, "amount": 1000 },
{ "type": "tax_deadline", "model": "303", "dueDate": "2026-04-20" }
]
}
Månedlig resultatrapport (/monthly)
GET /v1/monthly?month=YYYY-MM
Returnerer resultatrapporten (P&L) for en spesifikk måned: fakturerte inntekter, utgifter per kategori, netto fortjeneste og sammenligning med forrige måned.
curl "https://api.frihet.io/v1/monthly?month=2026-02" \
-H "X-API-Key: fri_tu-clave-aqui"
Svar (200):
{
"month": "2026-02",
"revenue": {
"invoiced": 8500.00,
"collected": 6200.00,
"outstanding": 2300.00
},
"expenses": {
"total": 3100.00,
"byCategory": {
"software": 450.00,
"marketing": 800.00,
"office": 350.00,
"professional_services": 1500.00
}
},
"profit": 5400.00,
"comparison": {
"revenueChange": 12.5,
"expenseChange": -5.2,
"profitChange": 22.1
}
}
Kvartalsvise skattetall (/quarterly)
GET /v1/quarterly?quarter=YYYY-Q1
Returnerer kvartalsvise skattetall, forberedt for innlevering av Modelo 303 (mva) og Modelo 130 (inntektsskatt for selvstendig næringsdrivende). Inkluderer skattepliktig grunnlag, påløpte avgifter, fradragsberettigede avgifter og resultat av avregningen.
curl "https://api.frihet.io/v1/quarterly?quarter=2026-Q1" \
-H "X-API-Key: fri_tu-clave-aqui"
Svar (200):
{
"quarter": "2026-Q1",
"period": { "from": "2026-01-01", "to": "2026-03-31" },
"modelo303": {
"baseImponible21": 12000.00,
"cuotaDevengada21": 2520.00,
"baseImponible10": 0,
"cuotaDevengada10": 0,
"baseImponible4": 0,
"cuotaDevengada4": 0,
"totalDevengado": 2520.00,
"ivaDeducible": 980.00,
"resultado": 1540.00
},
"modelo130": {
"ingresos": 12000.00,
"gastos": 4500.00,
"rendimientoNeto": 7500.00,
"porcentaje": 20,
"cuota": 1500.00,
"retenciones": 0,
"pagosAnteriores": 0,
"resultado": 1500.00
}
}
Endepunktene /context, /monthly og /quarterly er designet for å være det ideelle inngangspunktet for AI-agenter. De gir nødvendig informasjon i ett enkelt kall, uten behov for å konsultere flere individuelle endepunkter.
Finansielt dashbord (/summary)
GET /v1/summary
Returnerer en finansiell oppsummering av virksomheten: inntekter, utgifter, fortjeneste og tellere.
Spørreparametre:
| Parameter | Type | Beskrivelse |
|---|---|---|
from | string | Startdato (ISO 8601) |
to | string | Sluttdato (ISO 8601) |
curl "https://api.frihet.io/v1/summary?from=2026-01-01&to=2026-03-31" \
-H "X-API-Key: fri_tu-clave-aqui"
Svar (200):
{
"period": { "from": "2026-01-01", "to": "2026-03-31" },
"revenue": {
"invoiced": 15000.00,
"paid": 12000.00,
"pending": 2000.00,
"overdue": 1000.00
},
"expenses": { "total": 4500.00 },
"profit": 7500.00,
"counts": {
"invoices": 25,
"quotes": 8,
"expenses": 42,
"clients": 12,
"products": 5
},
"invoicesByStatus": {
"draft": 3,
"sent": 5,
"paid": 15,
"overdue": 2
},
"overdue": { "count": 2, "amount": 1000.00 }
}
Feilkoder
API-en bruker standard HTTP-koder. Feilsvar inkluderer et JSON-objekt med feltene error og, valgfritt, message og details.
| Kode | Betydning | Beskrivelse |
|---|---|---|
400 | Bad Request | Mangler et påkrevd felt, feil format eller ikke-tillatt felt |
401 | Unauthorized | API-nøkkelen er ikke oppgitt, er ugyldig, har feil format eller har utløpt |
403 | Forbidden | API-nøkkelen har ikke tillatelse til å få tilgang til denne ressursen |
404 | Not Found | Den forespurte ressursen eksisterer ikke |
405 | Method Not Allowed | HTTP-metoden støttes ikke for dette endepunktet |
413 | Payload Too Large | Forespørselens kropp overskrider 1 MB |
422 | Unprocessable Entity | Gyldige data, men serveren kan ikke behandle dem (f.eks.: skatteprofil ikke konfigurert) |
429 | Too Many Requests | Grensen på 100 forespørsler per minutt er overskredet |
500 | Internal Server Error | Intern serverfeil |
Struktur for feilsvar
Valideringsfeil (400):
{
"error": "Validation error",
"details": [
{
"code": "invalid_type",
"expected": "string",
"received": "undefined",
"path": ["clientName"],
"message": "Required"
}
]
}
Valideringsfeil bruker Zod-formatet. path-feltet indikerer hvilket felt som inneholder feilen, og message beskriver problemet.
Ugyldig eller utløpt nøkkel (401):
{
"error": "Invalid or expired API key"
}
Ugyldig nøkkelformat (401):
{
"error": "Invalid API key format"
}
Ressurs ikke funnet (404):
{
"error": "Resource not found"
}
Ugyldig status i filter (400):
{
"error": "Invalid status filter",
"message": "Valid values: draft, sent, paid, overdue, cancelled"
}
Rate limit overskredet (429):
{
"error": "Rate limit exceeded",
"message": "Maximum 100 requests per minute",
"retryAfter": 60
}
Intern feil (500):
{
"error": "Internal server error"
}
Paginering
Liste-endepunktene returnerer paginerte resultater med følgende struktur:
{
"data": [],
"total": 142,
"limit": 50,
"offset": 0
}
total: totalt antall poster som oppfyller de anvendte filtrenelimit: antall poster returnert på denne siden (maksimalt 100)offset: antall overhoppede poster (maksimalt 10 000)
For å hente neste side:
curl "https://api.frihet.io/v1/invoices?limit=50&offset=50" \
-H "X-API-Key: fri_tu-clave-aqui"
Resultatene sorteres etter ressursens naturlige dato i synkende rekkefølge (nyeste først):
- Fakturaer og tilbud:
issueDate - Utgifter:
date - Kunder og produkter:
createdAt
Streng validering
API-en bruker streng validering (Zod strict mode). Forespørsler med ukjente felt avvises med en 400-feil:
{
"error": "Validation error",
"details": [
{
"code": "unrecognized_keys",
"keys": ["campoInventado"],
"path": [],
"message": "Unrecognized key(s) in object: 'campoInventado'"
}
]
}
Dette forhindrer stille feil på grunn av skrivefeil i feltnavnene.
CORS
API-en støtter CORS for forespørsler fra nettleseren. Tillatte originer er:
https://app.frihet.iohttps://frihet.iohttps://www.frihet.io
For server-til-server-integrasjoner er CORS ikke relevant. Hvis du trenger å få tilgang til API-en fra et annet domene i nettleseren, bruk en proxy i din backend.
Sikkerhet-headere
Alle svar inkluderer sikkerhet-headere:
| Header | Verdi |
|---|---|
X-Content-Type-Options | nosniff |
X-Frame-Options | DENY |
X-XSS-Protection | 1; mode=block |
X-Request-Id | Unik forespørsel-ID (nyttig for feilsøking) |
OAuth for MCP
Endepunktet POST /api/oauth/api-key tillater automatisk provisjonering av en API-nøkkel gjennom MCPs OAuth-flyt. MCP-serveren bruker dette endepunktet internt -- du trenger ikke å kalle det direkte.
Flyten:
- Brukeren autentiserer via Firebase Auth
- MCP-klienten sender Firebase-tokenet til
/api/oauth/api-key - Serveren returnerer en ny nøkkel
fri_xxx...merket som "MCP OAuth" - Nøkkelen utløper etter 365 dager
Grense: 5 aktive nøkler per bruker. Hvis grensen overskrides, svarer endepunktet med en 429.
Beste praksis
- Lagre API-nøkkelen sikkert. Inkluder den aldri i frontend-kode, offentlige repositoryer eller logger.
- Administrer rate limiting. Implementer eksponensiell backoff hvis du mottar en
429. - Bruk paginering. Ikke be om alle poster samtidig; iterer med
limitogoffset. - Verifiser svarkodene. Ikke anta at alle forespørsler vil være vellykkede.
- Roter nøkler periodisk. Opprett en ny nøkkel, oppdater integrasjonen din og tilbakekall den forrige.
- Bruk alltid HTTPS. Alle API-forespørsler må være over HTTPS.
- Bruk filtre. Parametrene
status,fromogtoreduserer mengden overførte data. - Dra nytte av PATCH. For partielle oppdateringer, send kun de endrede feltene.