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.
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:
- Mene kohtaan Asetukset > Kehittäjät > API-avaimet
- Paina Luo avain
- Anna kuvaava nimi (esim.
kirjanpito-integraatio) - Aseta valinnaisesti vanhentumispäivämäärä päivissä. Jos jätät tyhjäksi, avain ei vanhene.
- 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:
- Luo uusi avain samalla käyttöoikeudella
- Päivitä integraatiosi käyttämään uutta avainta
- Varmista, että pyynnöt toimivat oikein
- 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:
| Otsake | Kuvaus | Esimerkki |
|---|---|---|
X-RateLimit-Limit | Rajoitettu määrä pyyntöjä minuutissa | 100 |
X-RateLimit-Remaining | Jäljellä olevat pyynnöt nykyisessä ikkunassa | 87 |
X-RateLimit-Reset | Unix-aikaleima (sekunteina), jolloin ikkuna nollataan | 1709312400 |
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, odotaX-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.
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:
| Parametri | Tyyppi | Oletus | Kuvaus |
|---|---|---|---|
limit | integer | 50 | Tuloksia sivua kohden (enintään 100) |
offset | integer | 0 | Ohitettavien tulosten määrä (enintään 10 000) |
status | string | -- | Suodata tilan mukaan: luonnos, lähetetty, maksettu, erääntynyt, peruutettu |
from | string | -- | Aloituspäivämäärä (ISO 8601: YYYY-MM-DD). Suodattaa issueDate-kentän mukaan |
to | string | -- | 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ä | Tyyppi | Kuvaus |
|---|---|---|
clientName | string | Asiakkaan nimi (enintään 10 000 merkkiä) |
items | array | Luettelo laskun riveistä. Jokainen rivi: { description, quantity, unitPrice } |
Valinnaiset kentät:
| Kenttä | Tyyppi | Kuvaus |
|---|---|---|
status | string | luonnos (oletus), lähetetty, maksettu, erääntynyt, peruutettu |
issueDate | string | Julkaisupäivämäärä (ISO 8601). Oletus: tänään |
dueDate | string | Eräpäivä (ISO 8601) |
notes | string | Sisäiset muistiinpanot (enintään 10 000 merkkiä) |
taxRate | number | Veroprosentti (0-100). Esim: 21 ALV 21% |
Jokaisen rivin rakenne (items[]):
| Kenttä | Tyyppi | Pakollinen | Kuvaus |
|---|---|---|---|
description | string | Kyllä | Konseptin kuvaus (enintään 10 000 merkkiä) |
quantity | number | Kyllä | Määrä |
unitPrice | number | Kyllä | 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.
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ä | Tyyppi | Pakollinen | Kuvaus |
|---|---|---|---|
recipientEmail | string | Kyllä | Vastaanottajan sähköpostiosoite (enintään 255 merkkiä) |
recipientName | string | Ei | Vastaanottajan nimi (enintään 200 merkkiä) |
customMessage | string | Ei | Mukautettu viesti sähköpostin rungossa (enintään 5 000 merkkiä) |
locale | string | Ei | Sä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ä | Tyyppi | Pakollinen | Kuvaus |
|---|---|---|---|
paidDate | string | Ei | Maksupä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:
| Parametri | Tyyppi | Oletus | Kuvaus |
|---|---|---|---|
limit | integer | 50 | Tuloksia sivua kohden (enintään 100) |
offset | integer | 0 | Ohitettavien tulosten määrä |
from | string | -- | Aloituspäivämäärä (ISO 8601). Suodattaa date-kentän mukaan |
to | string | -- | 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ä | Tyyppi | Kuvaus |
|---|---|---|
description | string | Kulun kuvaus (enintään 10 000 merkkiä) |
amount | number | Kulun summa |
Valinnaiset kentät:
| Kenttä | Tyyppi | Kuvaus |
|---|---|---|
category | string | Kulun luokka (enintään 10 000 merkkiä) |
date | string | Kulun päivämäärä (ISO 8601). Oletus: tänään |
vendor | string | Toimittaja (enintään 10 000 merkkiä) |
taxDeductible | boolean | Onko 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ä | Tyyppi | Kuvaus |
|---|---|---|
name | string | Asiakkaan nimi (enintään 10 000 merkkiä) |
Valinnaiset kentät:
| Kenttä | Tyyppi | Kuvaus |
|---|---|---|
email | string | Yhteyshenkilön sähköpostiosoite |
phone | string | Puhelin |
taxId | string | Y-tunnus/ALV-numero |
address | object | Osoite (katso rakenne alla) |
address-rakenteen rakenne:
| Kenttä | Tyyppi | Kuvaus |
|---|---|---|
street | string | Katu ja numero |
city | string | Kaupunki |
state | string | Maakunta tai osavaltio |
postalCode | string | Postinumero |
country | string | Maa |
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ä | Tyyppi | Kuvaus |
|---|---|---|
name | string | Yhteyshenkilön nimi |
Valinnaiset kentät:
| Kenttä | Tyyppi | Kuvaus |
|---|---|---|
email | string | Yhteyshenkilön sähköpostiosoite |
phone | string | Puhelin |
role | string | Asema tai rooli (esim. "Talousjohtaja") |
isPrimary | boolean | Onko 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.
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ä | Tyyppi | Kuvaus |
|---|---|---|
type | string | Aktiviteetin tyyppi: call, email, meeting tai task |
title | string | Aktiviteetin kuvaava otsikko |
Valinnaiset kentät:
| Kenttä | Tyyppi | Kuvaus |
|---|---|---|
description | string | Yksityiskohtainen kuvaus |
metadata | object | Lisätiedot vapaamuotoisena |
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ä | Tyyppi | Kuvaus |
|---|---|---|
content | string | Muistiinpanon 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ä | Tyyppi | Kuvaus |
|---|---|---|
name | string | Tuotteen tai palvelun nimi (enintään 10 000 merkkiä) |
unitPrice | number | Yksikköhinta |
Valinnaiset kentät:
| Kenttä | Tyyppi | Kuvaus |
|---|---|---|
description | string | Kuvaus (enintään 10 000 merkkiä) |
taxRate | number | Veroprosentti (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:
| Parametri | Tyyppi | Oletus | Kuvaus |
|---|---|---|---|
limit | integer | 50 | Tuloksia sivua kohden (enintään 100) |
offset | integer | 0 | Ohitettavien tulosten määrä |
status | string | -- | Suodata tilan mukaan: luonnos, lähetetty, hyväksytty, hylätty, vanhentunut |
from | string | -- | Aloituspäivämäärä (ISO 8601). Suodattaa issueDate-kentän mukaan |
to | string | -- | 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ä | Tyyppi | Kuvaus |
|---|---|---|
clientName | string | Asiakkaan nimi (enintään 10 000 merkkiä) |
items | array | Tarjouksen rivit. Jokainen rivi: { description, quantity, unitPrice } |
Valinnaiset kentät:
| Kenttä | Tyyppi | Kuvaus |
|---|---|---|
validUntil | string | Voimassaoloaika (ISO 8601) |
notes | string | Muistiinpanot tai ehdot (enintään 10 000 merkkiä) |
status | string | luonnos (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äsite | Raja |
|---|---|
| Elementtejä erässä | 50 enintään |
| Pyynnön koko | 1 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:
| Skenaario | Tulos |
|---|---|
| Ensimmäinen pyyntö avaimella | Resurssi luodaan normaalisti |
| Toistettu pyyntö samalla avaimella (24h sisällä) | Alkuperäinen vastaus palautetaan, ilman päällekkäisyyttä |
| Sama avain 24h jälkeen | Kä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
}
}
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:
| Parametri | Tyyppi | Kuvaus |
|---|---|---|
from | string | Aloituspäivämäärä (ISO 8601) |
to | string | Lopetuspä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.
| Koodi | Merkitys | Kuvaus |
|---|---|---|
400 | Bad Request | Puuttuva pakollinen kenttä, virheellinen muoto tai kielletty kenttä |
401 | Unauthorized | API-avainta ei ole annettu, se on virheellinen, sen muoto on virheellinen tai se on vanhentunut |
403 | Forbidden | API-avaimella ei ole oikeuksia tämän resurssin käyttöön |
404 | Not Found | Pyydettyä resurssia ei löytynyt |
405 | Method Not Allowed | HTTP-metodia ei tueta tälle rajapinnalle |
413 | Payload Too Large | Pyyntökuorma ylittää 1 Mt |
422 | Unprocessable Entity | Kelvolliset tiedot, mutta palvelin ei voi käsitellä niitä (esim. verotuksellinen profiili ei ole määritetty) |
429 | Too Many Requests | Yli 100 pyynnön minuutissa rajoitus on ylitetty |
500 | Internal Server Error | Sisä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.iohttps://frihet.iohttps://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:
| Otsake | Arvo |
|---|---|
X-Content-Type-Options | nosniff |
X-Frame-Options | DENY |
X-XSS-Protection | 1; mode=block |
X-Request-Id | Yksilö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:
- Käyttäjä autentikoi Firebase Auth -palvelun kautta
- MCP-asiakas lähettää Firebase-tokenin osoitteeseen
/api/oauth/api-key - Palvelin palauttaa uuden avaimen
fri_xxx..., joka on merkitty "MCP OAuth" -tunnuksella - 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
- Tallenna API-avain turvallisesti. Älä koskaan sisällytä sitä frontend-koodiin, julkisiin repositorioihin tai lokeihin.
- Hallitse nopeusrajoitusta. Toteuta eksponentiaalinen takaisinkytkentä, jos vastaanotat
429-vastauksen. - Käytä sivutusta. Älä pyydä kaikkia tietueita kerralla; selaa niitä
limit- jaoffset-parametreilla. - Tarkista vastauskoodit. Älä oleta, että kaikki pyynnöt onnistuvat.
- Vaihda avaimia säännöllisesti. Luo uusi avain, päivitä integraatiosi ja peruuta edellinen.
- Käytä aina HTTPS:ää. Kaikkien API-pyyntöjen on tapahduttava HTTPS:n kautta.
- Käytä suodattimia.
status-,from- jato-parametrit vähentävät siirrettyjen tietojen määrää. - Hyödynnä PATCH-metodia. Osittaisissa päivityksissä lähetä vain muutetut kentät.