Skip to main content

REST-API

Frihetin REST-API mahdollistaa tilisi resurssien ohjelmallisen käytön ja hallinnan. Kaikki viestintä tapahtuu HTTPS:n kautta ja vastaukset ovat JSON-muodossa.

Perus-URL

https://api.frihet.io/v1

Kaikki tällä sivulla kuvatut rajapinnat ovat suhteellisia tähän perus-URL-osoitteeseen.

Tunnistaminen: GET-pyyntö juureen (https://api.frihet.io/) palauttaa päälinkit ilman autentikointia:

{
"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 -määritys on saatavilla osoitteesta https://api.frihet.io/openapi.yaml.

SDK saatavilla

Jos käytät TypeScriptiä tai JavaScriptiä, virallinen SDK yksinkertaistaa integrointia:

npm install @frihet/sdk
import Frihet from '@frihet/sdk';
const frihet = new Frihet({ apiKey: 'fri_...' });
const invoices = await frihet.invoices.list({ status: 'overdue' });

Arkisto: github.com/Frihet-io/frihet-sdk


Autentikointi

Jokaisen pyynnön on sisällettävä API-avain X-API-Key-otsakkeessa. Avaimet luodaan Frihetin hallintapaneelissa kohdasta Asetukset > Kehittäjät > API-avaimet.

Avaimilla on etuliite fri_, jota seuraa 32 satunnaista, base64url-koodattua tavua. Esimerkki: fri_aBcDeFgHiJkLmNoPqRsTuVwXyZ012345678.

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

Vaihtoehtoisesti voit lähettää avaimen Bearer-tunnuksena Authorization-otsakkeessa:

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

Avainten turvallisuus

  • Selväkielinen avain näytetään vain kerran, luontihetkellä. Sitä ei voi hakea myöhemmin.
  • Palvelin tallentaa avaimen SHA-256-hajautuksen. Jopa tietomurron sattuessa alkuperäistä avainta ei voida palauttaa.
  • Voit luoda avaimia määritettävällä vanhentumispäivämäärällä.
  • Jos epäilet avaimen vaarantuneen, peruuta se välittömästi hallintapaneelista.

Avainten elinkaari

Luo avain:

  1. Mene kohtaan Asetukset > Kehittäjät > API-avaimet
  2. Paina Luo avain
  3. Anna kuvaava nimi (esim. kirjanpito-integraatio)
  4. Aseta valinnaisesti vanhentumispäivämäärä päivissä. Jos jätät tyhjäksi, avain ei vanhene.
  5. Kopioi avain välittömästi – et voi nähdä sitä uudelleen.

Vanhentuminen:

Vanhentumispäivämäärällä varustetut avaimet lakkaavat toimimasta automaattisesti määräajan umpeuduttua. Pyynnöt vanhentuneella avaimella saavat vastauksen 401 Unauthorized.

Peruutus:

Voit peruuttaa avaimen milloin tahansa kohdasta Asetukset > Kehittäjät > API-avaimet. Peruutus on välitön ja peruuttamaton: kyseisellä avaimella käynnissä olevat pyynnöt epäonnistuvat siitä hetkestä lähtien.

Avainten vaihto:

Voit vaihtaa avaimen keskeyttämättä palvelua seuraavasti:

  1. Luo uusi avain samalla käyttöoikeudella
  2. Päivitä integraatiosi käyttämään uutta avainta
  3. Varmista, että pyynnöt toimivat oikein
  4. Peruuta edellinen avain

Seuranta:

Jokainen avain näyttää viimeisen käytön päivämäärän Asetukset-paneelissa. Tarkista säännöllisesti passiiviset avaimet ja peruuta ne, joita ei enää käytetä.


Nopeusrajoitus

Jokaisella API-avaimella on 100 pyynnön minuutissa rajoitus. Jos tämä ylittyy, API vastaa koodilla 429:

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

Nopeusrajoituksen otsakkeet

Kaikki API-vastaukset sisältävät otsakkeet, jotta voit hallita rajoitusta ennakoivasti:

OtsakeKuvausEsimerkki
X-RateLimit-LimitRajoitettu määrä pyyntöjä minuutissa100
X-RateLimit-RemainingJäljellä olevat pyynnöt nykyisessä ikkunassa87
X-RateLimit-ResetUnix-aikaleima (sekunteina), jolloin ikkuna nollataan1709312400

Esimerkki vastauksesta nopeusrajoituksen otsakkeilla:

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

Koodin 429 hallinta:

Kun vastaanotat 429-vastauksen, käytä otsakkeita laskeaksesi, kuinka kauan sinun tulee odottaa ennen uudelleenyritystä:

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

Suositukset:

  • Jos vastaanotat 429-vastauksen, odota X-RateLimit-Reset-otsakkeen ilmoittamaan aikaleimaan asti ennen uudelleenyritystä.
  • Seuraa X-RateLimit-Remaining-otsaketta hidastaaksesi pyyntöjä ennen rajoituksen saavuttamista.
  • Jaa pyynnöt ajallisesti sen sijaan, että lähettäisit ne purskeina.

Pyynnön koko

POST-, PUT- ja PATCH-pyyntöjen runko ei saa ylittää 1 Mt. Suuremmat pyynnöt vastaanottavat koodin 413.


Resurssit

API tarjoaa 7 pääresurssia: laskut, kulut, asiakkaat, tuotteet, tarjoukset, toimittajat ja webhookit. Kaikki tukevat täydellisiä CRUD-operaatioita (GET, POST, PUT/PATCH, DELETE). Lisäksi asiakkailla on CRM-alakokoelmat: yhteystiedot, aktiviteetit ja muistiinpanot.

PATCH vs PUT

Sekä PUT että PATCH hyväksyvät osittaiset päivitykset. Sinun ei tarvitse lähettää koko resurssia – ainoastaan ne kentät, jotka haluat muokata.

Laskut (/invoices)

Listaa laskut

GET /v1/invoices

Kyselyparametrit:

ParametriTyyppiOletusKuvaus
limitinteger50Tuloksia sivua kohden (enintään 100)
offsetinteger0Ohitettavien tulosten määrä (enintään 10 000)
statusstring--Suodata tilan mukaan: luonnos, lähetetty, maksettu, erääntynyt, peruutettu
fromstring--Aloituspäivämäärä (ISO 8601: YYYY-MM-DD). Suodattaa issueDate-kentän mukaan
tostring--Lopetuspäivämäärä (ISO 8601: YYYY-MM-DD). Suodattaa issueDate-kentän mukaan

Esimerkki:

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"

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

Hae lasku

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

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

Luo lasku

POST /v1/invoices

Pakolliset kentät:

KenttäTyyppiKuvaus
clientNamestringAsiakkaan nimi (enintään 10 000 merkkiä)
itemsarrayLuettelo laskun riveistä. Jokainen rivi: { description, quantity, unitPrice }

Valinnaiset kentät:

KenttäTyyppiKuvaus
statusstringluonnos (oletus), lähetetty, maksettu, erääntynyt, peruutettu
issueDatestringJulkaisupäivämäärä (ISO 8601). Oletus: tänään
dueDatestringEräpäivä (ISO 8601)
notesstringSisäiset muistiinpanot (enintään 10 000 merkkiä)
taxRatenumberVeroprosentti (0-100). Esim: 21 ALV 21%

Jokaisen rivin rakenne (items[]):

KenttäTyyppiPakollinenKuvaus
descriptionstringKylläKonseptin kuvaus (enintään 10 000 merkkiä)
quantitynumberKylläMäärä
unitPricenumberKylläYksikköhinta
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"
}'

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

Päivitä lasku (PUT tai PATCH)

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

Sinun tarvitsee lähettää vain ne kentät, jotka haluat muokata. Kentät, joita ei ole sisällytetty, pysyvät ennallaan.

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

Vastaus (200): Päivitetty laskuobjekti.

caution

Jos lähetät items-taulukon, sinun on lähetettävä koko taulukko – yksittäisten rivien osittaisia päivityksiä ei tueta.

Poista lasku

DELETE /v1/invoices/:id
curl -X DELETE https://api.frihet.io/v1/invoices/def456 \
-H "X-API-Key: fri_tu-clave-aqui"

Vastaus: 204 No Content

Lataa lasku PDF-muodossa

GET /v1/invoices/:id/pdf

Palauttaa laskun PDF-tiedoston application/pdf-muodossa Content-Disposition: attachment-otsakkeella.

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

Lähetä lasku sähköpostitse

POST /v1/invoices/:id/send

Lähettää laskun määritetylle vastaanottajalle Resendin kautta. Jos laskun tila on luonnos, se päivitetään automaattisesti tilaan lähetetty.

Kentät:

KenttäTyyppiPakollinenKuvaus
recipientEmailstringKylläVastaanottajan sähköpostiosoite (enintään 255 merkkiä)
recipientNamestringEiVastaanottajan nimi (enintään 200 merkkiä)
customMessagestringEiMukautettu viesti sähköpostin rungossa (enintään 5 000 merkkiä)
localestringEiSähköpostin kieli: es (oletus) tai 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"
}'

