Hop til hovedindhold

REST API

Frihets REST API giver programmatisk adgang til og manipulation af dine kontoresurser. Al kommunikation foregår via HTTPS, og svar er i JSON-format.

Base-URL

https://api.frihet.io/v1

Alle endpoints beskrevet på denne side er relative til denne Base-URL.

Opdagelse: En GET-anmodning til roden (https://api.frihet.io/) returnerer de primære links uden behov for autentifikation:

{
"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-specifikationen er tilgængelig på https://api.frihet.io/openapi.yaml.

SDK tilgængelig

Hvis du bruger TypeScript eller JavaScript, forenkler det officielle SDK integrationen:

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


Autentifikation

Hver anmodning skal inkludere en API-nøgle i X-API-Key-headeren. Nøgler oprettes under Indstillinger > Udviklere > API-nøgler i Frihet-panelet.

Nøgler har præfikset fri_ efterfulgt af 32 tilfældige 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øglen som et Bearer-token i Authorization-headeren:

curl https://api.frihet.io/v1/clients \
-H "Authorization: Bearer fri_tu-clave-aqui"

Nøglernes sikkerhed

  • Nøglen i klartekst vises kun én gang, ved oprettelsestidspunktet. Den kan ikke gendannes efterfølgende.
  • Serveren gemmer et SHA-256-hash af nøglen. Selv i tilfælde af et databrud kan den originale nøgle ikke gendannes.
  • Du kan oprette nøgler med konfigurerbar udløbsdato.
  • Hvis du mistænker, at en nøgle er blevet kompromitteret, skal du straks tilbagekalde den fra panelet.

Nøglernes livscyklus

Opret en nøgle:

  1. Gå til Indstillinger > Udviklere > API-nøgler
  2. Klik på Opret nøgle
  3. Tildel et beskrivende navn (f.eks. integration-regnskab)
  4. Indstil eventuelt en udløbsdato i dage. Hvis feltet efterlades tomt, udløber nøglen ikke.
  5. Kopier nøglen med det samme -- du vil ikke kunne se den igen.

Udløb:

Nøgler med udløbsdato holder automatisk op med at fungere, når fristen udløber. Anmodninger med en udløbet nøgle modtager en 401 Unauthorized.

Tilbagekaldelse:

Du kan tilbagekalde en nøgle når som helst under Indstillinger > Udviklere > API-nøgler. Tilbagekaldelse er øjeblikkelig og irreversibel: igangværende anmodninger med den nøgle vil fejle fra det øjeblik.

Nøglerotation:

For at rotere en nøgle uden at afbryde tjenesten:

  1. Opret en ny nøgle med samme omfang.
  2. Opdater din integration til at bruge den nye nøgle.
  3. Bekræft, at anmodningerne fungerer korrekt.
  4. Tilbagekald den tidligere nøgle.

Overvågning:

Hver nøgle viser datoen for seneste brug i indstillingspanelet. Gennemgå regelmæssigt inaktive nøgler og tilbagekald dem, der ikke længere bruges.


Rate limiting

Hver API-nøgle har en grænse på 100 anmodninger pr. minut. Hvis dette overskrides, svarer API'en med en 429-kode:

{
"error": "Rate limit exceeded",
"message": "Maximum 100 requests per minute",
"retryAfter": 60
}

Rate limiting-headers

Alle API-svar inkluderer headers, så du proaktivt kan administrere grænsen:

HeaderBeskrivelseEksempel
X-RateLimit-LimitTilladte anmodninger pr. minut100
X-RateLimit-RemainingResterende anmodninger i det nuværende vindue87
X-RateLimit-ResetUnix-timestamp (sekunder), hvor vinduet nulstilles1709312400

Eksempel på svar med rate limiting-headers:

HTTP/1.1 200 OK
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 87
X-RateLimit-Reset: 1709312400
Content-Type: application/json

Håndtering af 429-koden:

Når du modtager en 429, skal du bruge headers til at beregne, hvor længe du skal vente, før du forsøger igen:

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 modtager en 429, skal du vente til det timestamp, der er angivet i X-RateLimit-Reset, før du forsøger igen.
  • Overvåg X-RateLimit-Remaining for at bremse anmodninger, før grænsen nås.
  • Fordel anmodninger over tid i stedet for at sende dem i byger.

Anmodningsstørrelse

Brødteksten for POST-, PUT- og PATCH-anmodninger må ikke overstige 1 MB. Større anmodninger modtager en 413-kode.


Ressourcer

API'en eksponerer 7 primære ressourcer: invoices, expenses, clients, products, quotes, vendors og webhooks. Alle understøtter komplette CRUD-operationer (GET, POST, PUT/PATCH, DELETE). Derudover har kunder CRM-underkollektioner: contacts, activities og notes.

PATCH vs PUT

Både PUT og PATCH accepterer delvise opdateringer. Du behøver ikke at sende hele ressourcen -- kun de felter, du ønsker at ændre.

Fakturaer (/invoices)

Vis fakturaer

GET /v1/invoices

Forespørgselsparametre:

ParameterTypeStandardBeskrivelse
limitinteger50Resultater pr. side (maks. 100)
offsetinteger0Antal resultater, der skal springes over (maks. 10.000)
statusstring--Filtrer efter status: kladde, sendt, betalt, forfalden, annulleret
fromstring--Startdato (ISO 8601: ÅÅÅÅ-MM-DD). Filtrerer efter issueDate
tostring--Slutdato (ISO 8601: ÅÅÅÅ-MM-DD). Filtrerer efter 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"
}

Opret faktura

POST /v1/invoices

Påkrævede felter:

FeltTypeBeskrivelse
clientNamestringKundenavn (maks. 10.000 tegn)
itemsarrayListe over fakturalinjer. Hver linje: { description, quantity, unitPrice }

Valgfrie felter:

FeltTypeBeskrivelse
statusstringkladde (standard), sendt, betalt, forfalden, annulleret
issueDatestringUdstillingsdato (ISO 8601). Standard: i dag
dueDatestringForfaldsdato (ISO 8601)
notesstringInterne noter (maks. 10.000 tegn)
taxRatenumberSkattesats i procent (0-100). F.eks.: 21 for 21% moms

Struktur for hver linje (items[]):

FeltTypePåkrævetBeskrivelse
descriptionstringJaBeskrivelse af elementet (maks. 10.000 tegn)
quantitynumberJaAntal
unitPricenumberJaEnhedspris
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"
}

