Hoppa till huvudinnehåll

API REST

Frihet API REST ger dig programmatisk åtkomst till och möjlighet att manipulera resurserna i ditt konto. All kommunikation sker över HTTPS och svaren är JSON.

Bas-URL

https://api.frihet.io/v1

Alla endpoints som beskrivs på den här sidan är relativa till denna bas-URL.

Upptäckt: En GET-förfrågan till roten (https://api.frihet.io/) returnerar de primära länkarna utan att autentisering behövs:

{
"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 finns tillgänglig på https://api.frihet.io/openapi.yaml.

SDK tillgänglig

Om du använder TypeScript eller JavaScript förenklar det officiella SDK:t 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


Autentisering

Varje förfrågan måste inkludera en API-nyckel i X-API-Key-headern. Nycklarna skapas från Inställningar > Utvecklare > API-nycklar i Frihet-panelen.

Nycklarna har prefixet fri_ följt av 32 slumpmässiga base64url-kodade byte. Exempel: fri_aBcDeFgHiJkLmNoPqRsTuVwXyZ012345678.

curl https://api.frihet.io/v1/clients \
-H "X-API-Key: fri_din-nyckel-här"

Alternativt kan du skicka nyckeln som en Bearer token i Authorization-headern:

curl https://api.frihet.io/v1/clients \
-H "Authorization: Bearer fri_din-nyckel-här"

Nyckelsäkerhet

  • Nyckeln i klartext visas endast en gång, vid skapandet. Den kan inte återställas efteråt.
  • Servern lagrar en SHA-256-hash av nyckeln. Även vid ett dataintrång är den ursprungliga nyckeln inte återställbar.
  • Du kan skapa nycklar med konfigurerbart utgångsdatum.
  • Om du misstänker att en nyckel har komprometterats, återkalla den omedelbart från panelen.

Nyckelns livscykel

Skapa en nyckel:

  1. Gå till Inställningar > Utvecklare > API-nycklar
  2. Klicka på Skapa nyckel
  3. Tilldela ett beskrivande namn (till exempel integration-bokföring)
  4. Ange eventuellt ett utgångsdatum i antal dagar. Om du lämnar fältet tomt, upphör nyckeln inte att gälla.
  5. Kopiera nyckeln omedelbart – du kommer inte kunna se den igen.

Utgång:

Nycklar med utgångsdatum slutar automatiskt att fungera när tidsfristen uppnåtts. Förfrågningar med en utgången nyckel får en 401 Unauthorized.

Återkallande:

Du kan återkalla en nyckel när som helst från Inställningar > Utvecklare > API-nycklar. Återkallandet är omedelbart och oåterkalleligt: pågående förfrågningar med den nyckeln kommer att misslyckas från det ögonblicket.

Nyckelrotation:

För att rotera en nyckel utan att avbryta tjänsten:

  1. Skapa en ny nyckel med samma omfång
  2. Uppdatera din integration för att använda den nya nyckeln
  3. Kontrollera att förfrågningarna fungerar korrekt
  4. Återkalla den gamla nyckeln

Övervakning:

Varje nyckel visar datum för senaste användning i inställningspanelen. Granska regelbundet inaktiva nycklar och återkalla de som inte längre används.


Rate limiting

Varje API-nyckel har en gräns på 100 förfrågningar per minut. Om gränsen överskrids svarar API:et med en 429-kod:

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

Rate limiting-headers

Alla API-svar inkluderar headers så att du proaktivt kan hantera gränsen:

HeaderBeskrivningExempel
X-RateLimit-LimitTillåtna förfrågningar per minut100
X-RateLimit-RemainingÅterstående förfrågningar i det aktuella fönstret87
X-RateLimit-ResetUnix-tidsstämpel (sekunder) när fönstret återställs1709312400

Exempel 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

Hantering av kod 429:

När du får en 429 använder du headers för att beräkna hur länge du ska vänta innan du försöker 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;
}

Rekommendationer:

  • Om du får en 429, vänta till den tidstämpel som anges i X-RateLimit-Reset innan du försöker igen.
  • Övervaka X-RateLimit-Remaining för att bromsa förfrågningarna innan du når gränsen.
  • Distribuera förfrågningarna över tid istället för att skicka i pulser.

Förfrågans storlek

Kroppen för POST-, PUT- och PATCH-förfrågningar får inte överstiga 1 MB. Större förfrågningar får en 413-kod.


Resurser

API:et exponerar 7 huvudresurser: invoices, expenses, clients, products, quotes, vendors och webhooks. Alla stöder kompletta CRUD-operationer (GET, POST, PUT/PATCH, DELETE). Dessutom har kunder CRM-underkollektioner: contacts, activities och notes.

PATCH vs PUT

Både PUT och PATCH accepterar partiella uppdateringar. Du behöver inte skicka hela resursen – endast de fält du vill ändra.

Fakturor (/invoices)

Lista fakturor

GET /v1/invoices

Frågeparametrar:

ParameterTypStandardBeskrivning
limitinteger50Resultat per sida (max 100)
offsetinteger0Antal resultat att hoppa över (max 10 000)
statusstring--Filtrera efter status: draft, sent, paid, overdue, cancelled
fromstring--Startdatum (ISO 8601: ÅÅÅÅ-MM-DD). Filtrerar efter issueDate
tostring--Slutdatum (ISO 8601: ÅÅÅÅ-MM-DD). Filtrerar efter issueDate

Exempel:

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
}