Vastaus (200):

{ "success": true, "messageId": "re_abc123..." }

Merkitse lasku maksetuksi

POST /v1/invoices/:id/paid
KenttäTyyppiPakollinenKuvaus
paidDatestringEiMaksupäivä (ISO 8601). Oletus: tänään
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" }'

Vastaus (200):

{ "success": true, "status": "paid", "paidAt": "2026-03-15" }

Kulut (/expenses)

Listaa kulut

GET /v1/expenses

Kyselyparametrit:

ParametriTyyppiOletusKuvaus
limitinteger50Tuloksia sivua kohden (enintään 100)
offsetinteger0Ohitettavien tulosten määrä
fromstring--Aloituspäivämäärä (ISO 8601). Suodattaa date-kentän mukaan
tostring--Lopetuspäivämäärä (ISO 8601). Suodattaa date-kentän mukaan
curl "https://api.frihet.io/v1/expenses?limit=20&from=2026-01-01" \
-H "X-API-Key: fri_tu-clave-aqui"

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

Hae kulu

GET /v1/expenses/:id

Luo kulu

POST /v1/expenses

Pakolliset kentät:

KenttäTyyppiKuvaus
descriptionstringKulun kuvaus (enintään 10 000 merkkiä)
amountnumberKulun summa

Valinnaiset kentät:

KenttäTyyppiKuvaus
categorystringKulun luokka (enintään 10 000 merkkiä)
datestringKulun päivämäärä (ISO 8601). Oletus: tänään
vendorstringToimittaja (enintään 10 000 merkkiä)
taxDeductiblebooleanOnko kulu vähennyskelpoinen
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
}'

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

Päivitä kulu (PUT tai 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 }'

Vastaus (200): Päivitetty kuluobjekti.

Poista kulu

DELETE /v1/expenses/:id

Vastaus: 204 No Content


Asiakkaat (/clients)

Listaa asiakkaat

GET /v1/clients

Hyväksyy limit-, offset-, from- ja to-parametrit (suodattaa createdAt-kentän mukaan).

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

Hae asiakas

GET /v1/clients/:id

Luo asiakas

POST /v1/clients

Pakolliset kentät:

KenttäTyyppiKuvaus
namestringAsiakkaan nimi (enintään 10 000 merkkiä)

Valinnaiset kentät:

KenttäTyyppiKuvaus
emailstringYhteyshenkilön sähköpostiosoite
phonestringPuhelin
taxIdstringY-tunnus/ALV-numero
addressobjectOsoite (katso rakenne alla)

address-rakenteen rakenne:

KenttäTyyppiKuvaus
streetstringKatu ja numero
citystringKaupunki
statestringMaakunta tai osavaltio
postalCodestringPostinumero
countrystringMaa

Kaikki address-kentät ovat valinnaisia.

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

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