Opdater faktura (PUT eller PATCH)

PUT /v1/invoices/:id
PATCH /v1/invoices/:id

Du skal kun sende de felter, du ønsker at ændre. Ikke-inkluderede felter forbliver uændrede.

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): Opdateret fakturaobjekt.

caution

Hvis du sender items, skal du sende hele array'et -- delvise opdateringer af individuelle linjer er ikke tilladt.

Slet 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

Download 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-mail

POST /v1/invoices/:id/send

Sender fakturaen til den specificerede modtager via Resend. Hvis fakturaen er i status kladde, opdateres den automatisk til sendt.

Felter:

FeltTypePåkrævetBeskrivelse
recipientEmailstringJaModtagerens e-mail (maks. 255 tegn)
recipientNamestringNejModtagerens navn (maks. 200 tegn)
customMessagestringNejTilpasset besked i e-mailens brødtekst (maks. 5.000 tegn)
localestringNejE-mailsprog: 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..." }

Marker faktura som betalt

POST /v1/invoices/:id/paid
FeltTypePåkrævetBeskrivelse
paidDatestringNejBetalingsdato (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" }

Udgifter (/expenses)

Vis udgifter

GET /v1/expenses

Forespørgselsparametre:

ParameterTypeStandardBeskrivelse
limitinteger50Resultater pr. side (maks. 100)
offsetinteger0Antal resultater, der skal springes over
fromstring--Startdato (ISO 8601). Filtrerer efter date
tostring--Slutdato (ISO 8601). Filtrerer efter 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 udgift

GET /v1/expenses/:id

Opret udgift

POST /v1/expenses

Påkrævede felter:

FeltTypeBeskrivelse
descriptionstringBeskrivelse af udgiften (maks. 10.000 tegn)
amountnumberUdgiftsbeløb

Valgfrie felter:

FeltTypeBeskrivelse
categorystringUdgiftskategori (maks. 10.000 tegn)
datestringUdgiftsdato (ISO 8601). Standard: i dag
vendorstringLeverandør (maks. 10.000 tegn)
taxDeductiblebooleanOm udgiften 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"
}

Opdater udgift (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): Opdateret udgiftsobjekt.

Slet udgift

DELETE /v1/expenses/:id

Svar: 204 No Content


Kunder (/clients)

Vis kunder

GET /v1/clients

Accepterer limit, offset, from og to (filtrerer efter createdAt).

curl "https://api.frihet.io/v1/clients?limit=50" \
-H "X-API-Key: fri_tu-clave-aqui"

Hent kunde

GET /v1/clients/:id

Opret kunde

POST /v1/clients

Påkrævede felter:

FeltTypeBeskrivelse
namestringKundenavn (maks. 10.000 tegn)

Valgfrie felter:

FeltTypeBeskrivelse
emailstringKontakt e-mail
phonestringTelefon
taxIdstringNIF/CIF/VAT
addressobjectAdresse (se struktur nedenfor)

Struktur af address:

FeltTypeBeskrivelse
streetstringGade og nummer
citystringBy
statestringProvins eller delstat
postalCodestringPostnummer
countrystringLand

Alle felter 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"
}

Opdater 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): Opdateret kundeobjekt.

Slet kunde

DELETE /v1/clients/:id

Svar: 204 No Content


CRM: Kontaktpersoner, Aktiviteter og Noter

Kunder har tre underkollektioner til styring af CRM-relationer: kontaktpersoner, aktiviteter og noter. Alle endpoints kræver et gyldigt clientId i URL'en.

Kontaktpersoner (/v1/clients/:id/contacts)

Vis 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"
Opret kontakt
POST /v1/clients/:id/contacts

Påkrævede felter:

FeltTypeBeskrivelse
namestringNavn på kontaktperson

Valgfrie felter:

FeltTypeBeskrivelse
emailstringKontaktens e-mail
phonestringTelefon
rolestringTitel eller rolle (f.eks. "Finansdirektør")
isPrimarybooleanOm det er kundens primære kontaktperson
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"
}
Opdater 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): Opdateret kontaktobjekt.

Slet 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)

Aktivitetstidslinjen registrerer interaktioner med en kunde. Systemaktiviteter (såsom invoice_created, quote_sent osv.) genereres automatisk. Du kan også oprette manuelle aktiviteter.

Uforanderlige

Aktiviteter er uforanderlige. De kan ikke opdateres eller slettes, når de først er oprettet.

Vis 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"
Opret aktivitet
POST /v1/clients/:id/activities

Påkrævede felter:

FeltTypeBeskrivelse
typestringAktivitetstype: call, email, meeting eller task
titlestringBeskrivende titel for aktiviteten

Valgfrie felter:

FeltTypeBeskrivelse
descriptionstringDetaljeret beskrivelse
metadataobjectYderligere data i frit format
Aktivitetstyper

Typerne call, email, meeting og task er til manuelt oprettede aktiviteter. Systemtyper som invoice_created, quote_sent eller expense_linked genereres automatisk og kan ikke oprettes 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"
}

Noter (/v1/clients/:id/notes)

Vis noter
GET /v1/clients/:id/notes
curl "https://api.frihet.io/v1/clients/cli001/notes" \
-H "X-API-Key: fri_tu-clave-aqui"
Hent note
GET /v1/clients/:id/notes/:noteId
curl "https://api.frihet.io/v1/clients/cli001/notes/note001" \
-H "X-API-Key: fri_tu-clave-aqui"
Opret note
POST /v1/clients/:id/notes

Påkrævede felter:

FeltTypeBeskrivelse
contentstringNotens indhold
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"
}
Opdater note
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): Opdateret noteobjekt.

Slet note
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)

Vis produkter

GET /v1/products

Accepterer limit, offset, from og to (filtrerer efter createdAt).

Hent produkt

GET /v1/products/:id

Opret produkt

POST /v1/products

Påkrævede felter:

FeltTypeBeskrivelse
namestringNavn på produkt eller service (maks. 10.000 tegn)
unitPricenumberEnhedspris

Valgfrie felter:

FeltTypeBeskrivelse
descriptionstringBeskrivelse (maks. 10.000 tegn)
taxRatenumberSkattesats i procent (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"
}

Opdater 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): Opdateret produktobjekt.

Slet produkt

DELETE /v1/products/:id

Svar: 204 No Content


Tilbud (/quotes)

Vis tilbud

GET /v1/quotes

Forespørgselsparametre:

ParameterTypeStandardBeskrivelse
limitinteger50Resultater pr. side (maks. 100)
offsetinteger0Antal resultater, der skal springes over
statusstring--Filtrer efter status: kladde, sendt, accepteret, afvist, udløbet
fromstring--Startdato (ISO 8601). Filtrerer efter issueDate
tostring--Slutdato (ISO 8601). Filtrerer efter issueDate
curl "https://api.frihet.io/v1/quotes?status=sent" \
-H "X-API-Key: fri_tu-clave-aqui"

Hent tilbud

GET /v1/quotes/:id

Opret tilbud

POST /v1/quotes

Påkrævede felter:

FeltTypeBeskrivelse
clientNamestringKundenavn (maks. 10.000 tegn)
itemsarrayTilbudslinjer. Hver linje: { description, quantity, unitPrice }

Valgfrie felter:

FeltTypeBeskrivelse
validUntilstringGyldighedsdato (ISO 8601)
notesstringNoter eller betingelser (maks. 10.000 tegn)
statusstringkladde (standard), sendt, accepteret, afvist, udløbet
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"
}

Opdater tilbud (PUT eller PATCH)

PUT /v1/quotes/:id
PATCH /v1/quotes/:id

Slet tilbud

DELETE /v1/quotes/:id

Svar: 204 No Content

Download tilbud i PDF

GET /v1/quotes/:id/pdf

Fungerer 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-mail

POST /v1/quotes/:id/send

Samme felter som /invoices/:id/send (recipientEmail, recipientName, customMessage, locale). Hvis tilbuddet er i status kladde, opdateres det automatisk til sendt.


Batchoperationer (/batch)

Alle primære ressourcer understøtter batchoprettelse. Send et array med op til 50 elementer i én enkelt anmodning.

POST /v1/{resource}/batch

Understøttede ressourcer: invoices, expenses, clients, products, quotes

Anmodningens brødtekst:

{
"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 et af elementerne fejler validering, oprettes resten alligevel. Individuelle fejl returneres i results-array'et:

{
"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 }
}

Grænser:

KonceptGrænse
Elementer pr. batch50 maks.
Anmodningsstørrelse1 MB maks.

Idempotens

POST-anmodninger accepterer en Idempotency-Key-header for at undgå duplikat oprettelse af ressourcer ved netværksforsøg. Hvis den samme nøgle sendes inden for de næste 24 timer, returnerer API'en det originale svar uden at udføre operationen igen.

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 }]
}'

Opførsel:

ScenarieResultat
Første anmodning med nøglenRessourcen oprettes normalt
Gentagen anmodning med samme nøgle (inden for 24 timer)Det originale svar returneres, uden duplikering
Samme nøgle efter 24 timerBehandles som en ny anmodning

Svarheader:

Når API'en registrerer en gentaget nøgle, inkluderer den X-Idempotent-Replayed: true-headeren, så forbrugeren ved, at svaret er en gentagelse.

HTTP/1.1 201 Created
X-Idempotent-Replayed: true
Content-Type: application/json

Krav:

  • Nøglen må højst være 64 tegn lang
  • Vi anbefaler at bruge UUID v4
  • Gælder kun for POST-anmodninger (oprettelse af ressourcer)

Søgning

Liste-endpoints understøtter fuldtekstsøgning via parameteren q:

curl "https://api.frihet.io/v1/invoices?q=acme" \
-H "X-API-Key: fri_tu-clave-aqui"

Søgningen anvendes på ressourcens primære tekstfelter (kundenavn, beskrivelse, noter osv.). Den kan kombineres med eksisterende filtre (status, from, to).


Intelligens-endpoints

Disse endpoints leverer aggregerede data og forretningskontekst. De er især nyttige for AI-agenter og eksterne dashboards.

Forretningskontekst (/context)

GET /v1/context

Returnerer en komplet oversigt over virksomheden, designet til at forsyne AI-agenter med den nødvendige kontekst for at træffe informerede beslutninger. Inkluderer finansiel oversigt, nylig aktivitet, alarmer og skattekonfiguration.

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": "Factura para 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 P&L (/monthly)

GET /v1/monthly?month=YYYY-MM

Returnerer resultatopgørelsen (P&L) for en specifik måned: fakturerede indtægter, udgifter pr. kategori, nettooverskud og sammenligning med den foregående 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 skattetal (/quarterly)

GET /v1/quarterly?quarter=YYYY-Q1

Returnerer skattetal for et kvartal, forberedt til indberetning af Model 303 (Moms) og Model 130 (IRPF). Inkluderer skattepligtige baser, påløbne afgifter, fradragsberettigede afgifter og opgørelsens resultat.

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
}
}
tip

Endpoints /context, /monthly og /quarterly er designet til at være det ideelle indgangspunkt for AI-agenter. De giver den nødvendige information i et enkelt kald, uden behov for at konsultere flere individuelle endpoints.


Finansielt dashboard (/summary)

GET /v1/summary

Returnerer en finansiel oversigt over virksomheden: indtægter, udgifter, overskud og tællere.

Forespørgselsparametre:

ParameterTypeBeskrivelse
fromstringStartdato (ISO 8601)
tostringSlutdato (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 }
}

Fejlkoder

API'en bruger standard HTTP-koder. Fejlsvar inkluderer et JSON-objekt med felterne error og, valgfrit, message og details.