Hämta 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"
}

Skapa faktura

POST /v1/invoices

Obligatoriska fält:

FältTypBeskrivning
clientNamestringKundens namn (max 10 000 tecken)
itemsarrayLista över fakturarader. Varje rad: { description, quantity, unitPrice }

Valfria fält:

FältTypBeskrivning
statusstringdraft (standard), sent, paid, overdue, cancelled
issueDatestringUtfärdandedatum (ISO 8601). Standard: idag
dueDatestringFörfallodatum (ISO 8601)
notesstringInterna anteckningar (max 10 000 tecken)
taxRatenumberSkattesats i procent (0-100). Ex: 21 för moms 21%

Struktur för varje rad (items[]):

FältTypObligatorisktBeskrivning
descriptionstringJaBeskrivning av posten (max 10 000 tecken)
quantitynumberJaKvantitet
unitPricenumberJaEnhetspris
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": "Projekt 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": "Projekt Q1 2026",
"createdAt": "2026-02-12T09:00:00.000Z",
"updatedAt": "2026-02-12T09:00:00.000Z"
}

Uppdatera faktura (PUT eller PATCH)

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

Du behöver bara skicka de fält du vill ändra. Fält som inte inkluderas förblir oförändrade.

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": "Skickad till kunden"
}'

Svar (200): Uppdaterat fakturaobjekt.

varning

Om du skickar items, måste du skicka hela arrayen – partiella uppdateringar av enskilda rader accepteras inte.

Ta bort 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

Ladda ner faktura i PDF

GET /v1/invoices/:id/pdf

Returnerar fakturan som en application/pdf med headern Content-Disposition: attachment.

curl -o factura.pdf https://api.frihet.io/v1/invoices/abc123/pdf \
-H "X-API-Key: fri_tu-clave-aqui"

Skicka faktura via e-post

POST /v1/invoices/:id/send

Skickar fakturan till den angivna mottagaren via Resend. Om fakturan är i draft-status uppdateras den automatiskt till sent.

Fält:

FältTypObligatorisktBeskrivning
recipientEmailstringJaMottagarens e-postadress (max 255 tecken)
recipientNamestringNejMottagarens namn (max 200 tecken)
customMessagestringNejAnpassat meddelande i e-postmeddelandets brödtext (max 5 000 tecken)
localestringNejE-postmeddelandets 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..." }

Markera faktura som betald

POST /v1/invoices/:id/paid
FältTypObligatorisktBeskrivning
paidDatestringNejBetalningsdatum (ISO 8601). Standard: idag
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)

Lista utgifter

GET /v1/expenses

Frågeparametrar:

ParameterTypStandardBeskrivning
limitinteger50Resultat per sida (max 100)
offsetinteger0Antal resultat att hoppa över
fromstring--Startdatum (ISO 8601). Filtrerar efter date
tostring--Slutdatum (ISO 8601). Filtrerar 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
}

Hämta utgift

GET /v1/expenses/:id

Skapa utgift

POST /v1/expenses

Obligatoriska fält:

FältTypBeskrivning
descriptionstringBeskrivning av utgiften (max 10 000 tecken)
amountnumberUtgiftens belopp

Valfria fält:

FältTypBeskrivning
categorystringUtgiftens kategori (max 10 000 tecken)
datestringUtgiftens datum (ISO 8601). Standard: idag
vendorstringLeverantör (max 10 000 tecken)
taxDeductiblebooleanOm utgiften är avdragsgill
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"
}

Uppdatera 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): Uppdaterat utgiftsobjekt.

Ta bort utgift

DELETE /v1/expenses/:id

Svar: 204 No Content


Kunder (/clients)

Lista kunder

GET /v1/clients

Accepterar limit, offset, from och to (filtrerar efter createdAt).

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

Hämta kund

GET /v1/clients/:id

Skapa kund

POST /v1/clients

Obligatoriska fält:

FältTypBeskrivning
namestringKundens namn (max 10 000 tecken)

Valfria fält:

FältTypBeskrivning
emailstringKontakt-e-post
phonestringTelefon
taxIdstringNIF/CIF/Momsreg.nr
addressobjectAdress (se struktur nedan)

Struktur för address:

FältTypBeskrivning
streetstringGatuadress och nummer
citystringOrt
statestringLän eller stat
postalCodestringPostnummer
countrystringLand

Alla fält i address är valfria.

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

Uppdatera kund (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): Uppdaterat kundobjekt.

Ta bort kund

DELETE /v1/clients/:id

Svar: 204 No Content


CRM: Kontaktpersoner, Aktiviteter och Anteckningar

Kunder har tre underkollektioner för att hantera CRM-relationer: kontaktpersoner, aktiviteter och anteckningar. Alla endpoints kräver ett giltigt clientId i URL:en.

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

Lista kontakter
GET /v1/clients/:id/contacts
curl "https://api.frihet.io/v1/clients/cli001/contacts" \
-H "X-API-Key: fri_tu-clave-aqui"
Hämta 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"
Skapa kontakt
POST /v1/clients/:id/contacts

Obligatoriska fält:

FältTypBeskrivning
namestringNamn på kontaktpersonen

Valfria fält:

FältTypBeskrivning
emailstringKontaktens e-post
phonestringTelefon
rolestringBefattning eller roll (ex. "Ekonomichef")
isPrimarybooleanOm det är kundens primära 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": "Ekonomichef",
"isPrimary": true
}'

Svar (201):

{
"id": "con001",
"name": "Maria Garcia",
"email": "maria@acme.es",
"phone": "+34 612 345 678",
"role": "Ekonomichef",
"isPrimary": true,
"createdAt": "2026-03-15T10:00:00.000Z",
"updatedAt": "2026-03-15T10:00:00.000Z"
}
Uppdatera 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): Uppdaterat kontaktobjekt.

Ta bort 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 registrerar interaktioner med en kund. Systemaktiviteter (som invoice_created, quote_sent, etc.) genereras automatiskt. Du kan också skapa manuella aktiviteter.

Oföränderliga

Aktiviteter är oföränderliga. De kan inte uppdateras eller raderas när de väl har skapats.

Lista aktiviteter
GET /v1/clients/:id/activities
curl "https://api.frihet.io/v1/clients/cli001/activities" \
-H "X-API-Key: fri_tu-clave-aqui"
Hämta 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"
Skapa aktivitet
POST /v1/clients/:id/activities

Obligatoriska fält:

FältTypBeskrivning
typestringTyp av aktivitet: call, email, meeting eller task
titlestringBeskrivande titel för aktiviteten

Valfria fält:

FältTypBeskrivning
descriptionstringDetaljerad beskrivning
metadataobjectYtterligare data i fritt format
Aktivitetstyper

Typerna call, email, meeting och task är för manuellt skapade aktiviteter. Systemtyper som invoice_created, quote_sent eller expense_linked genereras automatiskt och kan inte skapas via API:et.

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": "Uppföljningssamtal offert Q2",
"description": "Vi diskuterade offertvillkoren. Väntar på bekräftelse.",
"metadata": {
"duration": "15min",
"outcome": "pending"
}
}'

Svar (201):