Päivitä asiakas (PUT tai 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" }'

Vastaus (200): Päivitetty asiakasobjekti.

Poista asiakas

DELETE /v1/clients/:id

Vastaus: 204 No Content


CRM: Yhteyshenkilöt, aktiviteetit ja muistiinpanot

Asiakkailla on kolme alakokoelmaa CRM-suhteiden hallintaan: yhteyshenkilöt, aktiviteetit ja muistiinpanot. Kaikki rajapinnat vaativat kelvollisen clientId:n URL-osoitteessa.

Yhteyshenkilöt (/v1/clients/:id/contacts)

Listaa yhteyshenkilöt
GET /v1/clients/:id/contacts
curl "https://api.frihet.io/v1/clients/cli001/contacts" \
-H "X-API-Key: fri_tu-clave-aqui"
Hae yhteyshenkilö
GET /v1/clients/:id/contacts/:contactId
curl "https://api.frihet.io/v1/clients/cli001/contacts/con001" \
-H "X-API-Key: fri_tu-clave-aqui"
Luo yhteyshenkilö
POST /v1/clients/:id/contacts

Pakolliset kentät:

KenttäTyyppiKuvaus
namestringYhteyshenkilön nimi

Valinnaiset kentät:

KenttäTyyppiKuvaus
emailstringYhteyshenkilön sähköpostiosoite
phonestringPuhelin
rolestringAsema tai rooli (esim. "Talousjohtaja")
isPrimarybooleanOnko ensisijainen asiakkaan yhteyshenkilö
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
}'

Vastaus (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"
}
Päivitä yhteyshenkilö
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" }'

Vastaus (200): Päivitetty yhteyshenkilöobjekti.

Poista yhteyshenkilö
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"

Vastaus: 204 No Content

Aktiviteetit (/v1/clients/:id/activities)

Aktiviteettien aikajana tallentaa asiakkaan kanssa tehdyt vuorovaikutukset. Järjestelmäaktiviteetit (kuten invoice_created, quote_sent jne.) luodaan automaattisesti. Voit myös luoda manuaalisia aktiviteetteja.

Muuttumattomat

Aktiviteetit ovat muuttumattomia. Niitä ei voi päivittää tai poistaa sen jälkeen, kun ne on luotu.

Listaa aktiviteetit
GET /v1/clients/:id/activities
curl "https://api.frihet.io/v1/clients/cli001/activities" \
-H "X-API-Key: fri_tu-clave-aqui"
Hae aktiviteetti
GET /v1/clients/:id/activities/:activityId
curl "https://api.frihet.io/v1/clients/cli001/activities/act001" \
-H "X-API-Key: fri_tu-clave-aqui"
Luo aktiviteetti
POST /v1/clients/:id/activities

Pakolliset kentät:

KenttäTyyppiKuvaus
typestringAktiviteetin tyyppi: call, email, meeting tai task
titlestringAktiviteetin kuvaava otsikko

Valinnaiset kentät:

KenttäTyyppiKuvaus
descriptionstringYksityiskohtainen kuvaus
metadataobjectLisätiedot vapaamuotoisena
Aktiviteettityypit

call-, email-, meeting- ja task-tyypit ovat manuaalisesti luotuja aktiviteetteja varten. Järjestelmätyypit, kuten invoice_created, quote_sent tai expense_linked, luodaan automaattisesti, eikä niitä voi luoda API:n kautta.

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

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

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

Listaa muistiinpanot
GET /v1/clients/:id/notes
curl "https://api.frihet.io/v1/clients/cli001/notes" \
-H "X-API-Key: fri_tu-clave-aqui"
Hae muistiinpano
GET /v1/clients/:id/notes/:noteId
curl "https://api.frihet.io/v1/clients/cli001/notes/note001" \
-H "X-API-Key: fri_tu-clave-aqui"
Luo muistiinpano
POST /v1/clients/:id/notes

Pakolliset kentät:

KenttäTyyppiKuvaus
contentstringMuistiinpanon sisältö
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."
}'

Vastaus (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"
}
Päivitä muistiinpano
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."
}'

Vastaus (200): Päivitetty muistiinpano-objekti.

Poista muistiinpano
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"

Vastaus: 204 No Content


Tuotteet (/products)

Listaa tuotteet

GET /v1/products

Hyväksyy limit-, offset-, from- ja to-parametrit (suodattaa createdAt-kentän mukaan).

Hae tuote

GET /v1/products/:id