KodeBetydningBeskrivelse
400Bad RequestPåkrævet felt mangler, forkert format eller ikke-tilladt felt
401UnauthorizedAPI-nøglen er ikke angivet, er ugyldig, har forkert format eller er udløbet
403ForbiddenAPI-nøglen har ikke tilladelse til at tilgå denne ressource
404Not FoundDen anmodede ressource findes ikke
405Method Not AllowedHTTP-metoden understøttes ikke for dette endpoint
413Payload Too LargeAnmodningens brødtekst overstiger 1 MB
422Unprocessable EntityGyldige data, men serveren kan ikke behandle dem (f.eks. skatteprofil ikke konfigureret)
429Too Many RequestsGrænsen på 100 anmodninger pr. minut er overskredet
500Internal Server ErrorIntern serverfejl

Fejlsvarstrukturen

Valideringsfejl (400):

{
"error": "Validation error",
"details": [
{
"code": "invalid_type",
"expected": "string",
"received": "undefined",
"path": ["clientName"],
"message": "Required"
}
]
}

Valideringsfejl bruger Zod-formatet. Feltet path angiver, hvilket felt der indeholder fejlen, og message beskriver problemet.

Ugyldig eller udløbet API-nøgle (401):

{
"error": "Invalid or expired API key"
}

Ugyldigt nøgleformat (401):

{
"error": "Invalid API key format"
}

Ressource ikke fundet (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 fejl (500):

{
"error": "Internal server error"
}

Sideinddeling

Liste-endpoints returnerer sideinddelte resultater med følgende struktur:

{
"data": [],
"total": 142,
"limit": 50,
"offset": 0
}
  • total: det samlede antal poster, der opfylder de anvendte filtre
  • limit: antallet af poster, der returneres på denne side (maks. 100)
  • offset: antallet af overspringede poster (maks. 10.000)

For at hente den næste side:

curl "https://api.frihet.io/v1/invoices?limit=50&offset=50" \
-H "X-API-Key: fri_tu-clave-aqui"

Resultaterne sorteres efter ressourcens naturlige dato i faldende rækkefølge (nyeste først):

  • Fakturaer og tilbud: issueDate
  • Udgifter: date
  • Kunder og produkter: createdAt

Strikt validering

API'en bruger strikt validering (Zod strict mode). Anmodninger med ukendte felter afvises med en 400-fejl:

{
"error": "Validation error",
"details": [
{
"code": "unrecognized_keys",
"keys": ["campoInventado"],
"path": [],
"message": "Unrecognized key(s) in object: 'campoInventado'"
}
]
}

Dette forhindrer tavse fejl på grund af tastefejl i feltnavnene.


CORS

API'en understøtter CORS for anmodninger fra browseren. De tilladte oprindelser er:

  • https://app.frihet.io
  • https://frihet.io
  • https://www.frihet.io

For server-til-server-integrationer er CORS ikke relevant. Hvis du skal have adgang til API'en fra et andet domæne i browseren, skal du bruge en proxy i din backend.


Sikkerhedshearders

Alle svar inkluderer sikkerhedshearders:

HeaderVærdi
X-Content-Type-Optionsnosniff
X-Frame-OptionsDENY
X-XSS-Protection1; mode=block
X-Request-IdUnikt anmodnings-ID (nyttigt til debugging)

OAuth for MCP

Endpointet POST /api/oauth/api-key gør det muligt automatisk at tildele en API-nøgle via MCP's OAuth-flow. MCP-serveren bruger dette endpoint internt -- du behøver ikke at kalde det direkte.

Flowet:

  1. Brugeren autentificerer via Firebase Auth
  2. MCP-klienten sender Firebase-tokenet til /api/oauth/api-key
  3. Serveren returnerer en ny nøgle fri_xxx... mærket som "MCP OAuth"
  4. Nøglen udløber efter 365 dage

Grænse: 5 aktive nøgler pr. bruger. Hvis grænsen overskrides, svarer endpointet med en 429.


Bedste praksis

  1. Opbevar API-nøglen sikkert. Inkluder den aldrig i frontend-kode, offentlige repositories eller logs.
  2. Håndter rate limiting. Implementer eksponentiel backoff, hvis du modtager en 429.
  3. Brug sideinddeling. Anmod ikke om alle poster på én gang; iterer med limit og offset.
  4. Verificer svarkoderne. Antag ikke, at alle anmodninger vil lykkes.
  5. Roter nøgler regelmæssigt. Opret en ny nøgle, opdater din integration og tilbagekald den tidligere.
  6. Brug altid HTTPS. Alle anmodninger til API'en skal ske via HTTPS.
  7. Brug filtre. Parametrene status, from og to reducerer mængden af overførte data.
  8. Udnyt PATCH. Ved delvise opdateringer skal du kun sende de ændrede felter.