{
"id": "act001",
"type": "call",
"title": "Uppföljningssamtal offert Q2",
"description": "Vi diskuterade offertvillkoren. Väntar på bekräftelse.",
"metadata": {
"duration": "15min",
"outcome": "pending"
},
"createdAt": "2026-03-15T14:30:00.000Z"
}

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

Lista anteckningar
GET /v1/clients/:id/notes
curl "https://api.frihet.io/v1/clients/cli001/notes" \
-H "X-API-Key: fri_tu-clave-aqui"
Hämta anteckning
GET /v1/clients/:id/notes/:noteId
curl "https://api.frihet.io/v1/clients/cli001/notes/note001" \
-H "X-API-Key: fri_tu-clave-aqui"
Skapa anteckning
POST /v1/clients/:id/notes

Obligatoriska fält:

FältTypBeskrivning
contentstringAnteckningens innehåll
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": "Kund intresserad av Business-planen. Kontakta i april för förnyelse."
}'

Svar (201):

{
"id": "note001",
"content": "Kund intresserad av Business-planen. Kontakta i april för förnyelse.",
"createdAt": "2026-03-15T16:00:00.000Z",
"updatedAt": "2026-03-15T16:00:00.000Z"
}
Uppdatera anteckning
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": "Kund intresserad av Business-planen. Möte bekräftat 5 april."
}'

Svar (200): Uppdaterat anteckningsobjekt.

Ta bort anteckning
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)

Lista produkter

GET /v1/products

Accepterar limit, offset, from och to (filtrerar efter createdAt).

Hämta produkt

GET /v1/products/:id

Skapa produkt

POST /v1/products

Obligatoriska fält:

FältTypBeskrivning
namestringNamn på produkt eller tjänst (max 10 000 tecken)
unitPricenumberEnhetspris

Valfria fält:

FältTypBeskrivning
descriptionstringBeskrivning (max 10 000 tecken)
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": "Konsulttimme",
"unitPrice": 75,
"description": "Strategisk konsultation",
"taxRate": 21
}'

Svar (201):

{
"id": "prod001",
"name": "Konsulttimme",
"unitPrice": 75,
"description": "Strategisk konsultation",
"taxRate": 21,
"createdAt": "2026-02-12T10:00:00.000Z",
"updatedAt": "2026-02-12T10:00:00.000Z"
}

Uppdatera 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): Uppdaterat produktobjekt.

Ta bort produkt

DELETE /v1/products/:id

Svar: 204 No Content


Offerter (/quotes)

Lista offerter

GET /v1/quotes

Frågeparametrar:

ParameterTypStandardBeskrivning
limitinteger50Resultat per sida (max 100)
offsetinteger0Antal resultat att hoppa över
statusstring--Filtrera efter status: draft, sent, accepted, rejected, expired
fromstring--Startdatum (ISO 8601). Filtrerar efter issueDate
tostring--Slutdatum (ISO 8601). Filtrerar efter issueDate
curl "https://api.frihet.io/v1/quotes?status=sent" \
-H "X-API-Key: fri_tu-clave-aqui"

Hämta offert

GET /v1/quotes/:id

Skapa offert

POST /v1/quotes

Obligatoriska fält:

FältTypBeskrivning
clientNamestringKundens namn (max 10 000 tecken)
itemsarrayOffertrader. Varje rad: { description, quantity, unitPrice }

Valfria fält:

FältTypBeskrivning
validUntilstringGiltig till datum (ISO 8601)
notesstringAnteckningar eller villkor (max 10 000 tecken)
statusstringdraft (standard), sent, accepted, rejected, expired
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": "Webbutveckling", "quantity": 80, "unitPrice": 60 },
{ "description": "UX-design", "quantity": 20, "unitPrice": 55 }
],
"validUntil": "2026-04-01",
"notes": "Inkluderar 2 granskningsrundor"
}'

Svar (201):

{
"id": "quo001",
"clientName": "Design Studio SL",
"items": [
{ "description": "Webbutveckling", "quantity": 80, "unitPrice": 60 },
{ "description": "UX-design", "quantity": 20, "unitPrice": 55 }
],
"status": "draft",
"validUntil": "2026-04-01",
"notes": "Inkluderar 2 granskningsrundor",
"createdAt": "2026-02-12T11:00:00.000Z",
"updatedAt": "2026-02-12T11:00:00.000Z"
}