Luo tuote

POST /v1/products

Pakolliset kentät:

KenttäTyyppiKuvaus
namestringTuotteen tai palvelun nimi (enintään 10 000 merkkiä)
unitPricenumberYksikköhinta

Valinnaiset kentät:

KenttäTyyppiKuvaus
descriptionstringKuvaus (enintään 10 000 merkkiä)
taxRatenumberVeroprosentti (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
}'

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

Päivitä tuote (PUT tai 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 }'

Vastaus (200): Päivitetty tuoteobjekti.

Poista tuote

DELETE /v1/products/:id

Vastaus: 204 No Content


Tarjoukset (/quotes)

Listaa tarjoukset

GET /v1/quotes

Kyselyparametrit:

ParametriTyyppiOletusKuvaus
limitinteger50Tuloksia sivua kohden (enintään 100)
offsetinteger0Ohitettavien tulosten määrä
statusstring--Suodata tilan mukaan: luonnos, lähetetty, hyväksytty, hylätty, vanhentunut
fromstring--Aloituspäivämäärä (ISO 8601). Suodattaa issueDate-kentän mukaan
tostring--Lopetuspäivämäärä (ISO 8601). Suodattaa issueDate-kentän mukaan
curl "https://api.frihet.io/v1/quotes?status=sent" \
-H "X-API-Key: fri_tu-clave-aqui"

Hae tarjous

GET /v1/quotes/:id

Luo tarjous

POST /v1/quotes

Pakolliset kentät:

KenttäTyyppiKuvaus
clientNamestringAsiakkaan nimi (enintään 10 000 merkkiä)
itemsarrayTarjouksen rivit. Jokainen rivi: { description, quantity, unitPrice }

Valinnaiset kentät:

KenttäTyyppiKuvaus
validUntilstringVoimassaoloaika (ISO 8601)
notesstringMuistiinpanot tai ehdot (enintään 10 000 merkkiä)
statusstringluonnos (oletus), lähetetty, hyväksytty, hylätty, vanhentunut
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"
}'

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

Päivitä tarjous (PUT tai PATCH)

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

Poista tarjous

DELETE /v1/quotes/:id

Vastaus: 204 No Content

Lataa tarjous PDF-muodossa

GET /v1/quotes/:id/pdf

Toimii samalla tavalla kuin /invoices/:id/pdf. Palauttaa application/pdf.

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

Lähetä tarjous sähköpostitse

POST /v1/quotes/:id/send

Sammat kentät kuin /invoices/:id/send (recipientEmail, recipientName, customMessage, locale). Jos tarjouksen tila on luonnos, se päivitetään automaattisesti tilaan lähetetty.


Erätoiminnot (/batch)

Kaikki pääresurssit tukevat eräluontia. Lähetä enintään 50 elementin taulukko yhdellä pyynnöllä.

POST /v1/{resource}/batch

Tuetut resurssit: laskut, kulut, asiakkaat, tuotteet, tarjoukset

Pyynnön runko:

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

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

Jos jokin elementeistä epäonnistuu validoinnissa, loput luodaan silti. Yksittäiset virheet palautetaan results-taulukossa:

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

Rajoitukset:

KäsiteRaja
Elementtejä erässä50 enintään
Pyynnön koko1 Mt enintään

Idempotenssi

POST-pyynnöt hyväksyvät Idempotency-Key-otsakkeen estääkseen resurssien päällekkäisen luomisen verkon uudelleenyritysten yhteydessä. Jos sama avain lähetetään seuraavan 24 tunnin kuluessa, API palauttaa alkuperäisen vastauksen suorittamatta toimintoa uudelleen.

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

Käyttäytyminen:

SkenaarioTulos
Ensimmäinen pyyntö avaimellaResurssi luodaan normaalisti
Toistettu pyyntö samalla avaimella (24h sisällä)Alkuperäinen vastaus palautetaan, ilman päällekkäisyyttä
Sama avain 24h jälkeenKäsitellään uutena pyyntönä

Vastausotsake:

Kun API tunnistaa toistetun avaimen, se sisällyttää X-Idempotent-Replayed: true-otsakkeen, jotta kuluttaja tietää vastauksen olevan replika.

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

