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.
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:
- Gå till Inställningar > Utvecklare > API-nycklar
- Klicka på Skapa nyckel
- Tilldela ett beskrivande namn (till exempel
integration-bokföring) - Ange eventuellt ett utgångsdatum i antal dagar. Om du lämnar fältet tomt, upphör nyckeln inte att gälla.
- 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:
- Skapa en ny nyckel med samma omfång
- Uppdatera din integration för att använda den nya nyckeln
- Kontrollera att förfrågningarna fungerar korrekt
- Å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:
| Header | Beskrivning | Exempel |
|---|---|---|
X-RateLimit-Limit | Tillåtna förfrågningar per minut | 100 |
X-RateLimit-Remaining | Återstående förfrågningar i det aktuella fönstret | 87 |
X-RateLimit-Reset | Unix-tidsstämpel (sekunder) när fönstret återställs | 1709312400 |
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 iX-RateLimit-Resetinnan du försöker igen. - Övervaka
X-RateLimit-Remainingfö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.
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:
| Parameter | Typ | Standard | Beskrivning |
|---|---|---|---|
limit | integer | 50 | Resultat per sida (max 100) |
offset | integer | 0 | Antal resultat att hoppa över (max 10 000) |
status | string | -- | Filtrera efter status: draft, sent, paid, overdue, cancelled |
from | string | -- | Startdatum (ISO 8601: ÅÅÅÅ-MM-DD). Filtrerar efter issueDate |
to | string | -- | 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ält | Typ | Beskrivning |
|---|---|---|
clientName | string | Kundens namn (max 10 000 tecken) |
items | array | Lista över fakturarader. Varje rad: { description, quantity, unitPrice } |
Valfria fält:
| Fält | Typ | Beskrivning |
|---|---|---|
status | string | draft (standard), sent, paid, overdue, cancelled |
issueDate | string | Utfärdandedatum (ISO 8601). Standard: idag |
dueDate | string | Förfallodatum (ISO 8601) |
notes | string | Interna anteckningar (max 10 000 tecken) |
taxRate | number | Skattesats i procent (0-100). Ex: 21 för moms 21% |
Struktur för varje rad (items[]):
| Fält | Typ | Obligatoriskt | Beskrivning |
|---|---|---|---|
description | string | Ja | Beskrivning av posten (max 10 000 tecken) |
quantity | number | Ja | Kvantitet |
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": "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.
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ält | Typ | Obligatoriskt | Beskrivning |
|---|---|---|---|
recipientEmail | string | Ja | Mottagarens e-postadress (max 255 tecken) |
recipientName | string | Nej | Mottagarens namn (max 200 tecken) |
customMessage | string | Nej | Anpassat meddelande i e-postmeddelandets brödtext (max 5 000 tecken) |
locale | string | Nej | E-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ält | Typ | Obligatoriskt | Beskrivning |
|---|---|---|---|
paidDate | string | Nej | Betalningsdatum (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:
| Parameter | Typ | Standard | Beskrivning |
|---|---|---|---|
limit | integer | 50 | Resultat per sida (max 100) |
offset | integer | 0 | Antal resultat att hoppa över |
from | string | -- | Startdatum (ISO 8601). Filtrerar efter date |
to | string | -- | 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ält | Typ | Beskrivning |
|---|---|---|
description | string | Beskrivning av utgiften (max 10 000 tecken) |
amount | number | Utgiftens belopp |
Valfria fält:
| Fält | Typ | Beskrivning |
|---|---|---|
category | string | Utgiftens kategori (max 10 000 tecken) |
date | string | Utgiftens datum (ISO 8601). Standard: idag |
vendor | string | Leverantör (max 10 000 tecken) |
taxDeductible | boolean | Om 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ält | Typ | Beskrivning |
|---|---|---|
name | string | Kundens namn (max 10 000 tecken) |
Valfria fält:
| Fält | Typ | Beskrivning |
|---|---|---|
email | string | Kontakt-e-post |
phone | string | Telefon |
taxId | string | NIF/CIF/Momsreg.nr |
address | object | Adress (se struktur nedan) |
Struktur för address:
| Fält | Typ | Beskrivning |
|---|---|---|
street | string | Gatuadress och nummer |
city | string | Ort |
state | string | Län eller stat |
postalCode | string | Postnummer |
country | string | Land |
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ält | Typ | Beskrivning |
|---|---|---|
name | string | Namn på kontaktpersonen |
Valfria fält:
| Fält | Typ | Beskrivning |
|---|---|---|
email | string | Kontaktens e-post |
phone | string | Telefon |
role | string | Befattning eller roll (ex. "Ekonomichef") |
isPrimary | boolean | Om 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.
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ält | Typ | Beskrivning |
|---|---|---|
type | string | Typ av aktivitet: call, email, meeting eller task |
title | string | Beskrivande titel för aktiviteten |
Valfria fält:
| Fält | Typ | Beskrivning |
|---|---|---|
description | string | Detaljerad beskrivning |
metadata | object | Ytterligare data i fritt format |
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ält | Typ | Beskrivning |
|---|---|---|
content | string | Anteckningens 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ält | Typ | Beskrivning |
|---|---|---|
name | string | Namn på produkt eller tjänst (max 10 000 tecken) |
unitPrice | number | Enhetspris |
Valfria fält:
| Fält | Typ | Beskrivning |
|---|---|---|
description | string | Beskrivning (max 10 000 tecken) |
taxRate | number | Skattesats 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:
| Parameter | Typ | Standard | Beskrivning |
|---|---|---|---|
limit | integer | 50 | Resultat per sida (max 100) |
offset | integer | 0 | Antal resultat att hoppa över |
status | string | -- | Filtrera efter status: draft, sent, accepted, rejected, expired |
from | string | -- | Startdatum (ISO 8601). Filtrerar efter issueDate |
to | string | -- | 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ält | Typ | Beskrivning |
|---|---|---|
clientName | string | Kundens namn (max 10 000 tecken) |
items | array | Offertrader. Varje rad: { description, quantity, unitPrice } |
Valfria fält:
| Fält | Typ | Beskrivning |
|---|---|---|
validUntil | string | Giltig till datum (ISO 8601) |
notes | string | Anteckningar eller villkor (max 10 000 tecken) |
status | string | draft (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:
| Koncept | Gräns |
|---|---|
| Element per batch | Max 50 |
| Förfrågans storlek | Max 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:
| Scenario | Resultat |
|---|---|
| Första förfrågan med nyckeln | Resursen skapas normalt |
| Upprepad förfrågan med samma nyckel (inom 24h) | Det ursprungliga svaret returneras, utan att duplicera |
| Samma nyckel efter 24h | Behandlas 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
}
}
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:
| Parameter | Typ | Beskrivning |
|---|---|---|
from | string | Startdatum (ISO 8601) |
to | string | Slutdatum (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.
| Kod | Betydelse | Beskrivning |
|---|---|---|
400 | Bad Request | Ett obligatoriskt fält saknas, felaktigt format eller fält inte tillåtet |
401 | Unauthorized | API-nyckeln har inte angetts, är ogiltig, har felaktigt format eller har gått ut |
403 | Forbidden | API-nyckeln har inte behörighet att komma åt denna resurs |
404 | Not Found | Den begärda resursen finns inte |
405 | Method Not Allowed | HTTP-metoden stöds inte för denna endpoint |
413 | Payload Too Large | Förfrågans kropp överstiger 1 MB |
422 | Unprocessable Entity | Giltig data men servern kan inte bearbeta den (t.ex. skatteprofil inte konfigurerad) |
429 | Too Many Requests | Gränsen på 100 förfrågningar per minut har överskridits |
500 | Internal Server Error | Internt 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 filtrenlimit: 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.iohttps://frihet.iohttps://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:
| Header | Värde |
|---|---|
X-Content-Type-Options | nosniff |
X-Frame-Options | DENY |
X-XSS-Protection | 1; mode=block |
X-Request-Id | Unikt 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:
- Användaren autentiserar sig via Firebase Auth
- MCP-klienten skickar Firebase-token till
/api/oauth/api-key - Servern returnerar en ny nyckel
fri_xxx...märkt som "MCP OAuth" - 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
- Förvara API-nyckeln säkert. Inkludera den aldrig i frontend-kod, offentliga repositories eller loggar.
- Hantera rate limiting. Implementera exponentiell backoff om du får en
429. - Använd paginering. Begär inte alla poster på en gång; iterera med
limitochoffset. - Verifiera svarskoder. Anta inte att alla förfrågningar kommer att lyckas.
- Rotera nycklarna regelbundet. Skapa en ny nyckel, uppdatera din integration och återkalla den gamla.
- Använd alltid HTTPS. Alla förfrågningar till API:et måste ske över HTTPS.
- Använd filter. Parametrarna
status,fromochtominskar mängden överförd data. - Dra nytta av PATCH. För partiella uppdateringar, skicka endast de modifierade fälten.