Panoramica
L’API di Manilo è un’API REST JSON per gestire in modo programmatico lo stesso registro che usi nell’app iOS: conti, categorie, budget, gruppi condivisi e transazioni. Usala per costruire importatori, esportatori, ponti di sincronizzazione, dashboard o per alimentare le tue automazioni.
- URL di base:
https://api.manilo.app— l’URL di base precedenteapi.ledgy.appcontinua a funzionare. - Prefisso di versione: tutti gli endpoint di questo documento sono esposti sotto
/api/v1/. - Trasporto: solo HTTPS. Le richieste HTTP non vengono accettate.
- Codifica: corpi di richiesta e risposta in JSON. UTF-8. Nomi delle proprietà in
camelCase. - Autenticazione:
Authorization: Bearer …a ogni richiesta. - Abbonamento Cloud: richiesto su ogni endpoint v1. Vedi Requisito di abbonamento.
https://api.manilo.app/mcp — vedi Integrazioni. L’API REST documentata qui è pensata per il codice che scrivi tu.
Avvio rapido
Tre passaggi per arrivare alla tua prima richiesta autenticata.
1. Genera un Personal Access Token
- Accedi alla tua dashboard Manilo e apri Impostazioni → Accesso API.
- Fai clic su + Nuovo token.
- Dai al token un nome descrittivo (ad es. “Zapier — esportazione settimanale”), scegli gli ambiti che ti servono (vedi Ambiti) e, se vuoi, imposta una scadenza.
- Copia il token. Viene mostrato una sola volta. I token iniziano con il prefisso
lgpat_seguito da 64 caratteri esadecimali.
La stessa pagina elenca i tuoi token attivi con la data dell’ultimo utilizzo e il numero di permessi, mostra un avviso “In scadenza tra 30 giorni” e ti permette di revocare qualsiasi token all’istante tramite l’icona del cestino. Ogni account può avere fino a 25 token attivi contemporaneamente.
2. Esegui una richiesta
# Replace lgpat_… with your token curl "https://api.manilo.app/api/v1/accounts" \ -H "Authorization: Bearer lgpat_a1b2c3d4e5…"
3. Esamina la risposta
{
"items": [
{
"id": "acc_01HK8V…",
"name": "Wise EUR",
"currencyCode": "EUR",
"initialBalance": 1240.50,
"icon": "wallet",
"color": "#4A90E2",
"order": 0,
"createdAt": "2026-04-12T08:13:09Z",
"updatedAt": "2026-05-01T17:02:31Z"
}
],
"totalCount": 1
}
Autenticazione
Ogni richiesta a /api/v1/ deve includere un’intestazione Authorization. Sono accettati due tipi di token:
- Personal Access Token (PAT) — token bearer di lunga durata che crei dalla pagina Impostazioni → Accesso API della dashboard. Formato:
lgpat_+ 64 caratteri esadecimali. Con ambiti, revocabile, con scadenza facoltativa. Consigliato per tutte le integrazioni di terze parti. - JWT di sessione — token di breve durata emesso per le app first-party (iOS, dashboard). Non ha restrizioni di ambito. Puoi usarlo per un test occasionale, se riesci a estrarne uno da una sessione autenticata, ma la strada supportata sono i PAT.
Formato dell’intestazione
Authorization: Bearer lgpat_a1b2c3d4e5f6…
Limiti dei token
- Fino a 25 PAT attivi per account Manilo.
- Al momento della creazione si può impostare una scadenza facoltativa. I token scaduti restituiscono
401 Unauthorized. - I token revocati smettono di funzionare immediatamente: Manilo conserva solo un hash SHA-256 del token, mai il valore, quindi un token trapelato non può essere recuperato, ma solo revocato e sostituito.
Errori di autenticazione comuni
- 401
- Token mancante, malformato, scaduto o revocato.
- 403
- Il token è valido, ma l’endpoint richiesto esige un ambito che il tuo PAT non possiede, oppure il tuo abbonamento Cloud non è attivo.
Ambiti
I PAT seguono un modello deny-by-default (tutto negato salvo esplicita concessione). Un token può chiamare solo gli endpoint di cui possiede l’ambito richiesto; tutto il resto restituisce 403 Forbidden. Concedi l’insieme di ambiti più ristretto di cui la tua integrazione ha davvero bisogno.
Ambiti disponibili:
accounts:read
accounts:write
categories:read
categories:write
budgets:read
budgets:write
groups:read
groups:write
transactions:read
transactions:write
tags:read
tags:write
recurring:read
recurring:write
settings:read
settings:write
Ogni endpoint elencato di seguito mostra l’ambito richiesto in una piccola etichetta viola. Gli ambiti :write non implicano quelli :read: richiedili entrambi se ti servono entrambi.
Requisito di abbonamento
Tutti gli endpoint v1 — comprese le operazioni di sola lettura — richiedono che l’utente chiamante abbia un abbonamento Manilo Cloud attivo. Se l’abbonamento è decaduto, è scaduto o non è mai stato attivato, l’API risponde con:
HTTP/1.1 403 Forbidden
X-Subscription-Required: true
Content-Type: application/json
{ "error": "Active cloud subscription required" }
L’intestazione X-Subscription-Required permette ai client di distinguere un blocco dovuto all’abbonamento da un generico rifiuto per permessi insufficienti. Per ripristinare l’accesso, riattiva Cloud nell’app iOS oppure su dashboard.manilo.app/upgrade.
Errori
Gli errori usano i codici di stato HTTP standard. Il corpo della risposta è un oggetto JSON con un solo campo:
{ "error": "Human-readable message" }
Codici di stato da gestire:
- 200
- OK — risorsa restituita, oppure elenco restituito.
- 201
- Created — nuova risorsa creata. L’intestazione
Locationpunta all’URL canonico. - 204
- No Content — eliminazione riuscita; nessun corpo.
- 400
- Convalida non riuscita — campo obbligatorio mancante, valore fuori intervallo, JSON malformato.
- 401
- Autenticazione non riuscita — vedi Autenticazione.
- 403
- Permesso negato — ambito insufficiente o abbonamento non attivo.
- 404
- Risorsa non trovata, oppure nascosta da un controllo di autorizzazione.
- 409
- Conflict — ad es. violazione di un vincolo di unicità.
- 5xx
- Errore lato server. È sicuro riprovare le letture idempotenti con backoff esponenziale.
Paginazione e filtri
Per impostazione predefinita, gli endpoint di elenco restituiscono tutti gli elementi corrispondenti. Le transazioni, l’unica risorsa che può diventare voluminosa, supportano la paginazione a cursore.
Cursore delle transazioni
curl "https://api.manilo.app/api/v1/transactions?limit=50&type=expense&dateFrom=2026-01-01" \ -H "Authorization: Bearer lgpat_…"
La risposta include un nextCursor. Rimandalo indietro come parametro di query cursor per ottenere la pagina successiva; quando nextCursor è null, sei arrivato alla fine.
limit— dimensione della pagina, limitata all’intervallo1..200. Valore predefinito50.cursor— token opaco. Trattalo come una scatola nera.type,dateFrom,dateTo,categoryId,accountId,groupId— filtri facoltativi; vedi l’endpoint Elenca transazioni.
Tipi e formati
- ID — stringhe opache. Non analizzarle; trattale come identificatori UTF-8 sensibili a maiuscole e minuscole.
- Timestamp — ISO-8601 in UTC con un carattere
Zfinale, ad es."2026-05-13T10:30:00Z". - Date (ad es. il campo
datedi una transazione) — stesso formato ISO-8601, ma è significativa solo la parte della data. - Importi — numeri JSON espressi in unità principali con un massimo di 4 decimali (ad es.
12.50). Mai in unità secondarie. Sempre accompagnati dacurrencyCode. - Codici valuta — ISO-4217, esattamente tre lettere maiuscole (ad es.
"EUR","USD","GBP"). - Eliminazioni — tutte le operazioni di eliminazione sono eliminazioni logiche. Gli elementi eliminati smettono di comparire nelle risposte di elenco e di lettura; i partner di condivisione e gli scontrini storici vengono conservati.
- Effetti collaterali — eliminare un conto, una categoria o un gruppo lascia intatte le transazioni collegate; i loro riferimenti vengono staccati. L’endpoint Elimina conto accetta una strategia esplicita.
Conti
I conti sono i contenitori che custodiscono i saldi: un conto bancario, una carta di credito, un portafoglio in contanti, un conto di investimento. Ogni transazione è collegata a un conto (o a due, nel caso dei trasferimenti).
/api/v1/accounts
accounts:read
Restituisce tutti i conti di cui l’utente autenticato è proprietario o a cui ha accesso.
/api/v1/accounts/{id}
accounts:read
Recupera un conto tramite id. 404 se non viene trovato.
/api/v1/accounts
accounts:write
Crea un nuovo conto. Restituisce 201 con l’oggetto creato e un’intestazione Location.
| Campo | Tipo | Descrizione |
|---|---|---|
| name | string | obbligatorioNome visualizzato. Massimo 100 caratteri. |
| currencyCode | string | obbligatorioISO-4217. Esattamente 3 lettere. |
| initialBalance | number | obbligatorioSaldo iniziale in currencyCode. |
| order | integer | obbligatorioPosizione di ordinamento. I valori più bassi vengono prima. |
| icon | string | facoltativoIdentificatore dell’icona da /api/v1/icons. Massimo 50. |
| color | string | facoltativoColore esadecimale, ad es. "#4A90E2". Massimo 20. |
| iconColor | string | facoltativoSovrascrive la tinta dell’icona. |
POST /api/v1/accounts
{
"name": "Cash",
"currencyCode": "EUR",
"initialBalance": 50.00,
"order": 2,
"icon": "wallet",
"color": "#22C55E"
}
{
"id": "acc_01HK8V…",
"name": "Cash",
"currencyCode": "EUR",
"initialBalance": 50.00,
"order": 2,
"icon": "wallet",
"color": "#22C55E",
"iconColor": null,
"shareInviteToken": null,
"createdAt": "2026-05-13T10:30:00Z",
"updatedAt": "2026-05-13T10:30:00Z"
}
/api/v1/accounts/{id}
accounts:write
Sostituisce un conto esistente. Il corpo è identico a Crea; vanno forniti tutti i campi.
/api/v1/accounts/{id}
accounts:write
Elimina logicamente un conto. Decidi cosa succede alle sue transazioni tramite il parametro di query action.
| Campo | Tipo | Descrizione |
|---|---|---|
| action | enum | facoltativoDetach (predefinito): azzera il riferimento al conto su ogni transazione. Move: riassegna le transazioni a moveTargetAccountId. DeleteAll: elimina logicamente tutte le transazioni collegate di cui sei proprietario. |
| moveTargetAccountId | string | facoltativoObbligatorio quando action=Move. Id del conto di destinazione. |
Categorie
Le categorie indicano a cosa si riferisce una transazione (spesa alimentare, affitto, entrate da lavoro autonomo). Le categorie di sistema sono di sola lettura e condivise da tutti gli utenti; le categorie utente sono tue e le gestisci tu. I gruppi di categorie riuniscono categorie correlate.
/api/v1/categories/system-categories
categories:read
Restituisce l’insieme curato di categorie “note” di Manilo: il set iniziale incluso nell’app iOS. Sono versionate a livello globale e si possono mettere in cache in sicurezza in base a version.
Categorie utente
/api/v1/categories
categories:read
Elenca tutte le categorie definite dall’utente.
/api/v1/categories/{id}
categories:read
Recupera una categoria utente tramite id.
/api/v1/categories
categories:write
Crea una categoria utente.
| Campo | Tipo | Descrizione |
|---|---|---|
| name | string | obbligatorioNome visualizzato. Massimo 100. |
| type | string | obbligatorio"income" o "expense". |
| order | integer | obbligatorioPosizione di ordinamento all’interno del suo gruppo. |
| isPinned | boolean | obbligatorioFissa la categoria in cima al selettore. |
| categoryGroupId | string | facoltativoId del gruppo padre, oppure null se senza gruppo. |
| icon | string | facoltativoIdentificatore dell’icona. |
| color | string | facoltativoColore esadecimale. |
/api/v1/categories/{id}
categories:write
Sostituisce una categoria utente. Il corpo è identico a Crea.
/api/v1/categories/{id}
categories:write
Elimina logicamente una categoria utente. Le transazioni non vengono eliminate; il loro campo categoryId viene azzerato.
Gruppi di categorie
/api/v1/categories/groups
categories:read
Elenca i tuoi gruppi di categorie.
/api/v1/categories/groups/{id}
categories:read
Recupera un gruppo di categorie.
/api/v1/categories/groups
categories:write
Crea un gruppo di categorie.
| Campo | Tipo | Descrizione |
|---|---|---|
| name | string | obbligatorioNome visualizzato. Massimo 100. |
| order | integer | obbligatorioPosizione di ordinamento. |
| icon | string | facoltativoIdentificatore dell’icona. |
| color | string | facoltativoColore esadecimale. |
/api/v1/categories/groups/{id}
categories:write
Sostituisce un gruppo di categorie.
/api/v1/categories/groups/{id}
categories:write
Elimina logicamente un gruppo. Le categorie figlie sopravvivono: il loro campo categoryGroupId viene azzerato.
Budget
Un budget limita la spesa su una categoria (oppure, quando categoryId è null, sull’intero registro) in una finestra temporale ricorrente. Condividi un budget con un gruppo impostando groupId.
/api/v1/budgets
budgets:read
Elenca tutti i budget.
/api/v1/budgets/{id}
budgets:read
Recupera un budget.
/api/v1/budgets
budgets:write
Crea un budget.
| Campo | Tipo | Descrizione |
|---|---|---|
| amount | number | obbligatorioLimite per periodo. Deve essere maggiore di 0. |
| currencyCode | string | obbligatorioISO-4217. |
| period | integer | obbligatorio0 settimanale · 1 mensile · 2 trimestrale · 3 annuale. |
| startDate | string (ISO-8601) | obbligatorioInizio del primo periodo. |
| isActive | boolean | obbligatorioIndica se il budget è attualmente applicato. |
| endDate | string (ISO-8601) | facoltativoInterrompe il monitoraggio dopo questa data. |
| name | string | facoltativoEtichetta. Massimo 200. |
| categoryId | string | facoltativoCategoria da monitorare. Ometti per applicare il budget a tutte le spese. |
| groupId | string | facoltativoGruppo con cui condividere. Ometti per un budget personale. |
/api/v1/budgets/{id}
budgets:write
Sostituisce un budget.
/api/v1/budgets/{id}
budgets:write
Elimina logicamente un budget.
Gruppi
I gruppi sono registri condivisi: una famiglia, un viaggio, una casa condivisa. Ogni membro vede le stesse transazioni; la proprietà resta personale. Membri e inviti si gestiscono nell’app iOS; qui l’API espone la risorsa in sé.
/api/v1/groups
groups:read
Elenca i gruppi di cui sei proprietario o membro.
/api/v1/groups/{id}
groups:read
Recupera un gruppo.
/api/v1/groups
groups:write
Crea un gruppo. Ne diventi il proprietario; invita i membri dall’app iOS.
| Campo | Tipo | Descrizione |
|---|---|---|
| name | string | obbligatorioNome visualizzato. Massimo 100. |
| description | string | facoltativoTesto libero. Massimo 500. |
| icon | string | facoltativoIdentificatore dell’icona. |
| color | string | facoltativoColore esadecimale. |
/api/v1/groups/{id}
groups:write
Sostituisce i metadati di un gruppo.
/api/v1/groups/{id}
groups:write
Elimina logicamente un gruppo. I membri perdono la visibilità; le transazioni sottostanti tornano personali.
Transazioni
Le transazioni sono i verbi del registro. Esistono in quattro forme: income, expense, transfer (da conto a conto) e adjustment (riallineamento una tantum). L’endpoint di base crea entrate e spese; i trasferimenti hanno un endpoint dedicato; per gli importatori ad alto volume esistono le varianti in blocco.
/api/v1/transactions
transactions:read
Elenca le transazioni con paginazione a cursore e filtri.
| Campo | Tipo | Descrizione |
|---|---|---|
| limit | integer | facoltativoDimensione della pagina. 1..200. Valore predefinito 50. |
| cursor | string | facoltativoToken di continuazione opaco, ottenuto dalla risposta precedente. |
| type | string | facoltativo"income", "expense", "transfer" o "adjustment". |
| dateFrom | string (ISO-8601) | facoltativoLimite inferiore incluso. |
| dateTo | string (ISO-8601) | facoltativoLimite superiore incluso. |
| categoryId | string | facoltativoFiltra su una sola categoria. |
| accountId | string | facoltativoFiltra su un solo conto. |
| groupId | string | facoltativoFiltra su un gruppo condiviso. |
{
"items": [ /* TransactionDto[] */ ],
"totalCount": 317,
"nextCursor": "eyJrIjoiMjAyNi0wNS0xM1QxMDoz…"
}
/api/v1/transactions/{id}
transactions:read
Recupera una transazione.
/api/v1/transactions
transactions:write
Crea una singola transazione di entrata o di spesa. Per i trasferimenti, usa /transfer.
| Campo | Tipo | Descrizione |
|---|---|---|
| type | string | obbligatorio"income" o "expense". |
| amount | number | obbligatorioImporto positivo in currencyCode. |
| currencyCode | string | obbligatorioISO-4217. |
| date | string (ISO-8601) | obbligatorioQuando è avvenuta la transazione (UTC). |
| accountId | string | facoltativoConto di origine o di destinazione. |
| categoryId | string | facoltativoEtichetta di categoria. |
| payee | string | facoltativoEsercente o controparte. Massimo 200. |
| note | string | facoltativoNota in testo libero. Massimo 2000. |
| groupId | string | facoltativoCondivide con un gruppo. |
| exchangeRate | number | facoltativoTasso di cambio quando currencyCode ≠ valuta principale dell’utente. |
| convertedAmount | number | facoltativoImporto nella valuta principale dell’utente. |
POST /api/v1/transactions
{
"type": "expense",
"amount": 8.50,
"currencyCode": "EUR",
"date": "2026-05-12T09:14:00Z",
"accountId": "acc_01HK8V…",
"categoryId": "cat_food_drinks",
"payee": "Pret",
"note": "Flat white"
}
/api/v1/transactions/{id}
transactions:write
Sostituisce una transazione. Il corpo è identico a Crea.
/api/v1/transactions/{id}
transactions:write
Elimina logicamente una transazione.
/api/v1/transactions/transfer
transactions:write
Crea un trasferimento tra due conti. Nessuna categoria. Per i trasferimenti tra valute diverse, indica exchangeRate e convertedAmount nella valuta di destinazione.
| Campo | Tipo | Descrizione |
|---|---|---|
| fromAccountId | string | obbligatorioConto di origine. |
| toAccountId | string | obbligatorioConto di destinazione. Deve essere diverso da quello di origine. |
| amount | number | obbligatorioImporto inviato, in currencyCode. |
| currencyCode | string | obbligatorioValuta di origine, ISO-4217. |
| date | string (ISO-8601) | obbligatorioData del trasferimento. |
| exchangeRate | number | facoltativoObbligatorio quando la valuta di origine e quella di destinazione sono diverse. |
| convertedAmount | number | facoltativoImporto accreditato sul conto di destinazione, nella valuta di quest’ultimo. |
| note | string | facoltativoMassimo 2000. |
Operazioni in blocco
Pensate per gli importatori. Ogni lotto è limitato a 100 elementi e viene eseguito in modalità best-effort: una singola riga errata non annulla le altre. Gli elementi riusciti e gli errori riga per riga vengono riportati separatamente, così puoi riprovare solo quelli non riusciti.
/api/v1/transactions/bulk
transactions:write
Crea fino a 100 transazioni in un’unica chiamata.
{
"items": [ /* successful TransactionDto[] */ ],
"errors": [
{ "index": 3, "error": "Invalid currency code" }
]
}
/api/v1/transactions/bulk
transactions:write
Aggiorna fino a 100 transazioni in un’unica chiamata. Ogni elemento deve includere il proprio id insieme al corpo completo della transazione.
/api/v1/transactions/bulk-delete
transactions:write
Elimina logicamente fino a 100 transazioni in un’unica chiamata. Usa POST anziché DELETE, così il corpo della richiesta viene accettato da tutti i client HTTP.
| Campo | Tipo | Descrizione |
|---|---|---|
| ids | string[] | obbligatorioDa 1 a 100 id di transazioni. |
{
"deleted": 97,
"notFound": [ "tx_old1", "tx_old2", "tx_old3" ]
}
L’oggetto transazione
| Campo | Tipo | Descrizione |
|---|---|---|
| id | string | Identificatore opaco. |
| type | string | income · expense · transfer · adjustment. |
| amount | number | Espresso in currencyCode. |
| currencyCode | string | ISO-4217. |
| exchangeRate | number | null | Valorizzato sulle voci in valuta diversa. |
| convertedAmount | number | null | Lo stesso valore nella valuta principale dell’utente. |
| date | string | ISO-8601 UTC. |
| accountId | string | null | Nei trasferimenti è il conto di origine. |
| toAccountId | string | null | Conto di destinazione, solo nei trasferimenti. |
| categoryId | string | null | Null nei trasferimenti. |
| groupId | string | null | Valorizzato se la transazione è condivisa con un gruppo. |
| payee | string | null | Esercente o controparte. |
| note | string | null | Testo libero. |
| receiptImagePath | string | null | Percorso dello scontrino allegato. Recuperalo tramite l’endpoint degli scontrini (separato da v1). |
| recurringTransactionId | string | null | Valorizzato se la riga è stata generata da una regola ricorrente. |
| source | string | Tag di origine — api, mobile, web, import, ecc. |
| createdAt | string | ISO-8601 UTC. |
| updatedAt | string | ISO-8601 UTC. |
Icone
Manilo include un set di icone curato e una palette di colori usati ovunque: conti, categorie, gruppi. Recupera il catalogo una volta sola, mettilo in cache e riusa gli identificatori quando crei le risorse.
/api/v1/icons
Restituisce l’intera libreria di icone, raggruppata per categorie, insieme alla palette di colori supportata. È versionata: si può mettere in cache in sicurezza in base al campo version.
{
"version": "2026.05.10",
"library": "font-awesome-6",
"categories": [
{
"id": "finance",
"name": "Finance",
"icons": [ "wallet", "credit-card", "piggy-bank" ]
}
],
"colors": [
{ "name": "Blue", "hex": "#4A90E2" },
{ "name": "Green", "hex": "#22C55E" }
]
}
Versionamento
- Nessuna modifica incompatibile all’interno di v1. Aggiungeremo soltanto nuovi endpoint, nuovi campi facoltativi e nuovi valori di enum. Il tipo di un campo, la sua nullabilità o la sua obbligatorietà non cambieranno.
- I nuovi valori di enum non sono modifiche incompatibili. Tratta i valori sconosciuti di
type,sourceoactioncome “da non renderizzare” invece di andare in crash: li aggiungeremo man mano che il prodotto cresce. - Le modifiche incompatibili datate (se mai fossero necessarie) verranno rilasciate sotto
/api/v2/con almeno 6 mesi di disponibilità in parallelo e un’intestazione di deprecazione sulle risposte v1.
Assistenza
Hai trovato un bug, ti serve un endpoint o ti sei imbattuto in qualcosa di non documentato? Apri il centro assistenza oppure scrivi a support@manilo.app — quando segnali un problema, includi l’id della richiesta (riportato nell’intestazione di risposta X-Request-Id).
Per segnalazioni sensibili sul piano della sicurezza (un token trapelato, un aggiramento dei permessi, una lettura non autorizzata) scrivi a security@manilo.app.