Vaatimukset:

  • Avaimen on oltava enintään 64 merkkiä pitkä
  • Suosittelemme käyttämään UUID v4 -muotoa
  • Koskee vain POST-pyyntöjä (resurssien luominen)

Haku

Listaavat rajapinnat tukevat kokotekstihakua q-parametrin avulla:

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

Haku kohdistuu resurssin päätekstikenttiin (asiakkaan nimi, kuvaus, muistiinpanot jne.). Se voidaan yhdistää olemassa oleviin suodattimiin (status, from, to).


Älykkyysrajapinnat

Nämä rajapinnat tarjoavat yhdistettyjä tietoja ja liiketoimintakontekstin. Ne ovat erityisen hyödyllisiä tekoälyagenteille ja ulkoisille mittaristoille.

Liiketoimintakonteksti (/context)

GET /v1/context

Palauttaa kattavan yhteenvedon liiketoiminnasta, tarkoitettu syöttämään tekoälyagenteille tarvittavan kontekstin tietoisten päätösten tekemiseen. Sisältää taloudellisen yhteenvedon, viimeisimmät aktiviteetit, hälytykset ja verotuskokoonpanon.

curl https://api.frihet.io/v1/context \
-H "X-API-Key: fri_tu-clave-aqui"

Vastaus (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" }
]
}

Kuukausittainen tuloslaskelma (/monthly)

GET /v1/monthly?month=YYYY-MM

Palauttaa tietyn kuukauden tuloslaskelman (P&L): laskutetut tulot, kulut kategorioittain, nettotulos ja vertailu edelliseen kuukauteen.

curl "https://api.frihet.io/v1/monthly?month=2026-02" \
-H "X-API-Key: fri_tu-clave-aqui"

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

Neljännesvuosittaiset verotiedot (/quarterly)

GET /v1/quarterly?quarter=YYYY-Q1

Palauttaa neljänneksen verotiedot, valmisteltu Modelo 303 (ALV) ja Modelo 130 (IRPF) -ilmoitusten jättämiseen. Sisältää veropohjat, kertyneet verot, vähennyskelpoiset verot ja selvityksen tuloksen.

curl "https://api.frihet.io/v1/quarterly?quarter=2026-Q1" \
-H "X-API-Key: fri_tu-clave-aqui"