Uppdatera offert (PUT eller PATCH)

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

Ta bort offert

DELETE /v1/quotes/:id

Svar: 204 No Content

Ladda ner offert i PDF

GET /v1/quotes/:id/pdf

Fungerar på samma sätt som /invoices/:id/pdf. Returnerar application/pdf.

curl -o presupuesto.pdf https://api.frihet.io/v1/quotes/quo001/pdf \
-H "X-API-Key: fri_tu-clave-aqui"

Skicka offert via e-post

POST /v1/quotes/:id/send

Samma fält som /invoices/:id/send (recipientEmail, recipientName, customMessage, locale). Om offerten är i draft-status uppdateras den automatiskt till sent.


Batchoperationer (/batch)

Alla huvudresurser stöder batchskapande. Skicka en array med upp till 50 element i en enda förfrågan.

POST /v1/{resource}/batch

Resurser som stöds: invoices, expenses, clients, products, quotes

Förfrågans 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": "Konsultation", "quantity": 1, "unitPrice": 95 }] },
{ "clientName": "TechStart SL", "items": [{ "description": "Utveckling", "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 }
}

Om något av elementen misslyckas med valideringen skapas resten ändå. Individuella fel returneras i results-arrayen:

{
"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äns
Element per batchMax 50
Förfrågans storlekMax 1 MB

Idempotens

POST-förfrågningar accepterar en Idempotency-Key-header för att förhindra dubblettskapande av resurser vid nätverksåterförsök. Om samma nyckel skickas inom de följande 24 timmarna returnerar API:et det ursprungliga svaret utan att utföra 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": "Konsultation", "quantity": 10, "unitPrice": 95 }]
}'

Beteende:

ScenarioResultat
Första förfrågan med nyckelnResursen skapas normalt
Upprepad förfrågan med samma nyckel (inom 24h)Det ursprungliga svaret returneras, utan att duplicera
Samma nyckel efter 24hBehandlas som en ny förfrågan

Svar-header:

När API:et upptäcker en upprepad nyckel, inkluderar det headern X-Idempotent-Replayed: true så att konsumenten vet att svaret är en replika.

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

Krav:

  • Nyckeln får ha maximalt 64 tecken
  • Vi rekommenderar att använda UUID v4
  • Gäller endast POST-förfrågningar (skapa resurser)

Sökning

List-endpoints stöder fulltextsökning med parametern q:

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

Sökningen tillämpas på resursens huvudtextfält (kundnamn, beskrivning, anteckningar, etc.). Den kan kombineras med befintliga filter (status, from, to).


Intelligenta endpoints

Dessa endpoints tillhandahåller aggregerad data och affärskontext. De är särskilt användbara för AI-agenter och externa dashboards.

Affärskontext (/context)

GET /v1/context

Returnerar en komplett översikt över verksamheten, avsedd att förse AI-agenter med den kontext som behövs för att fatta välgrundade beslut. Inkluderar finansiell översikt, nyligen aktivitet, varningar och skatteinställningar.

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 för 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ånatlig resultaträkning (/monthly)

GET /v1/monthly?month=YYYY-MM

Returnerar resultaträkningen (P&L) för en specifik månad: fakturerade intäkter, utgifter per kategori, nettoresultat och jämförelse med föregående månad.

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

Kvartalsvisa skattesiffror (/quarterly)

GET /v1/quarterly?quarter=YYYY-Q1

Returnerar skattesiffrorna för ett kvartal, förberedda för inlämning av Modelo 303 (moms) och Modelo 130 (IRPF). Inkluderar beskattningsunderlag, ackumulerad skatt, avdragsgill skatt och resultat av avräkningen.

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

Endpoints /context, /monthly och /quarterly är utformade för att vara den ideala startpunkten för AI-agenter. De tillhandahåller nödvändig information i ett enda anrop, utan att behöva konsultera flera individuella endpoints.


Finansiell översikt (/summary)

GET /v1/summary

Returnerar en finansiell översikt över verksamheten: intäkter, utgifter, vinst och räknare.

Frågeparametrar:

ParameterTypBeskrivning
fromstringStartdatum (ISO 8601)
tostringSlutdatum (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 }
}

Felkoder

API:et använder standard HTTP-koder. Felsvar inkluderar ett JSON-objekt med fälten error och, valfritt, message och details.

KodBetydelseBeskrivning
400Bad RequestEtt obligatoriskt fält saknas, felaktigt format eller fält inte tillåtet
401UnauthorizedAPI-nyckeln har inte angetts, är ogiltig, har felaktigt format eller har gått ut
403ForbiddenAPI-nyckeln har inte behörighet att komma åt denna resurs
404Not FoundDen begärda resursen finns inte
405Method Not AllowedHTTP-metoden stöds inte för denna endpoint
413Payload Too LargeFörfrågans kropp överstiger 1 MB
422Unprocessable EntityGiltig data men servern kan inte bearbeta den (t.ex. skatteprofil inte konfigurerad)
429Too Many RequestsGränsen på 100 förfrågningar per minut har överskridits
500Internal Server ErrorInternt serverfel

Struktur för felsvar

Valideringsfel (400):

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

Valideringsfel använder Zod-formatet. Fältet path indikerar vilket fält som innehåller felet och message beskriver problemet.

Ogiltig eller utgången nyckel (401):

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

Ogiltigt nyckelformat (401):

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

Resurs hittades inte (404):

{
"error": "Resource not found"
}

Ogiltig status i filter (400):

{
"error": "Invalid status filter",
"message": "Valid values: draft, sent, paid, overdue, cancelled"
}

Rate limit överskridits (429):

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

Internt fel (500):

{
"error": "Internal server error"
}

Paginering

List-endpoints returnerar paginerade resultat med följande struktur:

{
"data": [],
"total": 142,
"limit": 50,
"offset": 0
}
  • total: totalt antal poster som uppfyller de tillämpade filtren
  • limit: antal poster som returneras på denna sida (max 100)
  • offset: antal poster som hoppats över (max 10 000)

För att få nästa sida:

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

Resultaten sorteras efter resursens naturliga datum i fallande ordning (senaste först):

  • Fakturor och offerter: issueDate
  • Utgifter: date
  • Kunder och produkter: createdAt

Strikt validering

API:et använder strikt validering (Zod strict mode). Förfrågningar med okända fält avvisas med ett 400-fel:

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

Detta förhindrar tysta fel på grund av stavfel i fältnamnen.


CORS

API:et stöder CORS för förfrågningar från webbläsaren. Tillåtna ursprung är:

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

För server-till-server-integrationer är CORS inte relevant. Om du behöver komma åt API:et från en annan domän i webbläsaren, använd en proxy i din backend.


Säkerhets-headers

Alla svar inkluderar säkerhets-headers:

HeaderVärde
X-Content-Type-Optionsnosniff
X-Frame-OptionsDENY
X-XSS-Protection1; mode=block
X-Request-IdUnikt ID för förfrågan (användbart för felsökning)

OAuth för MCP

Endpointen POST /api/oauth/api-key möjliggör automatisk tillhandahållande av en API-nyckel via MCP:s OAuth-flöde. MCP-servern använder denna endpoint internt – du behöver inte anropa den direkt.

Flödet:

  1. Användaren autentiserar sig via Firebase Auth
  2. MCP-klienten skickar Firebase-token till /api/oauth/api-key
  3. Servern returnerar en ny nyckel fri_xxx... märkt som "MCP OAuth"
  4. Nyckeln går ut efter 365 dagar

Gräns: 5 aktiva nycklar per användare. Om gränsen överskrids svarar endpointen med en 429.


Bästa praxis

  1. Förvara API-nyckeln säkert. Inkludera den aldrig i frontend-kod, offentliga repositories eller loggar.
  2. Hantera rate limiting. Implementera exponentiell backoff om du får en 429.
  3. Använd paginering. Begär inte alla poster på en gång; iterera med limit och offset.
  4. Verifiera svarskoder. Anta inte att alla förfrågningar kommer att lyckas.
  5. Rotera nycklarna regelbundet. Skapa en ny nyckel, uppdatera din integration och återkalla den gamla.
  6. Använd alltid HTTPS. Alla förfrågningar till API:et måste ske över HTTPS.
  7. Använd filter. Parametrarna status, from och to minskar mängden överförd data.
  8. Dra nytta av PATCH. För partiella uppdateringar, skicka endast de modifierade fälten.