Vastaus (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

Rajapinnat /context, /monthly ja /quarterly on suunniteltu ihanteellisiksi tekoälyagenttien sisääntulopisteiksi. Ne tarjoavat tarvittavat tiedot yhdellä kutsulla, ilman tarvetta kysellä useista yksittäisistä rajapinnoista.


Talousmittaristo (/summary)

GET /v1/summary

Palauttaa yrityksen taloudellisen yhteenvedon: tulot, kulut, voitto ja laskurit.

Kyselyparametrit:

ParametriTyyppiKuvaus
fromstringAloituspäivämäärä (ISO 8601)
tostringLopetuspäivämäärä (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"

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

Virhekoodit

API käyttää standardeja HTTP-koodeja. Virhevastaukset sisältävät JSON-objektin, jossa on kentät error ja valinnaisesti message sekä details.

KoodiMerkitysKuvaus
400Bad RequestPuuttuva pakollinen kenttä, virheellinen muoto tai kielletty kenttä
401UnauthorizedAPI-avainta ei ole annettu, se on virheellinen, sen muoto on virheellinen tai se on vanhentunut
403ForbiddenAPI-avaimella ei ole oikeuksia tämän resurssin käyttöön
404Not FoundPyydettyä resurssia ei löytynyt
405Method Not AllowedHTTP-metodia ei tueta tälle rajapinnalle
413Payload Too LargePyyntökuorma ylittää 1 Mt
422Unprocessable EntityKelvolliset tiedot, mutta palvelin ei voi käsitellä niitä (esim. verotuksellinen profiili ei ole määritetty)
429Too Many RequestsYli 100 pyynnön minuutissa rajoitus on ylitetty
500Internal Server ErrorSisäinen palvelinvirhe

Virhevastausten rakenne

Validointivirhe (400):

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

Validointivirheet käyttävät Zod-muotoa. path-kenttä ilmoittaa, missä kentässä virhe on, ja message kuvaa ongelman.

Virheellinen tai vanhentunut avain (401):

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

Virheellinen avainmuoto (401):

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

Resurssia ei löytynyt (404):

{
"error": "Resource not found"
}

Virheellinen tila suodattimessa (400):

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

Rajoitus ylitetty (429):

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

Sisäinen virhe (500):

{
"error": "Internal server error"
}

Sivutus

Listaavat rajapinnat palauttavat sivutetut tulokset seuraavalla rakenteella:

{
"data": [],
"total": 142,
"limit": 50,
"offset": 0
}
  • total: hakuehtoja vastaavien tietueiden kokonaismäärä
  • limit: tällä sivulla palautettujen tietueiden määrä (enintään 100)
  • offset: ohitettujen tietueiden määrä (enintään 10 000)

Seuraavan sivun hakemiseksi:

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

Tulokset järjestetään resurssin luonnollisen päivämäärän mukaan laskevassa järjestyksessä (uusimmat ensin):

  • Laskut ja tarjoukset: issueDate
  • Kulut: date
  • Asiakkaat ja tuotteet: createdAt

Tiukka validointi

API käyttää tiukkaa validointia (Zod strict mode). Pyynnöt tuntemattomilla kentillä hylätään virheellä 400:

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

Tämä estää hiljaiset virheet, jotka johtuvat kirjoitusvirheistä kenttien nimissä.


CORS

API tukee CORS:ia selaimesta tuleville pyynnöille. Sallitut alkuperät ovat:

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

Palvelimien välisille integraatioille CORS ei ole olennainen. Jos sinun on käytettävä API:a eri verkkotunnukselta selaimessa, käytä välityspalvelinta taustajärjestelmässäsi.


Suojausotsakkeet

Kaikki vastaukset sisältävät suojausotsakkeet:

OtsakeArvo
X-Content-Type-Optionsnosniff
X-Frame-OptionsDENY
X-XSS-Protection1; mode=block
X-Request-IdYksilöllinen pyyntötunnus (hyödyllinen virheenkorjauksessa)

OAuth MCP:lle

Rajapinta POST /api/oauth/api-key mahdollistaa API-avaimen automaattisen provisionoinnin MCP:n OAuth-kulun kautta. MCP-palvelin käyttää tätä rajapintaa sisäisesti – sinun ei tarvitse kutsua sitä suoraan.

Kulku:

  1. Käyttäjä autentikoi Firebase Auth -palvelun kautta
  2. MCP-asiakas lähettää Firebase-tokenin osoitteeseen /api/oauth/api-key
  3. Palvelin palauttaa uuden avaimen fri_xxx..., joka on merkitty "MCP OAuth" -tunnuksella
  4. Avain vanhenee 365 päivässä

Rajoitus: 5 aktiivista avainta käyttäjää kohden. Jos rajoitus ylittyy, rajapinta vastaa 429-koodilla.


Parhaat käytännöt

  1. Tallenna API-avain turvallisesti. Älä koskaan sisällytä sitä frontend-koodiin, julkisiin repositorioihin tai lokeihin.
  2. Hallitse nopeusrajoitusta. Toteuta eksponentiaalinen takaisinkytkentä, jos vastaanotat 429-vastauksen.
  3. Käytä sivutusta. Älä pyydä kaikkia tietueita kerralla; selaa niitä limit- ja offset-parametreilla.
  4. Tarkista vastauskoodit. Älä oleta, että kaikki pyynnöt onnistuvat.
  5. Vaihda avaimia säännöllisesti. Luo uusi avain, päivitä integraatiosi ja peruuta edellinen.
  6. Käytä aina HTTPS:ää. Kaikkien API-pyyntöjen on tapahduttava HTTPS:n kautta.
  7. Käytä suodattimia. status-, from- ja to-parametrit vähentävät siirrettyjen tietojen määrää.
  8. Hyödynnä PATCH-metodia. Osittaisissa päivityksissä lähetä vain muutetut kentät.