Riferimento API di Flowyer
Versione API: 90bdda12e80e
La descrizione completa della REST API di Flowyer per sviluppatori: endpoint, parametri, risposte ed esempi di codice.
Con la API di Flowyer il suo software o un assistente IA può leggere, creare e modificare record (pratiche, clienti, attività, ore di lavoro, costi e documenti) per conto di un utente Flowyer. Ogni richiesta viene eseguita esattamente con i permessi di quell'utente, ulteriormente limitati dagli ambiti della chiave o dell'autorizzazione. Tramite la API non è possibile eliminare nulla.
Le descrizioni degli endpoint e dei campi sono in inglese, perché gli assistenti IA leggono proprio questo testo.
URL di base
Tutti gli endpoint si trovano sotto gli indirizzi seguenti. Usi sempre esattamente l'host https che inizia con www., perché un reindirizzamento eliminerebbe l'intestazione Authorization.
URL di base
https://www.flowyer.it/api/agent
https://www.flowyer.hu/api/agent
https://www.flowyer.com/api/agent
https://www.flowyer.ro/api/agent
https://www.flowyer.de/api/agent
Autenticazione
Ogni richiesta richiede un token Bearer nell'intestazione Authorization. Esistono due tipi di token; gli endpoint li trattano allo stesso modo.
Chiave API personale
L'utente la crea in Flowyer in Impostazioni > Chiavi API, dopo che un amministratore dello studio ha abilitato la API. Una chiave inizia con flw_, viene mostrata una sola volta e può essere revocata in qualsiasi momento con effetto immediato.
OAuth 2.1 per le applicazioni collegate
Un'integrazione destinata ad altri utenti richiede l'accesso con il flusso OAuth 2.1 Authorization Code + PKCE (S256) invece di una chiave; i client possono registrarsi dinamicamente. Un token di accesso vale 60 minuti, un token di aggiornamento 60 giorni, e la coppia viene sostituita a ogni utilizzo. Il code_verifier PKCE contiene da 43 a 128 caratteri tra A-Z, a-z, 0-9 e - . _ ~ (RFC 7636 4.1), cioè base64url senza riempimento: una "=" finale viene rifiutata.
- Metadati del server
https://www.flowyer.com/.well-known/oauth-authorization-server- Autorizzazione
https://www.flowyer.com/authorize- Token
https://www.flowyer.com/api/agent/oauth/token- Registrazione del client
https://www.flowyer.com/api/agent/oauth/register- Revoca
https://www.flowyer.com/api/agent/oauth/revoke
Esempi di richiesta
curl 'https://www.flowyer.it/api/agent/me' \
-H 'Authorization: Bearer flw_...'
Ambiti
Ogni endpoint tranne GET /me richiede un ambito (scope). Se la chiave o l'autorizzazione non lo include, la risposta è 403 scope_missing. GET /me non richiede alcun ambito: serve a vedere cosa può fare la credenziale.
| Ambito | Significato | Endpoint |
|---|---|---|
matters:read |
Lettura pratiche | GETElenca le pratiche GETRisolvi la pratica per nome GETOttieni la pratica GETElenca i responsabili della pratica |
matters:create |
Creazione pratiche | POSTCrea una pratica |
matters:update |
Modifica pratiche | PATCHAggiorna la pratica POSTAggiungi un responsabile della pratica |
clients:read |
Lettura clienti | GETElenca i clienti GETRisolvi il cliente per nome GETOttieni il cliente |
clients:create |
Creazione clienti | POSTCrea un cliente |
clients:update |
Modifica clienti | PATCHAggiorna il cliente |
tasks:read |
Lettura attività | GETElenca le attività GETOttieni l'attività |
tasks:create |
Creazione attività | POSTCrea un'attività |
tasks:update |
Modifica attività | PATCHAggiorna l'attività POSTChiudi l'attività |
workhours:read |
Lettura ore | GETElenca le voci di tempo GETOttieni la voce di tempo |
workhours:create |
Registrazione ore | POSTRegistra una voce di tempo |
workhours:update |
Modifica ore | PATCHAggiorna la voce di tempo |
costs:read |
Lettura costi | GETElenca i costi GETOttieni il costo |
costs:create |
Registrazione costi | POSTRegistra un costo |
costs:update |
Modifica costi | PATCHAggiorna il costo |
invoices:read |
Lettura fatture | GETElenca le fatture GETOttieni la fattura |
documents:read |
Elenco documenti (solo metadati, senza download) | GETElenca i documenti della pratica GETElenca le cartelle della pratica |
documents:download |
Download documenti (contenuto completo) | GETScarica il documento |
documents:create |
Caricamento documenti | POSTCrea una cartella della pratica POSTAvvia il caricamento del documento POSTCompleta il caricamento del documento |
documents:update |
Rinomina documenti | PATCHRinomina il documento PATCHRinomina la cartella della pratica |
colleagues:read |
Elenco dei colleghi (solo nomi) | GETElenca i colleghi |
knowledge:read |
Lettura della knowledge base | GETElenca gli articoli della knowledge base GETOttieni l'articolo della knowledge base GETElenca le categorie della knowledge base GETOttieni la categoria della knowledge base |
knowledge:create |
Creazione di voci nella knowledge base | POSTCrea un articolo della knowledge base POSTCrea una categoria della knowledge base |
knowledge:update |
Modifica di voci nella knowledge base | PATCHAggiorna l'articolo della knowledge base PATCHAggiorna la categoria della knowledge base |
emails:read |
Lettura email delle pratiche | GETElenca le email della pratica GETOttieni l'email |
litigation:read |
Elenco cronologia processuale | GETElenca la cronologia processuale della pratica |
litigation:create |
Creazione voce cronologia processuale | POSTCrea una voce della cronologia processuale |
litigation:update |
Modifica voce cronologia processuale | PATCHAggiorna la voce della cronologia processuale |
mail_register:read |
Lettura registro postale | GETElenca il registro postale GETOttieni la voce del registro postale |
mail_register:create |
Creazione voci registro postale | POSTCrea una voce del registro postale |
mail_register:update |
Modifica voci registro postale | PATCHAggiorna la voce del registro postale |
comments:read |
Lettura dei commenti del caso | GETElenca i commenti della pratica |
comments:create |
Pubblicazione di commenti al caso | POSTPubblica un commento della pratica |
comments:update |
Modifica dei propri commenti | PATCHModifica un proprio commento della pratica |
trials:read |
Lettura delle udienze | GETElenca le udienze della pratica GETOttieni l'udienza |
trials:create |
Creazione udienze | POSTCrea un'udienza |
trials:update |
Modifica udienze | PATCHAggiorna l'udienza |
courts:read |
Elenco dei tribunali | GETElenca i tribunali |
hr:read |
Lettura delle assenze (solo date) | GETElenca le assenze del personale |
calendar:read |
Lettura eventi del calendario | GETElenca gli eventi del calendario GETOttieni l'evento del calendario |
calendar:create |
Creazione eventi del calendario | POSTCrea un evento del calendario |
calendar:update |
Modifica eventi del calendario | PATCHAggiorna l'evento del calendario |
bookings:read |
Visualizzare le prenotazioni di appuntamenti | GETElenca le prenotazioni GETOttieni la prenotazione |
bookings:create |
Creare prenotazioni di appuntamenti (invia un'email al cliente) | POSTCrea una prenotazione |
bookings:update |
Riprogrammare e modificare le prenotazioni | PATCHAggiorna la prenotazione |
bookings:send |
Confermare o annullare prenotazioni (invia un'email al cliente) | POSTConferma la prenotazione POSTAnnulla la prenotazione |
tickets:read |
Lettura dei ticket di assistenza | GETElenca i ticket GETOttieni il ticket |
tickets:reply |
Rispondere ai ticket (invia un'e-mail al cliente) | POSTRispondi al ticket |
tickets:update |
Modifica dello stato del ticket | PATCHCambia lo stato del ticket |
portal:read |
Portale clienti: lettura di conversazioni e messaggi | GETElenca i portali clienti GETElenca i messaggi del portale |
portal:reply |
Portale clienti: rispondere al cliente (invia un messaggio e una e-mail di notifica) | POSTRispondi nel portale clienti |
Errori
Ogni errore ha la stessa struttura: un codice (error), un messaggio in inglese (message), il messaggio nella lingua dello studio (message_localized) e dettagli facoltativi (details). Con 401, 403, 404 e 422 non ha senso ripetere la richiesta invariata, con due eccezioni: con 404 upload_not_finished completi prima il caricamento su upload_url, poi richiami complete; con un token di accesso OAuth scaduto (401 expired_key) rinnovi prima il token.
| HTTP | error | Significato |
|---|---|---|
| 400 | invalid_json use_www_host bad_request |
Richiesta non valida: corpo JSON non valido, host errato (usare l'host www.) o richiesta illeggibile. |
| 401 | missing_key invalid_key revoked_key expired_key user_inactive office_not_found |
La chiave manca, non è valida, è revocata o scaduta, il suo titolare non è più attivo, oppure lo studio della chiave non è stato trovato. |
| 403 | scope_missing module_forbidden forbidden office_api_disabled licence_expired office_archived |
Manca un permesso sulla chiave o sull'utente, oppure lo studio non ha abilitato l'API. |
| 404 | not_found matter_not_visible unknown_endpoint upload_not_finished replay_not_visible |
Il record non esiste o l'utente non può vederlo; endpoint sconosciuto; il file caricato non è ancora arrivato nello storage (upload_not_finished: lo carichi su upload_url, poi richiami complete); oppure una creazione ripetuta il cui record era già stato creato ma nel frattempo è stato eliminato o nascosto (replay_not_visible: non è stato creato nulla di nuovo, non lo crei di nuovo). |
| 405 | delete_not_allowed update_not_allowed method_not_allowed |
Eliminare non è possibile tramite l'API; modificare solo dove la descrizione offre un'operazione PATCH. |
| 409 | client_exists client_exists_generic idempotency_key_reused duplicate_in_progress record_conflict record_locked duplicate_name |
Esiste già un cliente con quel nome; nella cartella esiste già un documento con quel nome (duplicate_name); il record è cambiato dopo la lettura (record_conflict: lo rilegga e reinvii la modifica con il nuovo updated_at); il record è stato fatturato o bloccato (record_locked: esegua la modifica in Flowyer); l'Idempotency-Key è stato usato su un'altra risorsa; oppure una richiesta identica è in elaborazione. |
| 413 | request_too_large file_too_large |
Il corpo della richiesta è troppo grande (request_too_large), oppure il file da caricare supera il limite (file_too_large; details.max indica il limite in byte). |
| 422 | validation_failed unknown_client unknown_colleague blocked_file_type upload_token_invalid folder_not_in_matter document_name_too_long |
Un campo non valido o mancante (details.fields indica quale); un token di caricamento non valido, già usato o scaduto (upload_token_invalid: ricominci il caricamento); oppure una cartella che non appartiene alla pratica (folder_not_in_matter). |
| 429 | rate_limited auth_rate_limited |
Troppe richieste (300 al minuto per chiave); l'intestazione Retry-After indica quando riprovare. |
| 500 | server_error |
Errore imprevisto. La richiesta è stata registrata con il suo request_id; riprovare più tardi e, se si ripete, comunicare questo ID all'assistenza Flowyer. |
| 503 | office_maintenance office_setup_incomplete temporarily_unavailable |
Lo studio non è temporaneamente disponibile (manutenzione o configurazione in corso); l'intestazione Retry-After indica quando riprovare. |
Esempi di risposta · 403
{
"error": "scope_missing",
"message": "This API key does not have the \"clients:create\" permission. The permissions of an existing key cannot be changed, so the key owner needs to create a new key with this permission in Flowyer under Settings > API keys and use it in place of the old one.",
"message_localized": "Questa chiave API non ha il permesso \"clients:create\". I permessi di una chiave esistente non possono essere modificati, quindi il titolare della chiave deve creare in Flowyer, in Impostazioni > Chiavi API, una nuova chiave con questo permesso e usarla al posto di quella vecchia.",
"locale": "it",
"details": {
"required_scope": "clients:create"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Paginazione
Gli elenchi di record si sfogliano con i parametri limit e offset (predefinito 25, al massimo 100 elementi per pagina). pagination.total è il numero totale di risultati; l'offset della pagina successiva è l'offset precedente più limit. GET /colleagues, GET /clients/resolve e GET /matters/resolve non si sfogliano: accettano solo limit (con un valore predefinito e un massimo propri, si veda il singolo endpoint) e restituiscono total e truncated dentro data invece di un oggetto pagination, quindi non invii loro un offset.
Esempi di risposta · 200
{
"data": [
{
"id": 1234,
"...": "..."
}
],
"pagination": {
"limit": 25,
"offset": 0,
"total": 134
}
}
Ripetizioni sicure
Ogni creazione accetta un'intestazione Idempotency-Key (o un campo idempotency_key). Una richiesta ripetuta con lo stesso valore restituisce il record creato la prima volta (200, idempotent_replay) invece di crearne un altro. Chiavi diverse creano sempre record distinti. Senza chiave, una creazione identica entro 120 secondi restituisce il primo record.
Esempi di richiesta
curl -X POST 'https://www.flowyer.it/api/agent/clients' \
-H 'Authorization: Bearer flw_...' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: 7f3a9c21-1b2c-4d5e-8f90-0a1b2c3d4e5f' \
-d '{"name": "Kovács Kft."}'
Modifiche e conflitti
Una modifica è una richiesta PATCH sul percorso del record: cambiano solo i campi inviati, e un null esplicito svuota un campo solo se la descrizione del campo lo consente; per alcuni campi il null mantiene il valore memorizzato, quindi legga la descrizione del campo. Invii in expected_updated_at il valore updated_at della sua ultima lettura. Se nel frattempo qualcun altro ha modificato il record, la risposta è 409 record_conflict; in tal caso rilegga il record.
Esempi di richiesta
curl -X PATCH 'https://www.flowyer.it/api/agent/matters/1234' \
-H 'Authorization: Bearer flw_...' \
-H 'Content-Type: application/json' \
-d '{"expected_updated_at": "2026-10-30T09:15:00+01:00", "description": null}'
Date e fuso orario
Le date hanno il formato AAAA-MM-GG, gli istanti seguono ISO 8601 con lo scostamento del fuso orario dello studio. Il fuso orario dello studio si trova nel campo office.timezone della risposta di GET /me.
Limiti
Al massimo 300 richieste al minuto per chiave o token; oltre, la risposta è 429 e l'intestazione Retry-After indica quando riprovare. Il corpo di una richiesta JSON può essere al massimo di 64 KB, un documento caricato al massimo di 100 MB.
Versioni
La versione della descrizione OpenAPI cambia a ogni modifica ed è inviata anche come intestazione ETag, così i client possono verificare con If-None-Match se è cambiata.
Identità
Chi sono
/api/agent/me
Restituisce l'utente e lo studio per conto dei quali agisce questa chiave API, gli scope della chiave (cosa può fare) e i limiti di frequenza. La richiami per prima per sapere quali operazioni sono disponibili; non richiede alcuno scope.
Questo endpoint non ha input.
Risposte
200
OK.
dataobbligatorioCampi di data
userCampi di user
idnamelanguageofficeCampi di office
idnametimezoneZona IANA in cui l'API legge e scrive i timestamp, ad es. Europe/Budapest.
currency_idLa valuta dello studio (id valuta Flowyer): costs.create contabilizza in essa quando currency_id è omesso.
currencyCodice ISO della valuta dello studio, ad es. HUF, EUR, RON.
keyCampi di key
idnameNome che l'utente ha assegnato a questa chiave, oppure l'app connessa per un token OAuth.
kind"key" = una chiave API statica, "oauth" = un token di accesso OAuth 2.1.
"key" "oauth" prefixPrimi caratteri di una chiave statica, solo per identificazione; null per OAuth.
expires_atlast_used_atscopesScope di questa credenziale, ad es. "matters:read". Un'operazione il cui scope è mancante risponde 403.
available_scopesTutti gli scope che il proprietario della chiave potrebbe abilitare in Flowyer.
limitsCampi di limits
requests_per_minutelist_max_limitchannelCome la richiesta ha raggiunto Flowyer.
"rest" "mcp"
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
422
Parametro di query sconosciuto (questa operazione non ne accetta nessuno); details.fields lo nomina.
details.fields lo nomina.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl 'https://www.flowyer.it/api/agent/me' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.it/api/agent/me", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.it/api/agent/me",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Esempi di risposta
{
"data": {
"user": {
"id": 1234,
"name": "string",
"language": "string"
},
"office": {
"id": 1234,
"name": "string",
"timezone": "string",
"currency_id": 1234,
"currency": "string"
},
"key": {
"id": 1234,
"name": "string",
"kind": "key",
"prefix": "string",
"expires_at": "2026-10-30T09:15:00+01:00",
"last_used_at": "2026-10-30T09:15:00+01:00"
},
"scopes": [
"string"
],
"available_scopes": [
"string"
],
"limits": {
"requests_per_minute": 0,
"list_max_limit": 0
},
"channel": "rest"
}
}
{
"error": "invalid_key",
"message": "The API key is not valid.",
"message_localized": "La chiave API non è valida.",
"locale": "it",
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Colleghi
Elenca i colleghi
/api/agent/colleagues
Elenca i colleghi attivi dello studio (id, nome) per assigned_to_user_id / responsible_user_id. Con q (un nome così come ascoltato; accenti, maiuscole/minuscole e piccoli errori di battitura tollerati) risponde con lo stato exact/similar/none come gli strumenti resolve: solo "exact" è sicuro da usare direttamente.
Parametri di query
qNome di un collega da cercare, così come ascoltato o dettato, in qualsiasi ordine delle parole. Lo ometta per elencare tutti i colleghi attivi.
"Nagy Péter"limitNumero massimo di colleghi da restituire (predefinito 200).
200Risposte
200
OK.
dataobbligatorioCampi di data
statusSolo con q: exact = una corrispondenza certa (sicuro usare il suo id), similar = corrispondenza approssimativa o più corrispondenze (prima confermi con l'utente), none = nessuna corrispondenza (chieda all'utente). Null senza q.
"exact" "similar" "none" colleaguesColleghi attivi, prima la corrispondenza migliore con q, altrimenti per nome.
Campi di colleagues
idId utente: lo passi come assigned_to_user_id / responsible_user_id.
nameNome visualizzato così come lo mostra Flowyer (con il titolo, se presente).
titlePrefisso del nome come "Dr.", oppure null.
totalQuanti colleghi hanno corrisposto (tutti i colleghi attivi senza q) prima che l'elenco fosse ridotto a limit.
truncatedTrue quando hanno corrisposto più colleghi di quanti ne siano stati restituiti: restringa q o aumenti limit.
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl 'https://www.flowyer.it/api/agent/colleagues?q=Nagy%20P%C3%A9ter' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.it/api/agent/colleagues?q=Nagy%20P%C3%A9ter", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.it/api/agent/colleagues?q=Nagy%20P%C3%A9ter",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Esempi di risposta
{
"data": {
"status": "exact",
"colleagues": [
{
"id": 1234,
"name": "string",
"title": "string"
}
],
"total": 1,
"truncated": true
}
}
{
"error": "scope_missing",
"message": "This API key does not have the \"colleagues:read\" permission. The permissions of an existing key cannot be changed, so the key owner needs to create a new key with this permission in Flowyer under Settings > API keys and use it in place of the old one.",
"message_localized": "Questa chiave API non ha il permesso \"colleagues:read\". I permessi di una chiave esistente non possono essere modificati, quindi il titolare della chiave deve creare in Flowyer, in Impostazioni > Chiavi API, una nuova chiave con questo permesso e usarla al posto di quella vecchia.",
"locale": "it",
"details": {
"required_scope": "colleagues:read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Pratiche
Elenca le pratiche
/api/agent/matters
Elenca le pratiche (cause) che l'utente può visualizzare, dalla più recente. La usi per trovare una pratica tramite numero di fascicolo, oggetto o cliente prima di farvi riferimento altrove. Le pratiche archiviate sono nascoste a meno che include_archived non sia true.
Parametri di query
qRicerca a testo libero nell'oggetto e nei nomi dei clienti (accenti e maiuscole/minuscole ignorati) e negli altri numeri di fascicolo dello studio; oppure un numero di fascicolo, esattamente come restituito in case_number (lo schema di numerazione dello studio) o nel formato anno/sequenza come "2026/0025".
"2026/0025"client_idSolo le pratiche di questo cliente.
512responsible_user_idSolo le pratiche di cui questo utente (id da colleagues.list) è responsabile: come responsabile principale, responsabile aggiuntivo o membro di un gruppo di lavoro responsabile (come il filtro colleghi del web).
updated_sinceSolo le pratiche modificate a partire da questo momento (ISO 8601).
"2026-10-01T00:00:00+02:00"include_archivedIncluda le pratiche archiviate.
falselimitDimensione della pagina, 1-100. Valore predefinito 25.
2525offsetNumero di record da saltare. Usi offset + limit della pagina precedente per ottenere quella successiva; pagination.total è il conteggio totale.
00Risposte
200
OK.
dataobbligatorioCampi di data
idId della pratica. Lo usi come matter_id altrove.
1234case_numberNumero di fascicolo come visualizzato in Flowyer, nello schema di numerazione dello studio.
"2026/0025"subject"Kovács Kft. v. Nagy Bt. - contract dispute"status"active" "archived" case_type_idcase_typeNome localizzato del tipo di pratica.
responsible_user_idresponsibleNome visualizzato dell'avvocato responsabile.
clientsClienti (mandanti) della pratica.
Campi di clients
idnamestarted_onrestrictedTrue quando solo gli avvocati responsabili possono visualizzare la pratica (muro cinese).
created_atupdated_atcreated_via_apiPresente quando un agente esterno ha creato il record tramite questa API.
Campi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduseratpaginationobbligatorioCampi di pagination
limitobbligatoriooffsetobbligatoriototalobbligatorioNumero totale di record corrispondenti.
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl 'https://www.flowyer.it/api/agent/matters?q=2026%2F0025&client_id=512&updated_since=2026-10-01T00%3A00%3A00%2B02%3A00' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.it/api/agent/matters?q=2026%2F0025&client_id=512&updated_since=2026-10-01T00%3A00%3A00%2B02%3A00", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.it/api/agent/matters?q=2026%2F0025&client_id=512&updated_since=2026-10-01T00%3A00%3A00%2B02%3A00",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Esempi di risposta
{
"data": [
{
"id": 1234,
"case_number": "2026/0025",
"subject": "Kovács Kft. v. Nagy Bt. - contract dispute",
"status": "active",
"case_type_id": 1234,
"case_type": "string",
"responsible_user_id": 1234,
"responsible": "string",
"clients": [
{
"id": 1234,
"name": "string"
}
],
"started_on": "2026-10-30",
"restricted": true,
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
}
}
],
"pagination": {
"limit": 25,
"offset": 0,
"total": 1
}
}
{
"error": "scope_missing",
"message": "This API key does not have the \"matters:read\" permission. The permissions of an existing key cannot be changed, so the key owner needs to create a new key with this permission in Flowyer under Settings > API keys and use it in place of the old one.",
"message_localized": "Questa chiave API non ha il permesso \"matters:read\". I permessi di una chiave esistente non possono essere modificati, quindi il titolare della chiave deve creare in Flowyer, in Impostazioni > Chiavi API, una nuova chiave con questo permesso e usarla al posto di quella vecchia.",
"locale": "it",
"details": {
"required_scope": "matters:read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Risolvi la pratica per nome
/api/agent/matters/resolve
Trova una pratica tramite un oggetto o un nome cliente pronunciato o scritto in modo errato (accenti, maiuscole/minuscole e piccoli refusi tollerati). Restituisce lo stato exact/similar/none e i candidati. Solo "exact" è sicuro da usare direttamente; altrimenti confermi con l'utente. Molti casi simili non sono mai "exact": restringa con client_id o un nome più completo.
Parametri di query
nameobbligatorioOggetto della pratica o nome del cliente da cercare, come ascoltato o dettato.
"ingatlan adásvétel"client_idSolo le pratiche di questo cliente (da usare dopo che clients.resolve ha restituito un cliente exact).
limitNumero massimo di candidati da restituire (valore predefinito 5).
5Risposte
200
OK.
dataobbligatorioCampi di data
statusexact = una corrispondenza certa (sicuro usarne l'id). similar = una o più corrispondenze approssimative, confermi prima con l'utente. none = nessuna corrispondenza, chieda all'utente.
"exact" "similar" "none" mattersPratiche candidate, la corrispondenza migliore per prima.
Campi di matters
idId della pratica. Lo usi come matter_id altrove.
1234case_numberNumero di fascicolo come visualizzato in Flowyer, nello schema di numerazione dello studio.
"2026/0025"subject"Kovács Kft. v. Nagy Bt. - contract dispute"status"active" "archived" case_type_idcase_typeNome localizzato del tipo di pratica.
responsible_user_idresponsibleNome visualizzato dell'avvocato responsabile.
clientsClienti (mandanti) della pratica.
Campi di clients
idnamestarted_onrestrictedTrue quando solo gli avvocati responsabili possono visualizzare la pratica (muro cinese).
created_atupdated_atcreated_via_apiPresente quando un agente esterno ha creato il record tramite questa API.
Campi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduserattotalQuante pratiche hanno corrisposto prima che l'elenco fosse ridotto a limit.
truncatedTrue quando hanno corrisposto più pratiche di quelle restituite, oppure esistevano troppi casi simili per verificarli tutti; restringa con client_id o un nome più completo, oppure aumenti limit, invece di scegliere da un elenco incompleto.
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl 'https://www.flowyer.it/api/agent/matters/resolve?name=ingatlan%20ad%C3%A1sv%C3%A9tel' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.it/api/agent/matters/resolve?name=ingatlan%20ad%C3%A1sv%C3%A9tel", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.it/api/agent/matters/resolve?name=ingatlan%20ad%C3%A1sv%C3%A9tel",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Esempi di risposta
{
"data": {
"status": "exact",
"matters": [
{
"id": 1234,
"case_number": "2026/0025",
"subject": "Kovács Kft. v. Nagy Bt. - contract dispute",
"status": "active",
"case_type_id": 1234,
"case_type": "string",
"responsible_user_id": 1234,
"responsible": "string",
"clients": [
{
"id": 1234,
"name": "string"
}
],
"started_on": "2026-10-30",
"restricted": true,
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
}
}
],
"total": 1,
"truncated": true
}
}
{
"error": "scope_missing",
"message": "This API key does not have the \"matters:read\" permission. The permissions of an existing key cannot be changed, so the key owner needs to create a new key with this permission in Flowyer under Settings > API keys and use it in place of the old one.",
"message_localized": "Questa chiave API non ha il permesso \"matters:read\". I permessi di una chiave esistente non possono essere modificati, quindi il titolare della chiave deve creare in Flowyer, in Impostazioni > Chiavi API, una nuova chiave con questo permesso e usarla al posto di quella vecchia.",
"locale": "it",
"details": {
"required_scope": "matters:read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Ottieni la pratica
/api/agent/matters/{id}
Restituisce una pratica (causa) con i suoi clienti e dettagli. Risponde 404 quando la pratica non esiste o l'utente non può visualizzarla.
Parametri di percorso
idobbligatorioId della pratica.
1234Risposte
200
OK.
dataobbligatorioCampi di data
idId della pratica. Lo usi come matter_id altrove.
1234case_numberNumero di fascicolo come visualizzato in Flowyer, nello schema di numerazione dello studio.
"2026/0025"subject"Kovács Kft. v. Nagy Bt. - contract dispute"status"active" "archived" case_type_idcase_typeNome localizzato del tipo di pratica.
responsible_user_idresponsibleNome visualizzato dell'avvocato responsabile.
clientsClienti (mandanti) della pratica.
Campi di clients
idnamestarted_onrestrictedTrue quando solo gli avvocati responsabili possono visualizzare la pratica (muro cinese).
created_atupdated_atcreated_via_apiPresente quando un agente esterno ha creato il record tramite questa API.
Campi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduseratdescriptionlitigiousarchived_atGiorno in cui la pratica è stata archiviata, YYYY-MM-DD. Flowyer registra solo la data, non l'ora del giorno.
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl 'https://www.flowyer.it/api/agent/matters/1234' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.it/api/agent/matters/1234", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.it/api/agent/matters/1234",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Esempi di risposta
{
"data": {
"id": 1234,
"case_number": "2026/0025",
"subject": "Kovács Kft. v. Nagy Bt. - contract dispute",
"status": "active",
"case_type_id": 1234,
"case_type": "string",
"responsible_user_id": 1234,
"responsible": "string",
"clients": [
{
"id": 1234,
"name": "string"
}
],
"started_on": "2026-10-30",
"restricted": true,
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
},
"description": "string",
"litigious": true,
"archived_at": "2026-10-30"
}
}
{
"error": "matter_not_visible",
"message": "The matter 1234 does not exist, is archived, or is not visible to the user who owns this API key.",
"message_localized": "La pratica 1234 non esiste, è archiviata oppure non è visibile al titolare di questa chiave API.",
"locale": "it",
"details": {
"matter_id": 1234
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Crea una pratica
/api/agent/matters
Apre una pratica (causa) con il numero di fascicolo successivo dell'anno. Richiede almeno un cliente esistente (lo trovi o lo crei prima). L'avvocato responsabile è per impostazione predefinita l'utente della chiave e viene notificato in caso contrario. Parti, contatti e onorari si impostano in Flowyer.
Parametri di intestazione
Idempotency-KeyConsigliato a ogni creazione. Un valore univoco per operazione logica (ad es. un UUID). Lo stesso valore restituisce lo stesso record: riprovare con esso restituisce il record creato la prima volta invece di crearne un secondo. Valori diversi creano sempre record diversi. I client che non possono inviare header possono passare lo stesso valore nel campo del corpo idempotency_key. Lettere, cifre, _, -, : o ., al massimo 128 caratteri.
^[A-Za-z0-9_\-:.]{1,128}$Corpo della richiesta application/json
subjectobbligatorioTitolo breve della pratica come appare negli elenchi. Testo semplice; "<" e ">" non sono consentiti.
^[^<>]*$"Kovács Kft. v. Nagy Bt. - contract dispute"case_type_idobbligatorioId del tipo di pratica (area del diritto) dall'elenco globale dei tipi di pratica di Flowyer: scelga quello il cui nome corrisponde alle parole dell'utente, oppure chieda all'utente di sceglierlo per nome. Un id sconosciuto risponde 422 con details.known_case_types (id + nome localizzato); una pratica esistente mostra il suo tipo in matters.get case_type_id / case_type.
client_idsobbligatorioId dei clienti (mandanti). Almeno uno, al massimo 20.
[
512
]responsible_user_idAvvocato responsabile: un id utente da colleagues.list (vi cerchi un nome dettato). Valore predefinito: l'utente dietro la chiave.
started_onData di inizio, YYYY-MM-DD. Valore predefinito: oggi.
"2026-10-29"descriptionDescrizione più lunga, testo semplice.
main_case_numberIl numero di riferimento principale proprio dello studio per la pratica. Obbligatorio quando lo schema di numerazione dello studio lo utilizza (in caso contrario l'API risponde 422).
restrictedtrue = solo gli avvocati responsabili possono visualizzare la pratica (muro cinese).
falseidempotency_keyStesso ruolo dell'header Idempotency-Key, per i client che non possono inviare header personalizzati. Lettere, cifre, _, -, : o ., al massimo 128 caratteri.
^[A-Za-z0-9_\-:.]{1,128}$"b8f1c2e0-6f7a-4d2e-9c1b-2a3d4e5f6a7b"Risposte
201
Creato.
dataobbligatorioCampi di data
idId della pratica. Lo usi come matter_id altrove.
1234case_numberNumero di fascicolo come visualizzato in Flowyer, nello schema di numerazione dello studio.
"2026/0025"subject"Kovács Kft. v. Nagy Bt. - contract dispute"status"active" "archived" case_type_idcase_typeNome localizzato del tipo di pratica.
responsible_user_idresponsibleNome visualizzato dell'avvocato responsabile.
clientsClienti (mandanti) della pratica.
Campi di clients
idnamestarted_onrestrictedTrue quando solo gli avvocati responsabili possono visualizzare la pratica (muro cinese).
created_atupdated_atcreated_via_apiPresente quando un agente esterno ha creato il record tramite questa API.
Campi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduseratdescriptionlitigiousarchived_atGiorno in cui la pratica è stata archiviata, YYYY-MM-DD. Flowyer registra solo la data, non l'ora del giorno.
createdtrue
200
Replay idempotente: questo Idempotency-Key (o, senza chiave, una richiesta identica entro 120 secondi) ha già creato il record; viene restituito di nuovo, nulla di nuovo è stato creato.
dataobbligatorioCampi di data
idId della pratica. Lo usi come matter_id altrove.
1234case_numberNumero di fascicolo come visualizzato in Flowyer, nello schema di numerazione dello studio.
"2026/0025"subject"Kovács Kft. v. Nagy Bt. - contract dispute"status"active" "archived" case_type_idcase_typeNome localizzato del tipo di pratica.
responsible_user_idresponsibleNome visualizzato dell'avvocato responsabile.
clientsClienti (mandanti) della pratica.
Campi di clients
idnamestarted_onrestrictedTrue quando solo gli avvocati responsabili possono visualizzare la pratica (muro cinese).
created_atupdated_atcreated_via_apiPresente quando un agente esterno ha creato il record tramite questa API.
Campi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduseratdescriptionlitigiousarchived_atGiorno in cui la pratica è stata archiviata, YYYY-MM-DD. Flowyer registra solo la data, non l'ora del giorno.
createdfalseidempotent_replaytrue
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente. replay_not_visible: questo Idempotency-Key (o, senza chiave, una richiesta identica) ha già creato il record (details.record_id), ma da allora è stato eliminato o non è visibile all'utente; nulla di nuovo è stato creato, non lo ricrei.
replay_not_visible: questo Idempotency-Key (o, senza chiave, una richiesta identica) ha già creato il record (details.record_id), ma da allora è stato eliminato o non è visibile all'utente; nulla di nuovo è stato creato, non lo ricrei.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
409
L'Idempotency-Key è stato usato per un altro tipo di risorsa (idempotency_key_reused), oppure, senza chiave, una richiesta identica è in fase di elaborazione in questo momento (duplicate_in_progress; riprovi a breve).
idempotency_key_reused), oppure, senza chiave, una richiesta identica è in fase di elaborazione in questo momento (duplicate_in_progress; riprovi a breve).
413
Il corpo della richiesta è troppo grande (request_too_large).
request_too_large).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl -X POST 'https://www.flowyer.it/api/agent/matters' \
-H 'Authorization: Bearer flw_...' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: 7f3a9c21-1b2c-4d5e-8f90-0a1b2c3d4e5f' \
-d '{
"subject": "Kovács Kft. v. Nagy Bt. - contract dispute",
"case_type_id": 1234,
"client_ids": [
512
],
"started_on": "2026-10-29"
}'
const response = await fetch("https://www.flowyer.it/api/agent/matters", {
method: "POST",
headers: {
"Authorization": "Bearer flw_...",
"Content-Type": "application/json",
"Idempotency-Key": crypto.randomUUID(),
},
body: JSON.stringify({
"subject": "Kovács Kft. v. Nagy Bt. - contract dispute",
"case_type_id": 1234,
"client_ids": [
512
],
"started_on": "2026-10-29"
}),
});
const result = await response.json();
import uuid
import requests
response = requests.post(
"https://www.flowyer.it/api/agent/matters",
headers={
"Authorization": "Bearer flw_...",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"subject": "Kovács Kft. v. Nagy Bt. - contract dispute",
"case_type_id": 1234,
"client_ids": [
512,
],
"started_on": "2026-10-29",
},
timeout=30,
)
print(response.status_code, response.json())
{
"subject": "Kovács Kft. v. Nagy Bt. - contract dispute",
"case_type_id": 1234,
"client_ids": [
512
],
"started_on": "2026-10-29"
}
Esempi di risposta
{
"data": {
"id": 1234,
"case_number": "2026/0025",
"subject": "Kovács Kft. v. Nagy Bt. - contract dispute",
"status": "active",
"case_type_id": 1234,
"case_type": "string",
"responsible_user_id": 1234,
"responsible": "string",
"clients": [
{
"id": 1234,
"name": "string"
}
],
"started_on": "2026-10-30",
"restricted": true,
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
},
"description": "string",
"litigious": true,
"archived_at": "2026-10-30"
},
"created": true
}
{
"data": {
"id": 1234,
"case_number": "2026/0025",
"subject": "Kovács Kft. v. Nagy Bt. - contract dispute",
"status": "active",
"case_type_id": 1234,
"case_type": "string",
"responsible_user_id": 1234,
"responsible": "string",
"clients": [
{
"id": 1234,
"name": "string"
}
],
"started_on": "2026-10-30",
"restricted": true,
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
},
"description": "string",
"litigious": true,
"archived_at": "2026-10-30"
},
"created": false,
"idempotent_replay": true
}
{
"error": "validation_failed",
"message": "The request is invalid. See \"details.fields\" for the field-level errors.",
"message_localized": "La richiesta non è valida. Gli errori per campo sono in \"details.fields\".",
"locale": "it",
"details": {
"fields": {
"subject": [
"Il campo subject è obbligatorio."
]
}
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Aggiorna la pratica
/api/agent/matters/{id}
Modifica l'oggetto, la descrizione, la data di inizio, il flag contenzioso o l'avvocato responsabile di una pratica. Numero di fascicolo, muro cinese, stato di archiviazione, onorari e collegamenti ai clienti non sono modificabili qui. Passi expected_updated_at dalla sua ultima lettura; una modifica in conflitto risponde 409.
Parametri di percorso
idobbligatorioId del record da modificare.
Corpo della richiesta application/json
expected_updated_atIl valore updated_at dalla sua lettura più recente di questo record (obbligatorio ogni volta che il record ne ha uno). Se il record è cambiato da allora (un collega lo ha modificato), l'API risponde 409 e deve rileggere prima di riprovare. Un record legacy il cui updated_at è null accetta null.
subjectTitolo breve della pratica. Testo semplice, al massimo 255 caratteri come NUOVO valore; nemmeno "<" e ">" possono essere introdotti, ma un oggetto memorizzato più lungo o che li contiene può essere restituito invariato. null mantiene l'oggetto attuale.
descriptionDescrizione più lunga, testo semplice, al massimo 10000 caratteri come NUOVO valore; una descrizione memorizzata più lunga può essere restituita invariata.
started_onData di inizio, YYYY-MM-DD. null mantiene il valore attuale (una data di inizio non può essere cancellata).
litigiousSe la pratica è contenziosa.
responsible_user_idNuovo avvocato responsabile: l'id utente di un collega attivo da colleagues.list. Viene notificato quando non è Lei. Inviare quello attuale, o null / 0, come viene restituita una pratica senza responsabile, non cambia nulla.
Risposte
200
Aggiornato.
dataobbligatorioCampi di data
idId della pratica. Lo usi come matter_id altrove.
1234case_numberNumero di fascicolo come visualizzato in Flowyer, nello schema di numerazione dello studio.
"2026/0025"subject"Kovács Kft. v. Nagy Bt. - contract dispute"status"active" "archived" case_type_idcase_typeNome localizzato del tipo di pratica.
responsible_user_idresponsibleNome visualizzato dell'avvocato responsabile.
clientsClienti (mandanti) della pratica.
Campi di clients
idnamestarted_onrestrictedTrue quando solo gli avvocati responsabili possono visualizzare la pratica (muro cinese).
created_atupdated_atcreated_via_apiPresente quando un agente esterno ha creato il record tramite questa API.
Campi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduseratdescriptionlitigiousarchived_atGiorno in cui la pratica è stata archiviata, YYYY-MM-DD. Flowyer registra solo la data, non l'ora del giorno.
updatedtrue
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
409
Il record è cambiato da quando lo ha letto (record_conflict: expected_updated_at non corrisponde più; lo rilegga e riprovi con il nuovo updated_at).
record_conflict: expected_updated_at non corrisponde più; lo rilegga e riprovi con il nuovo updated_at).
413
Il corpo della richiesta è troppo grande (request_too_large).
request_too_large).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl -X PATCH 'https://www.flowyer.it/api/agent/matters/1234' \
-H 'Authorization: Bearer flw_...' \
-H 'Content-Type: application/json' \
-d '{
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"subject": "string"
}'
const response = await fetch("https://www.flowyer.it/api/agent/matters/1234", {
method: "PATCH",
headers: {
"Authorization": "Bearer flw_...",
"Content-Type": "application/json",
},
body: JSON.stringify({
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"subject": "string"
}),
});
const result = await response.json();
import requests
response = requests.patch(
"https://www.flowyer.it/api/agent/matters/1234",
headers={
"Authorization": "Bearer flw_...",
},
json={
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"subject": "string",
},
timeout=30,
)
print(response.status_code, response.json())
{
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"subject": "string"
}
Esempi di risposta
{
"data": {
"id": 1234,
"case_number": "2026/0025",
"subject": "Kovács Kft. v. Nagy Bt. - contract dispute",
"status": "active",
"case_type_id": 1234,
"case_type": "string",
"responsible_user_id": 1234,
"responsible": "string",
"clients": [
{
"id": 1234,
"name": "string"
}
],
"started_on": "2026-10-30",
"restricted": true,
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
},
"description": "string",
"litigious": true,
"archived_at": "2026-10-30"
},
"updated": true
}
{
"error": "record_conflict",
"message": "The record changed since you read it (someone edited it). Read it again and retry with the new updated_at.",
"message_localized": "Il record è cambiato dall'ultima lettura (qualcuno lo ha modificato). Rileggerlo e riprovare con il nuovo updated_at.",
"locale": "it",
"details": {
"current_updated_at": "2026-10-30T10:42:05+01:00",
"reason": "modified_since_read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Elenca i responsabili della pratica
/api/agent/matters/{id}/responsibles
Elenca i responsabili AGGIUNTIVI di una pratica (il responsabile principale è in matters.get): ciascuno è un collega (type "user", user_id impostato) o un gruppo di lavoro (type "workgroup", workgroup_id impostato), tutti in grado di vedere la pratica. Risponde 404 quando la pratica non è visibile.
Parametri di percorso
idobbligatorioId della pratica.
1234Parametri di query
limitDimensione della pagina, 1-100. Valore predefinito 25.
2525offsetNumero di record da saltare. Usi offset + limit della pagina precedente per ottenere quella successiva; pagination.total è il conteggio totale.
00Risposte
200
OK.
dataobbligatorioCampi di data
type"user" = un singolo collega; "workgroup" = ogni membro di un gruppo di lavoro.
"user" "workgroup" user_idId utente del collega per una voce "user" (lo passi come user_id a matters.responsibles.add); null per un gruppo di lavoro.
workgroup_idId del gruppo di lavoro per una voce "workgroup"; null per un singolo collega. I responsabili dei gruppi di lavoro sono gestiti in Flowyer.
nameNome visualizzato del collega o del gruppo di lavoro.
paginationobbligatorioCampi di pagination
limitobbligatoriooffsetobbligatoriototalobbligatorioNumero totale di record corrispondenti.
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl 'https://www.flowyer.it/api/agent/matters/1234/responsibles?limit=25' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.it/api/agent/matters/1234/responsibles?limit=25", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.it/api/agent/matters/1234/responsibles?limit=25",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Esempi di risposta
{
"data": [
{
"type": "user",
"user_id": 1234,
"workgroup_id": 1234,
"name": "string"
}
],
"pagination": {
"limit": 25,
"offset": 0,
"total": 1
}
}
{
"error": "matter_not_visible",
"message": "The matter 1234 does not exist, is archived, or is not visible to the user who owns this API key.",
"message_localized": "La pratica 1234 non esiste, è archiviata oppure non è visibile al titolare di questa chiave API.",
"locale": "it",
"details": {
"matter_id": 1234
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Aggiungi un responsabile della pratica
/api/agent/matters/{id}/responsibles
Aggiunge un collega (user_id da colleagues.list) come responsabile aggiuntivo di una pratica. Questo CONCEDE a quel collega l'accesso alla pratica, quindi aggiunga solo qualcuno che dovrebbe vederla; viene notificato. Idempotente: riaggiungere un responsabile esistente non comporta alcuna modifica.
Parametri di percorso
idobbligatorioPratica di cui il collega diventa responsabile (deve essere visibile).
1234Corpo della richiesta application/json
user_idobbligatorioCollega da aggiungere: un id utente da colleagues.list. Aggiungerlo gli concede l'accesso alla pratica.
42Risposte
200
OK.
dataobbligatorioCampi di data
user_idIl collega ora responsabile della pratica.
nameNome visualizzato del collega.
already_responsibleTrue quando il collega era già un responsabile della pratica (nulla è cambiato).
notifiedTrue quando il collega è stato notificato di essere stato aggiunto. Mai true quando il collega è Lei, o quando era già responsabile.
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
413
Il corpo della richiesta è troppo grande (request_too_large).
request_too_large).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl -X POST 'https://www.flowyer.it/api/agent/matters/1234/responsibles' \
-H 'Authorization: Bearer flw_...' \
-H 'Content-Type: application/json' \
-d '{
"user_id": 42
}'
const response = await fetch("https://www.flowyer.it/api/agent/matters/1234/responsibles", {
method: "POST",
headers: {
"Authorization": "Bearer flw_...",
"Content-Type": "application/json",
},
body: JSON.stringify({
"user_id": 42
}),
});
const result = await response.json();
import requests
response = requests.post(
"https://www.flowyer.it/api/agent/matters/1234/responsibles",
headers={
"Authorization": "Bearer flw_...",
},
json={
"user_id": 42,
},
timeout=30,
)
print(response.status_code, response.json())
{
"user_id": 42
}
Esempi di risposta
{
"data": {
"user_id": 1234,
"name": "string",
"already_responsible": true,
"notified": true
}
}
{
"error": "validation_failed",
"message": "The request is invalid. See \"details.fields\" for the field-level errors.",
"message_localized": "La richiesta non è valida. Gli errori per campo sono in \"details.fields\".",
"locale": "it",
"details": {
"fields": {
"user_id": [
"Il campo user id è obbligatorio."
]
}
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Clienti
Elenca i clienti
/api/agent/clients
Elenca i clienti dello studio (persone e aziende), in ordine alfabetico; q effettua la ricerca nel nome (accenti e maiuscole/minuscole ignorati), nell'e-mail e nel codice fiscale. Prima di creare un cliente, verifichi il nome con clients.resolve (tollera anche gli errori di battitura). I clienti archiviati sono nascosti a meno che include_archived non sia true.
Parametri di query
qRicerca nel nome (accenti e maiuscole/minuscole ignorati), nell'e-mail e nel codice fiscale.
"Kovács"is_persontrue = solo persone fisiche, false = solo aziende.
include_archivedfalselimitDimensione della pagina, 1-100. Valore predefinito 25.
2525offsetNumero di record da saltare. Usi offset + limit della pagina precedente per ottenere quella successiva; pagination.total è il conteggio totale.
00Risposte
200
OK.
dataobbligatorioCampi di data
idId del cliente. Lo usi come client_id altrove.
512name"Kovács Kft."is_personTrue per una persona fisica, false per un'azienda.
emailphonearchivedrecorded_by_user_idrecorded_bycreated_atupdated_atcreated_via_apiCampi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduseratpaginationobbligatorioCampi di pagination
limitobbligatoriooffsetobbligatoriototalobbligatorioNumero totale di record corrispondenti.
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl 'https://www.flowyer.it/api/agent/clients?q=Kov%C3%A1cs&limit=25' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.it/api/agent/clients?q=Kov%C3%A1cs&limit=25", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.it/api/agent/clients?q=Kov%C3%A1cs&limit=25",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Esempi di risposta
{
"data": [
{
"id": 512,
"name": "Kovács Kft.",
"is_person": true,
"email": "info@example.hu",
"phone": "string",
"archived": true,
"recorded_by_user_id": 1234,
"recorded_by": "string",
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
}
}
],
"pagination": {
"limit": 25,
"offset": 0,
"total": 1
}
}
{
"error": "scope_missing",
"message": "This API key does not have the \"clients:read\" permission. The permissions of an existing key cannot be changed, so the key owner needs to create a new key with this permission in Flowyer under Settings > API keys and use it in place of the old one.",
"message_localized": "Questa chiave API non ha il permesso \"clients:read\". I permessi di una chiave esistente non possono essere modificati, quindi il titolare della chiave deve creare in Flowyer, in Impostazioni > Chiavi API, una nuova chiave con questo permesso e usarla al posto di quella vecchia.",
"locale": "it",
"details": {
"required_scope": "clients:read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Risolvi il cliente per nome
/api/agent/clients/resolve
Trova un cliente a partire da un nome pronunciato o scritto in modo errato (accenti, maiuscole/minuscole e piccoli errori di battitura tollerati). Restituisce lo stato exact/similar/none e i clienti candidati. Solo "exact" è sicuro da usare direttamente; con "similar" o "none" chieda all'utente. Un nome con molti simili non è mai "exact": chieda un nome più completo.
Parametri di query
nameobbligatorioNome del cliente da cercare, così come ascoltato o dettato.
"Józsi ingatlan"limitNumero massimo di candidati da restituire (valore predefinito 5).
5Risposte
200
OK.
dataobbligatorioCampi di data
statusexact = una corrispondenza certa (sicuro usarne l'id). similar = una o più corrispondenze approssimative, confermi prima con l'utente. none = nessuna corrispondenza, chieda all'utente.
"exact" "similar" "none" matchesClienti candidati, prima la corrispondenza migliore.
Campi di matches
idId del cliente. Lo usi come client_id altrove.
512name"Kovács Kft."is_personTrue per una persona fisica, false per un'azienda.
emailphonearchivedrecorded_by_user_idrecorded_bycreated_atupdated_atcreated_via_apiCampi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduserattotalQuanti clienti hanno corrisposto prima che l'elenco fosse ridotto a limit.
truncatedTrue quando hanno corrisposto più clienti di quanti ne siano stati restituiti, oppure esistevano troppi nomi simili per verificarli tutti; chieda all'utente un nome più completo o aumenti limit anziché scegliere da un elenco incompleto.
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl 'https://www.flowyer.it/api/agent/clients/resolve?name=J%C3%B3zsi%20ingatlan' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.it/api/agent/clients/resolve?name=J%C3%B3zsi%20ingatlan", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.it/api/agent/clients/resolve?name=J%C3%B3zsi%20ingatlan",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Esempi di risposta
{
"data": {
"status": "exact",
"matches": [
{
"id": 512,
"name": "Kovács Kft.",
"is_person": true,
"email": "info@example.hu",
"phone": "string",
"archived": true,
"recorded_by_user_id": 1234,
"recorded_by": "string",
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
}
}
],
"total": 1,
"truncated": true
}
}
{
"error": "scope_missing",
"message": "This API key does not have the \"clients:read\" permission. The permissions of an existing key cannot be changed, so the key owner needs to create a new key with this permission in Flowyer under Settings > API keys and use it in place of the old one.",
"message_localized": "Questa chiave API non ha il permesso \"clients:read\". I permessi di una chiave esistente non possono essere modificati, quindi il titolare della chiave deve creare in Flowyer, in Impostazioni > Chiavi API, una nuova chiave con questo permesso e usarla al posto di quella vecchia.",
"locale": "it",
"details": {
"required_scope": "clients:read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Ottieni il cliente
/api/agent/clients/{id}
Restituisce un cliente con l'indirizzo e i dati di registrazione. I numeri dei documenti d'identità e le impostazioni delle tariffe non vengono mai restituiti.
Parametri di percorso
idobbligatorioId del cliente.
512Risposte
200
OK.
dataobbligatorioCampi di data
idId del cliente. Lo usi come client_id altrove.
512name"Kovács Kft."is_personTrue per una persona fisica, false per un'azienda.
emailphonearchivedrecorded_by_user_idrecorded_bycreated_atupdated_atcreated_via_apiCampi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduserataddressCampi di address
zipcitystreetmailing_addressCampi di mailing_address
zipcitystreettax_numberSolo aziende; null per una persona fisica.
company_registration_numberSolo aziende; null per una persona fisica.
representative_nameSolo aziende; null per una persona fisica.
representative_positionSolo aziende; null per una persona fisica.
main_activityAttività principale. Solo aziende; null per una persona fisica.
nationality_countrynote
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl 'https://www.flowyer.it/api/agent/clients/512' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.it/api/agent/clients/512", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.it/api/agent/clients/512",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Esempi di risposta
{
"data": {
"id": 512,
"name": "Kovács Kft.",
"is_person": true,
"email": "info@example.hu",
"phone": "string",
"archived": true,
"recorded_by_user_id": 1234,
"recorded_by": "string",
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
},
"address": {
"zip": "string",
"city": "string",
"street": "string"
},
"mailing_address": {
"zip": "string",
"city": "string",
"street": "string"
},
"tax_number": "string",
"company_registration_number": "string",
"representative_name": "string",
"representative_position": "string",
"main_activity": "string",
"nationality_country": "string",
"note": "string"
}
}
{
"error": "not_found",
"message": "The record was not found, or it is not visible to the user who owns this API key.",
"message_localized": "Il record non è stato trovato oppure non è visibile al titolare di questa chiave API.",
"locale": "it",
"details": {
"client_id": 512
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Crea un cliente
/api/agent/clients
Crea un cliente (persona o azienda), registrato come creato dall'utente della chiave. Verifichi prima il nome con clients.resolve (tollera accenti mancanti ed errori di battitura): un 409 rileva solo un cliente attivo con lo stesso identico nome, a meno che allow_duplicate_name non sia true. I numeri di documento e le tariffe non possono essere impostati.
Parametri di intestazione
Idempotency-KeyConsigliato a ogni creazione. Un valore univoco per operazione logica (ad es. un UUID). Lo stesso valore restituisce lo stesso record: riprovare con esso restituisce il record creato la prima volta invece di crearne un secondo. Valori diversi creano sempre record diversi. I client che non possono inviare header possono passare lo stesso valore nel campo del corpo idempotency_key. Lettere, cifre, _, -, : o ., al massimo 128 caratteri.
^[A-Za-z0-9_\-:.]{1,128}$Corpo della richiesta application/json
nameobbligatorioNome completo della persona o ragione sociale dell'azienda. Testo semplice; "<" e ">" non sono consentiti.
^[^<>]*$"Kovács Kft."is_persontrue per una persona fisica, false (predefinito) per un'azienda.
falseemail"info@kovacskft.hu"phone"+36 1 234 5678"addressIndirizzo della sede legale / di residenza.
Campi di address
zipcitystreetmailing_addressCampi di mailing_address
zipcitystreettax_numberCodice fiscale dell'azienda (solo aziende).
"12345678-2-41"company_registration_numberNumero di registrazione dell'azienda (solo aziende).
"01-09-123456"representative_nameSolo aziende.
representative_positionSolo aziende.
main_activityAttività principale (solo aziende).
nationality_countrynoteallow_duplicate_nameCrea anche se esiste un cliente attivo con lo stesso nome.
falseidempotency_keyStesso ruolo dell'header Idempotency-Key, per i client che non possono inviare header personalizzati. Lettere, cifre, _, -, : o ., al massimo 128 caratteri.
^[A-Za-z0-9_\-:.]{1,128}$"b8f1c2e0-6f7a-4d2e-9c1b-2a3d4e5f6a7b"Risposte
201
Creato.
dataobbligatorioCampi di data
idId del cliente. Lo usi come client_id altrove.
512name"Kovács Kft."is_personTrue per una persona fisica, false per un'azienda.
emailphonearchivedrecorded_by_user_idrecorded_bycreated_atupdated_atcreated_via_apiCampi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduserataddressCampi di address
zipcitystreetmailing_addressCampi di mailing_address
zipcitystreettax_numberSolo aziende; null per una persona fisica.
company_registration_numberSolo aziende; null per una persona fisica.
representative_nameSolo aziende; null per una persona fisica.
representative_positionSolo aziende; null per una persona fisica.
main_activityAttività principale. Solo aziende; null per una persona fisica.
nationality_countrynotecreatedtrue
200
Replay idempotente: questo Idempotency-Key (o, senza chiave, una richiesta identica entro 120 secondi) ha già creato il record; viene restituito di nuovo, nulla di nuovo è stato creato.
dataobbligatorioCampi di data
idId del cliente. Lo usi come client_id altrove.
512name"Kovács Kft."is_personTrue per una persona fisica, false per un'azienda.
emailphonearchivedrecorded_by_user_idrecorded_bycreated_atupdated_atcreated_via_apiCampi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduserataddressCampi di address
zipcitystreetmailing_addressCampi di mailing_address
zipcitystreettax_numberSolo aziende; null per una persona fisica.
company_registration_numberSolo aziende; null per una persona fisica.
representative_nameSolo aziende; null per una persona fisica.
representative_positionSolo aziende; null per una persona fisica.
main_activityAttività principale. Solo aziende; null per una persona fisica.
nationality_countrynotecreatedfalseidempotent_replaytrue
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente. replay_not_visible: questo Idempotency-Key (o, senza chiave, una richiesta identica) ha già creato il record (details.record_id), ma da allora è stato eliminato o non è visibile all'utente; nulla di nuovo è stato creato, non lo ricrei.
replay_not_visible: questo Idempotency-Key (o, senza chiave, una richiesta identica) ha già creato il record (details.record_id), ma da allora è stato eliminato o non è visibile all'utente; nulla di nuovo è stato creato, non lo ricrei.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
409
Esiste un cliente attivo con lo stesso nome (client_exists, oppure client_exists_generic senza lo scope clients:read, quando il cliente esistente non può essere nominato; passi allow_duplicate_name per forzare), la Idempotency-Key è stata usata per un altro tipo di risorsa (idempotency_key_reused), oppure, senza una chiave, una richiesta identica è in elaborazione (duplicate_in_progress).
client_exists, oppure client_exists_generic senza lo scope clients:read, quando il cliente esistente non può essere nominato; passi allow_duplicate_name per forzare), la Idempotency-Key è stata usata per un altro tipo di risorsa (idempotency_key_reused), oppure, senza una chiave, una richiesta identica è in elaborazione (duplicate_in_progress).
413
Il corpo della richiesta è troppo grande (request_too_large).
request_too_large).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl -X POST 'https://www.flowyer.it/api/agent/clients' \
-H 'Authorization: Bearer flw_...' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: 7f3a9c21-1b2c-4d5e-8f90-0a1b2c3d4e5f' \
-d '{
"name": "Kovács Kft.",
"email": "info@kovacskft.hu",
"phone": "+36 1 234 5678",
"tax_number": "12345678-2-41",
"company_registration_number": "01-09-123456"
}'
const response = await fetch("https://www.flowyer.it/api/agent/clients", {
method: "POST",
headers: {
"Authorization": "Bearer flw_...",
"Content-Type": "application/json",
"Idempotency-Key": crypto.randomUUID(),
},
body: JSON.stringify({
"name": "Kovács Kft.",
"email": "info@kovacskft.hu",
"phone": "+36 1 234 5678",
"tax_number": "12345678-2-41",
"company_registration_number": "01-09-123456"
}),
});
const result = await response.json();
import uuid
import requests
response = requests.post(
"https://www.flowyer.it/api/agent/clients",
headers={
"Authorization": "Bearer flw_...",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"name": "Kovács Kft.",
"email": "info@kovacskft.hu",
"phone": "+36 1 234 5678",
"tax_number": "12345678-2-41",
"company_registration_number": "01-09-123456",
},
timeout=30,
)
print(response.status_code, response.json())
{
"name": "Kovács Kft.",
"email": "info@kovacskft.hu",
"phone": "+36 1 234 5678",
"tax_number": "12345678-2-41",
"company_registration_number": "01-09-123456"
}
Esempi di risposta
{
"data": {
"id": 512,
"name": "Kovács Kft.",
"is_person": true,
"email": "info@example.hu",
"phone": "string",
"archived": true,
"recorded_by_user_id": 1234,
"recorded_by": "string",
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
},
"address": {
"zip": "string",
"city": "string",
"street": "string"
},
"mailing_address": {
"zip": "string",
"city": "string",
"street": "string"
},
"tax_number": "string",
"company_registration_number": "string",
"representative_name": "string",
"representative_position": "string",
"main_activity": "string",
"nationality_country": "string",
"note": "string"
},
"created": true
}
{
"data": {
"id": 512,
"name": "Kovács Kft.",
"is_person": true,
"email": "info@example.hu",
"phone": "string",
"archived": true,
"recorded_by_user_id": 1234,
"recorded_by": "string",
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
},
"address": {
"zip": "string",
"city": "string",
"street": "string"
},
"mailing_address": {
"zip": "string",
"city": "string",
"street": "string"
},
"tax_number": "string",
"company_registration_number": "string",
"representative_name": "string",
"representative_position": "string",
"main_activity": "string",
"nationality_country": "string",
"note": "string"
},
"created": false,
"idempotent_replay": true
}
{
"error": "validation_failed",
"message": "The request is invalid. See \"details.fields\" for the field-level errors.",
"message_localized": "La richiesta non è valida. Gli errori per campo sono in \"details.fields\".",
"locale": "it",
"details": {
"fields": {
"name": [
"Il campo name è obbligatorio."
]
}
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Aggiorna il cliente
/api/agent/clients/{id}
Modifica i campi di contatto di un cliente (nome, email, telefono, indirizzo, nota, nazionalità e rappresentante/attività dell'azienda). I numeri di documento, i codici fiscali, le tariffe e il tipo persona/azienda non sono modificabili qui. Passi expected_updated_at; una modifica in conflitto risponde con 409.
Parametri di percorso
idobbligatorioId del record da modificare.
Corpo della richiesta application/json
expected_updated_atIl valore updated_at dalla sua lettura più recente di questo record (obbligatorio ogni volta che il record ne ha uno). Se il record è cambiato da allora (un collega lo ha modificato), l'API risponde 409 e deve rileggere prima di riprovare. Un record legacy il cui updated_at è null accetta null.
nameNome completo o ragione sociale. Testo semplice, al massimo 255 caratteri come NUOVO valore; non è possibile introdurre nemmeno "<" e ">", ma un nome memorizzato più lungo o che li contiene può essere restituito invariato. null mantiene il nome corrente.
emailphoneaddressIndirizzo della sede legale / di residenza.
Campi di address
zipcitystreetmailing_addressCampi di mailing_address
zipcitystreetrepresentative_nameSolo aziende.
representative_positionSolo aziende.
main_activityAttività principale (solo aziende).
nationality_countrynoteNota a testo libero, al massimo 4000 caratteri come NUOVO valore; una nota memorizzata più lunga può essere restituita invariata. null cancella la nota.
Risposte
200
Aggiornato.
dataobbligatorioCampi di data
idId del cliente. Lo usi come client_id altrove.
512name"Kovács Kft."is_personTrue per una persona fisica, false per un'azienda.
emailphonearchivedrecorded_by_user_idrecorded_bycreated_atupdated_atcreated_via_apiCampi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduserataddressCampi di address
zipcitystreetmailing_addressCampi di mailing_address
zipcitystreettax_numberSolo aziende; null per una persona fisica.
company_registration_numberSolo aziende; null per una persona fisica.
representative_nameSolo aziende; null per una persona fisica.
representative_positionSolo aziende; null per una persona fisica.
main_activityAttività principale. Solo aziende; null per una persona fisica.
nationality_countrynoteupdatedtrue
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
409
Il record è cambiato da quando lo ha letto (record_conflict: expected_updated_at non corrisponde più; lo rilegga e riprovi con il nuovo updated_at).
record_conflict: expected_updated_at non corrisponde più; lo rilegga e riprovi con il nuovo updated_at).
413
Il corpo della richiesta è troppo grande (request_too_large).
request_too_large).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl -X PATCH 'https://www.flowyer.it/api/agent/clients/1234' \
-H 'Authorization: Bearer flw_...' \
-H 'Content-Type: application/json' \
-d '{
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"name": "string"
}'
const response = await fetch("https://www.flowyer.it/api/agent/clients/1234", {
method: "PATCH",
headers: {
"Authorization": "Bearer flw_...",
"Content-Type": "application/json",
},
body: JSON.stringify({
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"name": "string"
}),
});
const result = await response.json();
import requests
response = requests.patch(
"https://www.flowyer.it/api/agent/clients/1234",
headers={
"Authorization": "Bearer flw_...",
},
json={
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"name": "string",
},
timeout=30,
)
print(response.status_code, response.json())
{
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"name": "string"
}
Esempi di risposta
{
"data": {
"id": 512,
"name": "Kovács Kft.",
"is_person": true,
"email": "info@example.hu",
"phone": "string",
"archived": true,
"recorded_by_user_id": 1234,
"recorded_by": "string",
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
},
"address": {
"zip": "string",
"city": "string",
"street": "string"
},
"mailing_address": {
"zip": "string",
"city": "string",
"street": "string"
},
"tax_number": "string",
"company_registration_number": "string",
"representative_name": "string",
"representative_position": "string",
"main_activity": "string",
"nationality_country": "string",
"note": "string"
},
"updated": true
}
{
"error": "record_conflict",
"message": "The record changed since you read it (someone edited it). Read it again and retry with the new updated_at.",
"message_localized": "Il record è cambiato dall'ultima lettura (qualcuno lo ha modificato). Rileggerlo e riprovare con il nuovo updated_at.",
"locale": "it",
"details": {
"current_updated_at": "2026-10-30T10:42:05+01:00",
"reason": "modified_since_read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Attività
Elenca le attività
/api/agent/tasks
Elenca le attività (cose da fare con una scadenza) che l'utente può vedere, prima la scadenza più imminente. Attività aperte per impostazione predefinita; filtri per assegnatario, pratica, cliente o intervallo di scadenze.
Parametri di query
statusopen (predefinito), closed o all.
"open" "closed" "all" "open"assigned_to_user_idSolo le attività assegnate a questo utente (un id utente da colleagues.list).
matter_idSolo le attività di questa pratica.
client_idSolo le attività senza pratica di questo cliente.
deadline_fromScadenza a partire da questa data inclusa.
"2026-11-01"deadline_toScadenza fino a questa data inclusa.
"2026-11-30"limitDimensione della pagina, 1-100. Valore predefinito 25.
2525offsetNumero di record da saltare. Usi offset + limit della pagina precedente per ottenere quella successiva; pagination.total è il conteggio totale.
00Risposte
200
OK.
dataobbligatorioCampi di data
id9876subject"Submit the statement of defence"descriptiondeadlineData di scadenza, YYYY-MM-DD.
"2026-11-15"priority1 = bassa, 2 = media, 3 = alta; null = non impostata (un'attività più vecchia senza priorità).
2status"open" "closed" closed_atGiorno in cui l'attività è stata chiusa, YYYY-MM-DD. Flowyer registra solo la data, non l'ora del giorno.
matterLa pratica a cui appartiene l'attività, se presente.
Campi di matter
idcase_numberclientIl cliente: il primo cliente della pratica, oppure il cliente proprio dell'attività quando non ha una pratica.
Campi di client
idnameassigned_to_user_idassigned_tocreated_by_user_idcreated_byflag_idcreated_atupdated_atcreated_via_apiCampi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduseratpaginationobbligatorioCampi di pagination
limitobbligatoriooffsetobbligatoriototalobbligatorioNumero totale di record corrispondenti.
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl 'https://www.flowyer.it/api/agent/tasks?deadline_from=2026-11-01&deadline_to=2026-11-30&limit=25' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.it/api/agent/tasks?deadline_from=2026-11-01&deadline_to=2026-11-30&limit=25", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.it/api/agent/tasks?deadline_from=2026-11-01&deadline_to=2026-11-30&limit=25",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Esempi di risposta
{
"data": [
{
"id": 9876,
"subject": "Submit the statement of defence",
"description": "string",
"deadline": "2026-11-15",
"priority": 2,
"status": "open",
"closed_at": "2026-10-30",
"matter": {
"id": 1234,
"case_number": "string"
},
"client": {
"id": 1234,
"name": "string"
},
"assigned_to_user_id": 1234,
"assigned_to": "string",
"created_by_user_id": 1234,
"created_by": "string",
"flag_id": 1234,
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
}
}
],
"pagination": {
"limit": 25,
"offset": 0,
"total": 1
}
}
{
"error": "scope_missing",
"message": "This API key does not have the \"tasks:read\" permission. The permissions of an existing key cannot be changed, so the key owner needs to create a new key with this permission in Flowyer under Settings > API keys and use it in place of the old one.",
"message_localized": "Questa chiave API non ha il permesso \"tasks:read\". I permessi di una chiave esistente non possono essere modificati, quindi il titolare della chiave deve creare in Flowyer, in Impostazioni > Chiavi API, una nuova chiave con questo permesso e usarla al posto di quella vecchia.",
"locale": "it",
"details": {
"required_scope": "tasks:read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Ottieni l'attività
/api/agent/tasks/{id}
Restituisce un'attività. Risponde con 404 quando l'attività non esiste o l'utente non può vederla.
Parametri di percorso
idobbligatorioId dell'attività.
9876Risposte
200
OK.
dataobbligatorioCampi di data
id9876subject"Submit the statement of defence"descriptiondeadlineData di scadenza, YYYY-MM-DD.
"2026-11-15"priority1 = bassa, 2 = media, 3 = alta; null = non impostata (un'attività più vecchia senza priorità).
2status"open" "closed" closed_atGiorno in cui l'attività è stata chiusa, YYYY-MM-DD. Flowyer registra solo la data, non l'ora del giorno.
matterLa pratica a cui appartiene l'attività, se presente.
Campi di matter
idcase_numberclientIl cliente: il primo cliente della pratica, oppure il cliente proprio dell'attività quando non ha una pratica.
Campi di client
idnameassigned_to_user_idassigned_tocreated_by_user_idcreated_byflag_idcreated_atupdated_atcreated_via_apiCampi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduserat
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl 'https://www.flowyer.it/api/agent/tasks/9876' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.it/api/agent/tasks/9876", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.it/api/agent/tasks/9876",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Esempi di risposta
{
"data": {
"id": 9876,
"subject": "Submit the statement of defence",
"description": "string",
"deadline": "2026-11-15",
"priority": 2,
"status": "open",
"closed_at": "2026-10-30",
"matter": {
"id": 1234,
"case_number": "string"
},
"client": {
"id": 1234,
"name": "string"
},
"assigned_to_user_id": 1234,
"assigned_to": "string",
"created_by_user_id": 1234,
"created_by": "string",
"flag_id": 1234,
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
}
}
}
{
"error": "not_found",
"message": "The record was not found, or it is not visible to the user who owns this API key.",
"message_localized": "Il record non è stato trovato oppure non è visibile al titolare di questa chiave API.",
"locale": "it",
"details": {
"task_id": 9876
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Crea un'attività
/api/agent/tasks
Crea un'attività (cosa da fare con una scadenza), su una pratica (matter_id, visibile e non archiviata) oppure senza pratica, facoltativamente per un cliente (client_id). L'assegnatario è per impostazione predefinita l'utente della chiave e viene notificato quando si tratta di qualcun altro.
Parametri di intestazione
Idempotency-KeyConsigliato a ogni creazione. Un valore univoco per operazione logica (ad es. un UUID). Lo stesso valore restituisce lo stesso record: riprovare con esso restituisce il record creato la prima volta invece di crearne un secondo. Valori diversi creano sempre record diversi. I client che non possono inviare header possono passare lo stesso valore nel campo del corpo idempotency_key. Lettere, cifre, _, -, : o ., al massimo 128 caratteri.
^[A-Za-z0-9_\-:.]{1,128}$Corpo della richiesta application/json
subjectobbligatorioCosa deve essere fatto. Testo semplice.
"Submit the statement of defence"deadlineobbligatorioData di scadenza, YYYY-MM-DD.
"2026-11-15"matter_idPratica a cui appartiene l'attività. La ometta per un'attività senza pratica.
1234client_idCliente di un'attività senza pratica. Non consentito insieme a matter_id (un'attività di una pratica assume il cliente della pratica).
assigned_to_user_idCollega responsabile dell'attività: un id utente da colleagues.list (cerchi lì un nome dettato). Predefinito: l'utente della chiave.
priority1 = bassa, 2 = media (predefinito), 3 = alta.
2descriptionDettagli più estesi, testo semplice.
flag_idId di un flag di attività dello studio (etichetta).
idempotency_keyStesso ruolo dell'header Idempotency-Key, per i client che non possono inviare header personalizzati. Lettere, cifre, _, -, : o ., al massimo 128 caratteri.
^[A-Za-z0-9_\-:.]{1,128}$"b8f1c2e0-6f7a-4d2e-9c1b-2a3d4e5f6a7b"Risposte
201
Creato.
dataobbligatorioCampi di data
id9876subject"Submit the statement of defence"descriptiondeadlineData di scadenza, YYYY-MM-DD.
"2026-11-15"priority1 = bassa, 2 = media, 3 = alta; null = non impostata (un'attività più vecchia senza priorità).
2status"open" "closed" closed_atGiorno in cui l'attività è stata chiusa, YYYY-MM-DD. Flowyer registra solo la data, non l'ora del giorno.
matterLa pratica a cui appartiene l'attività, se presente.
Campi di matter
idcase_numberclientIl cliente: il primo cliente della pratica, oppure il cliente proprio dell'attività quando non ha una pratica.
Campi di client
idnameassigned_to_user_idassigned_tocreated_by_user_idcreated_byflag_idcreated_atupdated_atcreated_via_apiCampi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduseratcreatedtrue
200
Replay idempotente: questo Idempotency-Key (o, senza chiave, una richiesta identica entro 120 secondi) ha già creato il record; viene restituito di nuovo, nulla di nuovo è stato creato.
dataobbligatorioCampi di data
id9876subject"Submit the statement of defence"descriptiondeadlineData di scadenza, YYYY-MM-DD.
"2026-11-15"priority1 = bassa, 2 = media, 3 = alta; null = non impostata (un'attività più vecchia senza priorità).
2status"open" "closed" closed_atGiorno in cui l'attività è stata chiusa, YYYY-MM-DD. Flowyer registra solo la data, non l'ora del giorno.
matterLa pratica a cui appartiene l'attività, se presente.
Campi di matter
idcase_numberclientIl cliente: il primo cliente della pratica, oppure il cliente proprio dell'attività quando non ha una pratica.
Campi di client
idnameassigned_to_user_idassigned_tocreated_by_user_idcreated_byflag_idcreated_atupdated_atcreated_via_apiCampi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduseratcreatedfalseidempotent_replaytrue
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente. replay_not_visible: questo Idempotency-Key (o, senza chiave, una richiesta identica) ha già creato il record (details.record_id), ma da allora è stato eliminato o non è visibile all'utente; nulla di nuovo è stato creato, non lo ricrei.
replay_not_visible: questo Idempotency-Key (o, senza chiave, una richiesta identica) ha già creato il record (details.record_id), ma da allora è stato eliminato o non è visibile all'utente; nulla di nuovo è stato creato, non lo ricrei.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
409
L'Idempotency-Key è stato usato per un altro tipo di risorsa (idempotency_key_reused), oppure, senza chiave, una richiesta identica è in fase di elaborazione in questo momento (duplicate_in_progress; riprovi a breve).
idempotency_key_reused), oppure, senza chiave, una richiesta identica è in fase di elaborazione in questo momento (duplicate_in_progress; riprovi a breve).
413
Il corpo della richiesta è troppo grande (request_too_large).
request_too_large).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl -X POST 'https://www.flowyer.it/api/agent/tasks' \
-H 'Authorization: Bearer flw_...' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: 7f3a9c21-1b2c-4d5e-8f90-0a1b2c3d4e5f' \
-d '{
"subject": "Submit the statement of defence",
"deadline": "2026-11-15",
"matter_id": 1234
}'
const response = await fetch("https://www.flowyer.it/api/agent/tasks", {
method: "POST",
headers: {
"Authorization": "Bearer flw_...",
"Content-Type": "application/json",
"Idempotency-Key": crypto.randomUUID(),
},
body: JSON.stringify({
"subject": "Submit the statement of defence",
"deadline": "2026-11-15",
"matter_id": 1234
}),
});
const result = await response.json();
import uuid
import requests
response = requests.post(
"https://www.flowyer.it/api/agent/tasks",
headers={
"Authorization": "Bearer flw_...",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"subject": "Submit the statement of defence",
"deadline": "2026-11-15",
"matter_id": 1234,
},
timeout=30,
)
print(response.status_code, response.json())
{
"subject": "Submit the statement of defence",
"deadline": "2026-11-15",
"matter_id": 1234
}
Esempi di risposta
{
"data": {
"id": 9876,
"subject": "Submit the statement of defence",
"description": "string",
"deadline": "2026-11-15",
"priority": 2,
"status": "open",
"closed_at": "2026-10-30",
"matter": {
"id": 1234,
"case_number": "string"
},
"client": {
"id": 1234,
"name": "string"
},
"assigned_to_user_id": 1234,
"assigned_to": "string",
"created_by_user_id": 1234,
"created_by": "string",
"flag_id": 1234,
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
}
},
"created": true
}
{
"data": {
"id": 9876,
"subject": "Submit the statement of defence",
"description": "string",
"deadline": "2026-11-15",
"priority": 2,
"status": "open",
"closed_at": "2026-10-30",
"matter": {
"id": 1234,
"case_number": "string"
},
"client": {
"id": 1234,
"name": "string"
},
"assigned_to_user_id": 1234,
"assigned_to": "string",
"created_by_user_id": 1234,
"created_by": "string",
"flag_id": 1234,
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
}
},
"created": false,
"idempotent_replay": true
}
{
"error": "validation_failed",
"message": "The request is invalid. See \"details.fields\" for the field-level errors.",
"message_localized": "La richiesta non è valida. Gli errori per campo sono in \"details.fields\".",
"locale": "it",
"details": {
"fields": {
"subject": [
"Il campo subject è obbligatorio."
]
}
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Aggiorna l'attività
/api/agent/tasks/{id}
Modifica un'attività: oggetto, scadenza, descrizione, priorità, flag, assegnatario o la pratica a cui appartiene. Spostarla su una pratica ricalcola il collegamento al tribunale e rimuove un cliente diretto; client_id è solo per un'attività senza pratica. Passi expected_updated_at; una modifica in conflitto risponde con 409.
Parametri di percorso
idobbligatorioId del record da modificare.
Corpo della richiesta application/json
expected_updated_atIl valore updated_at dalla sua lettura più recente di questo record (obbligatorio ogni volta che il record ne ha uno). Se il record è cambiato da allora (un collega lo ha modificato), l'API risponde 409 e deve rileggere prima di riprovare. Un record legacy il cui updated_at è null accetta null.
subjectCosa deve essere fatto. Testo semplice, al massimo 1000 caratteri come NUOVO valore; un oggetto memorizzato più lungo può essere restituito invariato. null mantiene l'oggetto corrente.
deadlineData di scadenza, YYYY-MM-DD. null mantiene la scadenza corrente (una scadenza non può essere cancellata).
matter_idSposta l'attività su questa pratica (deve essere visibile e non archiviata), oppure null per scollegarla. Inviare la pratica corrente dell'attività non cambia nulla.
client_idCliente di un'attività senza pratica. Consentito solo quando l'attività non ha una pratica.
assigned_to_user_idNuovo assegnatario: l'id utente di un collega attivo da colleagues.list. Viene notificato quando non è Lei. Inviare quello corrente, o null / 0 con cui viene restituita un'attività senza assegnatario, non cambia nulla.
priority1 = bassa, 2 = media, 3 = alta. La ometta per mantenere la priorità corrente (anche quando l'attività viene restituita con priorità null); null viene rifiutato.
descriptionDettagli più estesi, testo semplice, al massimo 10000 caratteri come NUOVO valore; una descrizione memorizzata più lunga può essere restituita invariata.
flag_idId di un flag di attività dello studio (etichetta), oppure null per cancellarlo.
Risposte
200
Aggiornato.
dataobbligatorioCampi di data
id9876subject"Submit the statement of defence"descriptiondeadlineData di scadenza, YYYY-MM-DD.
"2026-11-15"priority1 = bassa, 2 = media, 3 = alta; null = non impostata (un'attività più vecchia senza priorità).
2status"open" "closed" closed_atGiorno in cui l'attività è stata chiusa, YYYY-MM-DD. Flowyer registra solo la data, non l'ora del giorno.
matterLa pratica a cui appartiene l'attività, se presente.
Campi di matter
idcase_numberclientIl cliente: il primo cliente della pratica, oppure il cliente proprio dell'attività quando non ha una pratica.
Campi di client
idnameassigned_to_user_idassigned_tocreated_by_user_idcreated_byflag_idcreated_atupdated_atcreated_via_apiCampi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduseratupdatedtrue
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
409
Il record è cambiato da quando lo ha letto (record_conflict: expected_updated_at non corrisponde più; lo rilegga e riprovi con il nuovo updated_at).
record_conflict: expected_updated_at non corrisponde più; lo rilegga e riprovi con il nuovo updated_at).
413
Il corpo della richiesta è troppo grande (request_too_large).
request_too_large).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl -X PATCH 'https://www.flowyer.it/api/agent/tasks/1234' \
-H 'Authorization: Bearer flw_...' \
-H 'Content-Type: application/json' \
-d '{
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"subject": "string"
}'
const response = await fetch("https://www.flowyer.it/api/agent/tasks/1234", {
method: "PATCH",
headers: {
"Authorization": "Bearer flw_...",
"Content-Type": "application/json",
},
body: JSON.stringify({
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"subject": "string"
}),
});
const result = await response.json();
import requests
response = requests.patch(
"https://www.flowyer.it/api/agent/tasks/1234",
headers={
"Authorization": "Bearer flw_...",
},
json={
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"subject": "string",
},
timeout=30,
)
print(response.status_code, response.json())
{
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"subject": "string"
}
Esempi di risposta
{
"data": {
"id": 9876,
"subject": "Submit the statement of defence",
"description": "string",
"deadline": "2026-11-15",
"priority": 2,
"status": "open",
"closed_at": "2026-10-30",
"matter": {
"id": 1234,
"case_number": "string"
},
"client": {
"id": 1234,
"name": "string"
},
"assigned_to_user_id": 1234,
"assigned_to": "string",
"created_by_user_id": 1234,
"created_by": "string",
"flag_id": 1234,
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
}
},
"updated": true
}
{
"error": "record_conflict",
"message": "The record changed since you read it (someone edited it). Read it again and retry with the new updated_at.",
"message_localized": "Il record è cambiato dall'ultima lettura (qualcuno lo ha modificato). Rileggerlo e riprovare con il nuovo updated_at.",
"locale": "it",
"details": {
"current_updated_at": "2026-10-30T10:42:05+01:00",
"reason": "modified_since_read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Chiudi l'attività
/api/agent/tasks/{id}/close
Chiude un'attività. Se vengono forniti i minuti, registra anche una voce di tempo (richiede workhours:create e una pratica: quella propria dell'attività, oppure matter_id su un'attività senza pratica); i minuti fatturabili vengono limitati al tetto orario dello studio. Una seconda chiusura risponde con 409, quindi un nuovo tentativo non registra mai una seconda voce.
Parametri di percorso
idobbligatorioId dell'attività.
9876Corpo della richiesta application/json
minutes_spentTempo impiegato, in minuti. Registrare qualsiasi tempo richiede lo scope workhours:create e una pratica.
minutes_invoiceableMinuti fatturabili; limitati al tetto orario dello studio.
minutes_normativeMinuti normativi; memorizzati grezzi, mai limitati.
matter_idAssegna questa pratica a un'attività SENZA PRATICA alla chiusura (e rende così possibile registrare il tempo). Non consentito quando l'attività ha già una pratica.
client_idCliente diretto (Megbízó) per un'attività senza pratica chiusa senza una pratica.
Risposte
200
OK.
dataobbligatorioCampi di data
id9876subject"Submit the statement of defence"descriptiondeadlineData di scadenza, YYYY-MM-DD.
"2026-11-15"priority1 = bassa, 2 = media, 3 = alta; null = non impostata (un'attività più vecchia senza priorità).
2status"open" "closed" closed_atGiorno in cui l'attività è stata chiusa, YYYY-MM-DD. Flowyer registra solo la data, non l'ora del giorno.
matterLa pratica a cui appartiene l'attività, se presente.
Campi di matter
idcase_numberclientIl cliente: il primo cliente della pratica, oppure il cliente proprio dell'attività quando non ha una pratica.
Campi di client
idnameassigned_to_user_idassigned_tocreated_by_user_idcreated_byflag_idcreated_atupdated_atcreated_via_apiCampi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduseratbooked_workhourLa voce di tempo registrata dalla chiusura, oppure null quando non è stato inserito alcun tempo.
Campi di booked_workhour
idminutesminutes_invoiceableminutes_normative
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
413
Il corpo della richiesta è troppo grande (request_too_large).
request_too_large).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl -X POST 'https://www.flowyer.it/api/agent/tasks/9876/close' \
-H 'Authorization: Bearer flw_...' \
-H 'Content-Type: application/json' \
-d '{}'
const response = await fetch("https://www.flowyer.it/api/agent/tasks/9876/close", {
method: "POST",
headers: {
"Authorization": "Bearer flw_...",
"Content-Type": "application/json",
},
body: JSON.stringify({}),
});
const result = await response.json();
import requests
response = requests.post(
"https://www.flowyer.it/api/agent/tasks/9876/close",
headers={
"Authorization": "Bearer flw_...",
},
json={},
timeout=30,
)
print(response.status_code, response.json())
{}
Esempi di risposta
{
"data": {
"id": 9876,
"subject": "Submit the statement of defence",
"description": "string",
"deadline": "2026-11-15",
"priority": 2,
"status": "open",
"closed_at": "2026-10-30",
"matter": {
"id": 1234,
"case_number": "string"
},
"client": {
"id": 1234,
"name": "string"
},
"assigned_to_user_id": 1234,
"assigned_to": "string",
"created_by_user_id": 1234,
"created_by": "string",
"flag_id": 1234,
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
},
"booked_workhour": {
"id": 1234,
"minutes": 0,
"minutes_invoiceable": 0,
"minutes_normative": 0
}
}
}
{
"error": "not_found",
"message": "The record was not found, or it is not visible to the user who owns this API key.",
"message_localized": "Il record non è stato trovato oppure non è visibile al titolare di questa chiave API.",
"locale": "it",
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Ore di lavoro
Elenca le voci di tempo
/api/agent/workhours
Elenca le voci di tempo attive (non ancora fatturate) sulle pratiche che l'utente può vedere, prima le più recenti. Filtra per pratica, collega responsabile o intervallo di date. Anche le voci escluse dal riepilogo vengono elencate, contrassegnate con excluded: true; le escluda dai totali fatturabili.
Parametri di query
matter_idSolo le voci di questa pratica.
1234responsible_user_idSolo le voci registrate a questo collega (un id utente da colleagues.list).
date_fromSolo le voci a partire da questa data inclusa (YYYY-MM-DD).
date_toSolo le voci fino a questa data inclusa (YYYY-MM-DD).
limitDimensione della pagina, 1-100. Valore predefinito 25.
2525offsetNumero di record da saltare. Usi offset + limit della pagina precedente per ottenere quella successiva; pagination.total è il conteggio totale.
00Risposte
200
OK.
dataobbligatorioCampi di data
idId della voce di tempo.
matter_idPratica a cui è registrata la voce.
dateactivityCosa è stato fatto (testo semplice).
minutesMinuti impiegati.
minutes_invoiceableMinuti fatturabili dopo l'applicazione del tetto orario dello studio (possono essere inferiori a quelli richiesti). Contano ai fini della fatturazione solo finché excluded è false.
minutes_normativeMinuti normativi (informativi; mai limitati).
responsible_user_idCollega a cui è registrato il tempo.
responsiblerecorded_by_user_idChi ha registrato la voce.
lockedTrue quando la voce è bloccata (di sola lettura tramite l'API).
excludedTrue quando un collega ha escluso la voce dal riepilogo della pratica: non viene fatturata e i suoi minuti sono esclusi dai totali fatturabili.
created_atupdated_atRinvii questo valore come expected_updated_at durante l'aggiornamento.
paginationobbligatorioCampi di pagination
limitobbligatoriooffsetobbligatoriototalobbligatorioNumero totale di record corrispondenti.
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl 'https://www.flowyer.it/api/agent/workhours?matter_id=1234&limit=25' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.it/api/agent/workhours?matter_id=1234&limit=25", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.it/api/agent/workhours?matter_id=1234&limit=25",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Esempi di risposta
{
"data": [
{
"id": 1234,
"matter_id": 1234,
"date": "2026-10-30",
"activity": "string",
"minutes": 0,
"minutes_invoiceable": 0,
"minutes_normative": 0,
"responsible_user_id": 1234,
"responsible": "string",
"recorded_by_user_id": 1234,
"locked": true,
"excluded": true,
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00"
}
],
"pagination": {
"limit": 25,
"offset": 0,
"total": 1
}
}
{
"error": "scope_missing",
"message": "This API key does not have the \"workhours:read\" permission. The permissions of an existing key cannot be changed, so the key owner needs to create a new key with this permission in Flowyer under Settings > API keys and use it in place of the old one.",
"message_localized": "Questa chiave API non ha il permesso \"workhours:read\". I permessi di una chiave esistente non possono essere modificati, quindi il titolare della chiave deve creare in Flowyer, in Impostazioni > Chiavi API, una nuova chiave con questo permesso e usarla al posto di quella vecchia.",
"locale": "it",
"details": {
"required_scope": "workhours:read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Ottieni la voce di tempo
/api/agent/workhours/{id}
Restituisce una voce di tempo attiva per id, se la relativa pratica è visibile all'utente.
Parametri di percorso
idobbligatorioId della voce di tempo.
Risposte
200
OK.
dataobbligatorioCampi di data
idId della voce di tempo.
matter_idPratica a cui è registrata la voce.
dateactivityCosa è stato fatto (testo semplice).
minutesMinuti impiegati.
minutes_invoiceableMinuti fatturabili dopo l'applicazione del tetto orario dello studio (possono essere inferiori a quelli richiesti). Contano ai fini della fatturazione solo finché excluded è false.
minutes_normativeMinuti normativi (informativi; mai limitati).
responsible_user_idCollega a cui è registrato il tempo.
responsiblerecorded_by_user_idChi ha registrato la voce.
lockedTrue quando la voce è bloccata (di sola lettura tramite l'API).
excludedTrue quando un collega ha escluso la voce dal riepilogo della pratica: non viene fatturata e i suoi minuti sono esclusi dai totali fatturabili.
created_atupdated_atRinvii questo valore come expected_updated_at durante l'aggiornamento.
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl 'https://www.flowyer.it/api/agent/workhours/1234' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.it/api/agent/workhours/1234", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.it/api/agent/workhours/1234",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Esempi di risposta
{
"data": {
"id": 1234,
"matter_id": 1234,
"date": "2026-10-30",
"activity": "string",
"minutes": 0,
"minutes_invoiceable": 0,
"minutes_normative": 0,
"responsible_user_id": 1234,
"responsible": "string",
"recorded_by_user_id": 1234,
"locked": true,
"excluded": true,
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00"
}
}
{
"error": "not_found",
"message": "The record was not found, or it is not visible to the user who owns this API key.",
"message_localized": "Il record non è stato trovato oppure non è visibile al titolare di questa chiave API.",
"locale": "it",
"details": {
"record_type": "workhour",
"record_id": 1234
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Registra una voce di tempo
/api/agent/workhours
Registra una voce di tempo su una pratica: data, attività, minuti impiegati e minuti fatturabili. Minuti fatturabili omessi significano non fatturabile: invii minutes_invoiceable per il lavoro fatturabile. Vengono limitati al tetto orario dello studio. Il collega responsabile è per impostazione predefinita l'utente della chiave e, in caso contrario, viene notificato.
Parametri di intestazione
Idempotency-KeyConsigliato a ogni creazione. Un valore univoco per operazione logica (ad es. un UUID). Lo stesso valore restituisce lo stesso record: riprovare con esso restituisce il record creato la prima volta invece di crearne un secondo. Valori diversi creano sempre record diversi. I client che non possono inviare header possono passare lo stesso valore nel campo del corpo idempotency_key. Lettere, cifre, _, -, : o ., al massimo 128 caratteri.
^[A-Za-z0-9_\-:.]{1,128}$Corpo della richiesta application/json
matter_idobbligatorioPratica a cui è registrato il tempo (deve essere visibile).
1234dateobbligatorioData del lavoro, YYYY-MM-DD.
"2026-10-30"subjectCosa è stato fatto; il lato di lettura la restituisce come activity e qui è accettato uno dei due nomi (uno dei due è obbligatorio). Testo semplice; "<" e ">" non sono consentiti.
^[^<>]*$"Drafting the statement of claim"activityLo stesso campo di subject, con il nome usato dal lato di lettura. Ne invii uno dei due.
^[^<>]*$minutesMinuti effettivamente impiegati.
90minutes_invoiceableMinuti fatturabili richiesti. Omessi o null = non fatturabile (la voce non fattura nulla; non vengono derivati da minutes): per il lavoro fatturabile li invii esplicitamente, di solito uguali a minutes. Il tetto orario dello studio può ridurre il valore memorizzato. Contano ai fini della fatturazione solo finché la voce non è esclusa dal riepilogo.
60minutes_normativeMinuti normativi (informativi; mai limitati).
responsible_user_idCollega a cui è registrato il tempo: un id utente da colleagues.list (cerchi lì un nome dettato). Predefinito: l'utente della chiave.
idempotency_keyStesso ruolo dell'header Idempotency-Key, per i client che non possono inviare header personalizzati. Lettere, cifre, _, -, : o ., al massimo 128 caratteri.
^[A-Za-z0-9_\-:.]{1,128}$"b8f1c2e0-6f7a-4d2e-9c1b-2a3d4e5f6a7b"Risposte
201
Creato.
dataobbligatorioCampi di data
idId della voce di tempo.
matter_idPratica a cui è registrata la voce.
dateactivityCosa è stato fatto (testo semplice).
minutesMinuti impiegati.
minutes_invoiceableMinuti fatturabili dopo l'applicazione del tetto orario dello studio (possono essere inferiori a quelli richiesti). Contano ai fini della fatturazione solo finché excluded è false.
minutes_normativeMinuti normativi (informativi; mai limitati).
responsible_user_idCollega a cui è registrato il tempo.
responsiblerecorded_by_user_idChi ha registrato la voce.
lockedTrue quando la voce è bloccata (di sola lettura tramite l'API).
excludedTrue quando un collega ha escluso la voce dal riepilogo della pratica: non viene fatturata e i suoi minuti sono esclusi dai totali fatturabili.
created_atupdated_atRinvii questo valore come expected_updated_at durante l'aggiornamento.
createdtrue
200
Replay idempotente: questo Idempotency-Key (o, senza chiave, una richiesta identica entro 120 secondi) ha già creato il record; viene restituito di nuovo, nulla di nuovo è stato creato.
dataobbligatorioCampi di data
idId della voce di tempo.
matter_idPratica a cui è registrata la voce.
dateactivityCosa è stato fatto (testo semplice).
minutesMinuti impiegati.
minutes_invoiceableMinuti fatturabili dopo l'applicazione del tetto orario dello studio (possono essere inferiori a quelli richiesti). Contano ai fini della fatturazione solo finché excluded è false.
minutes_normativeMinuti normativi (informativi; mai limitati).
responsible_user_idCollega a cui è registrato il tempo.
responsiblerecorded_by_user_idChi ha registrato la voce.
lockedTrue quando la voce è bloccata (di sola lettura tramite l'API).
excludedTrue quando un collega ha escluso la voce dal riepilogo della pratica: non viene fatturata e i suoi minuti sono esclusi dai totali fatturabili.
created_atupdated_atRinvii questo valore come expected_updated_at durante l'aggiornamento.
createdfalseidempotent_replaytrue
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente. replay_not_visible: questo Idempotency-Key (o, senza chiave, una richiesta identica) ha già creato il record (details.record_id), ma da allora è stato eliminato o non è visibile all'utente; nulla di nuovo è stato creato, non lo ricrei.
replay_not_visible: questo Idempotency-Key (o, senza chiave, una richiesta identica) ha già creato il record (details.record_id), ma da allora è stato eliminato o non è visibile all'utente; nulla di nuovo è stato creato, non lo ricrei.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
409
L'Idempotency-Key è stato usato per un altro tipo di risorsa (idempotency_key_reused), oppure, senza chiave, una richiesta identica è in fase di elaborazione in questo momento (duplicate_in_progress; riprovi a breve).
idempotency_key_reused), oppure, senza chiave, una richiesta identica è in fase di elaborazione in questo momento (duplicate_in_progress; riprovi a breve).
413
Il corpo della richiesta è troppo grande (request_too_large).
request_too_large).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl -X POST 'https://www.flowyer.it/api/agent/workhours' \
-H 'Authorization: Bearer flw_...' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: 7f3a9c21-1b2c-4d5e-8f90-0a1b2c3d4e5f' \
-d '{
"matter_id": 1234,
"date": "2026-10-30",
"subject": "Drafting the statement of claim",
"minutes": 90,
"minutes_invoiceable": 60
}'
const response = await fetch("https://www.flowyer.it/api/agent/workhours", {
method: "POST",
headers: {
"Authorization": "Bearer flw_...",
"Content-Type": "application/json",
"Idempotency-Key": crypto.randomUUID(),
},
body: JSON.stringify({
"matter_id": 1234,
"date": "2026-10-30",
"subject": "Drafting the statement of claim",
"minutes": 90,
"minutes_invoiceable": 60
}),
});
const result = await response.json();
import uuid
import requests
response = requests.post(
"https://www.flowyer.it/api/agent/workhours",
headers={
"Authorization": "Bearer flw_...",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"matter_id": 1234,
"date": "2026-10-30",
"subject": "Drafting the statement of claim",
"minutes": 90,
"minutes_invoiceable": 60,
},
timeout=30,
)
print(response.status_code, response.json())
{
"matter_id": 1234,
"date": "2026-10-30",
"subject": "Drafting the statement of claim",
"minutes": 90,
"minutes_invoiceable": 60
}
Esempi di risposta
{
"data": {
"id": 1234,
"matter_id": 1234,
"date": "2026-10-30",
"activity": "string",
"minutes": 0,
"minutes_invoiceable": 0,
"minutes_normative": 0,
"responsible_user_id": 1234,
"responsible": "string",
"recorded_by_user_id": 1234,
"locked": true,
"excluded": true,
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00"
},
"created": true
}
{
"data": {
"id": 1234,
"matter_id": 1234,
"date": "2026-10-30",
"activity": "string",
"minutes": 0,
"minutes_invoiceable": 0,
"minutes_normative": 0,
"responsible_user_id": 1234,
"responsible": "string",
"recorded_by_user_id": 1234,
"locked": true,
"excluded": true,
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00"
},
"created": false,
"idempotent_replay": true
}
{
"error": "validation_failed",
"message": "The request is invalid. See \"details.fields\" for the field-level errors.",
"message_localized": "La richiesta non è valida. Gli errori per campo sono in \"details.fields\".",
"locale": "it",
"details": {
"fields": {
"matter_id": [
"Il campo matter id è obbligatorio."
]
}
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Aggiorna la voce di tempo
/api/agent/workhours/{id}
Modifica una voce di tempo attiva: data, attività (subject o activity), minuti, minuti fatturabili (un numero modificato viene limitato al tetto orario, uno rinviato invariato viene mantenuto) e il collega responsabile. Una voce bloccata o fatturata non può essere modificata (409). Passi expected_updated_at; un conflitto risponde con 409.
Parametri di percorso
idobbligatorioId del record da modificare.
Corpo della richiesta application/json
expected_updated_atIl valore updated_at dalla sua lettura più recente di questo record (obbligatorio ogni volta che il record ne ha uno). Se il record è cambiato da allora (un collega lo ha modificato), l'API risponde 409 e deve rileggere prima di riprovare. Un record legacy il cui updated_at è null accetta null.
dateData del lavoro, YYYY-MM-DD. null mantiene la data corrente.
subjectCosa è stato fatto, il valore che il lato di lettura restituisce come activity (è accettato uno dei due nomi; null sotto uno di essi significa "non fornito", vengono rifiutati solo due testi diversi). Testo semplice, al massimo 1000 caratteri come NUOVO valore; non è possibile introdurre nemmeno "<" e ">", ma un testo memorizzato più lungo o che li contiene può essere restituito invariato. null mantiene il testo corrente.
activityLo stesso campo di subject, con il nome usato dal lato di lettura. Ne invii uno dei due (null sotto l'altro va bene).
minutesMinuti effettivamente impiegati; null li cancella.
minutes_invoiceableMinuti fatturabili richiesti. Un numero diverso da quello memorizzato viene limitato a ciò che resta del tetto orario; rinviare il valore restituito dalla lettura lo mantiene come registrato (non viene limitato di nuovo). null li cancella. Contano ai fini della fatturazione solo finché la voce non è esclusa dal riepilogo (excluded è false).
minutes_normativeMinuti normativi (mai limitati); null li cancella.
responsible_user_idNuovo collega responsabile: l'id utente di un collega attivo da colleagues.list; viene notificato quando non è Lei. Inviare quello corrente, o null / 0 con cui viene restituita una voce senza responsabile, non cambia nulla.
Risposte
200
Aggiornato.
dataobbligatorioCampi di data
idId della voce di tempo.
matter_idPratica a cui è registrata la voce.
dateactivityCosa è stato fatto (testo semplice).
minutesMinuti impiegati.
minutes_invoiceableMinuti fatturabili dopo l'applicazione del tetto orario dello studio (possono essere inferiori a quelli richiesti). Contano ai fini della fatturazione solo finché excluded è false.
minutes_normativeMinuti normativi (informativi; mai limitati).
responsible_user_idCollega a cui è registrato il tempo.
responsiblerecorded_by_user_idChi ha registrato la voce.
lockedTrue quando la voce è bloccata (di sola lettura tramite l'API).
excludedTrue quando un collega ha escluso la voce dal riepilogo della pratica: non viene fatturata e i suoi minuti sono esclusi dai totali fatturabili.
created_atupdated_atRinvii questo valore come expected_updated_at durante l'aggiornamento.
updatedtrue
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
409
Il record è cambiato da quando lo ha letto (record_conflict: expected_updated_at non corrisponde più; lo rilegga e riprovi con il nuovo updated_at), oppure è stato fatturato / bloccato e non può più essere modificato tramite l'API (record_locked; effettui la modifica in Flowyer).
record_conflict: expected_updated_at non corrisponde più; lo rilegga e riprovi con il nuovo updated_at), oppure è stato fatturato / bloccato e non può più essere modificato tramite l'API (record_locked; effettui la modifica in Flowyer).
413
Il corpo della richiesta è troppo grande (request_too_large).
request_too_large).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl -X PATCH 'https://www.flowyer.it/api/agent/workhours/1234' \
-H 'Authorization: Bearer flw_...' \
-H 'Content-Type: application/json' \
-d '{
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"date": "2026-10-30"
}'
const response = await fetch("https://www.flowyer.it/api/agent/workhours/1234", {
method: "PATCH",
headers: {
"Authorization": "Bearer flw_...",
"Content-Type": "application/json",
},
body: JSON.stringify({
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"date": "2026-10-30"
}),
});
const result = await response.json();
import requests
response = requests.patch(
"https://www.flowyer.it/api/agent/workhours/1234",
headers={
"Authorization": "Bearer flw_...",
},
json={
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"date": "2026-10-30",
},
timeout=30,
)
print(response.status_code, response.json())
{
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"date": "2026-10-30"
}
Esempi di risposta
{
"data": {
"id": 1234,
"matter_id": 1234,
"date": "2026-10-30",
"activity": "string",
"minutes": 0,
"minutes_invoiceable": 0,
"minutes_normative": 0,
"responsible_user_id": 1234,
"responsible": "string",
"recorded_by_user_id": 1234,
"locked": true,
"excluded": true,
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00"
},
"updated": true
}
{
"error": "record_conflict",
"message": "The record changed since you read it (someone edited it). Read it again and retry with the new updated_at.",
"message_localized": "Il record è cambiato dall'ultima lettura (qualcuno lo ha modificato). Rileggerlo e riprovare con il nuovo updated_at.",
"locale": "it",
"details": {
"current_updated_at": "2026-10-30T10:42:05+01:00",
"reason": "modified_since_read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Costi
Elenca i costi
/api/agent/costs
Elenca i costi attivi delle pratiche che l'utente può vedere, prima i più recenti (un costo fatturato non è più presente qui). Filtra per pratica, collega responsabile o intervallo di date. Gli importi sono al netto. Le righe contrassegnate con excluded: true sono fuori dal riepilogo e le righe contrassegnate con locked: true sono gestite da Flowyer.
Parametri di query
matter_idSolo i costi di questa pratica.
1234responsible_user_idSolo i costi registrati per questo collega (un id utente da colleagues.list).
date_fromSolo i costi a partire da questa data inclusa (YYYY-MM-DD).
date_toSolo i costi fino a questa data inclusa (YYYY-MM-DD).
limitDimensione della pagina, 1-100. Valore predefinito 25.
2525offsetNumero di record da saltare. Usi offset + limit della pagina precedente per ottenere quella successiva; pagination.total è il conteggio totale.
00Risposte
200
OK.
dataobbligatorioCampi di data
idId del costo.
matter_idPratica a cui appartiene il costo.
dateactivityDescrizione del costo (testo semplice).
costImporto netto del costo (IVA esclusa).
cost_invoiceableImporto netto da addebitare al cliente. Conta ai fini della fatturazione solo finché excluded è false.
currency_idId della valuta (elenco valute di Flowyer).
currencyCodice ISO della valuta, ad es. HUF, EUR.
responsible_user_idresponsibleexcludedTrue quando un collega ha escluso il costo dal riepilogo della pratica: non viene fatturato ed è escluso dai totali fatturabili.
lockedTrue quando il costo è gestito da Flowyer, replicato da una fattura in entrata o da una maggiorazione di esborso, e non può essere modificato tramite l'API (costs.update risponde con 409 record_locked, details.reason indica quale).
approved_for_billingTrue quando un collega ha approvato il costo per la fatturazione nel riepilogo della pratica. Rimane modificabile tramite l'API (come nel web) e l'approvazione NON viene richiesta di nuovo in seguito: lo segnali prima di modificare l'importo di un costo approvato.
created_atupdated_atRinvii questo valore come expected_updated_at durante l'aggiornamento.
paginationobbligatorioCampi di pagination
limitobbligatoriooffsetobbligatoriototalobbligatorioNumero totale di record corrispondenti.
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl 'https://www.flowyer.it/api/agent/costs?matter_id=1234&limit=25' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.it/api/agent/costs?matter_id=1234&limit=25", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.it/api/agent/costs?matter_id=1234&limit=25",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Esempi di risposta
{
"data": [
{
"id": 1234,
"matter_id": 1234,
"date": "2026-10-30",
"activity": "string",
"cost": 0,
"cost_invoiceable": 0,
"currency_id": 1234,
"currency": "string",
"responsible_user_id": 1234,
"responsible": "string",
"excluded": true,
"locked": true,
"approved_for_billing": true,
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00"
}
],
"pagination": {
"limit": 25,
"offset": 0,
"total": 1
}
}
{
"error": "scope_missing",
"message": "This API key does not have the \"costs:read\" permission. The permissions of an existing key cannot be changed, so the key owner needs to create a new key with this permission in Flowyer under Settings > API keys and use it in place of the old one.",
"message_localized": "Questa chiave API non ha il permesso \"costs:read\". I permessi di una chiave esistente non possono essere modificati, quindi il titolare della chiave deve creare in Flowyer, in Impostazioni > Chiavi API, una nuova chiave con questo permesso e usarla al posto di quella vecchia.",
"locale": "it",
"details": {
"required_scope": "costs:read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Ottieni il costo
/api/agent/costs/{id}
Restituisce un costo attivo per id, se la relativa pratica è visibile all'utente. Gli importi sono al netto.
Parametri di percorso
idobbligatorioId del costo.
Risposte
200
OK.
dataobbligatorioCampi di data
idId del costo.
matter_idPratica a cui appartiene il costo.
dateactivityDescrizione del costo (testo semplice).
costImporto netto del costo (IVA esclusa).
cost_invoiceableImporto netto da addebitare al cliente. Conta ai fini della fatturazione solo finché excluded è false.
currency_idId della valuta (elenco valute di Flowyer).
currencyCodice ISO della valuta, ad es. HUF, EUR.
responsible_user_idresponsibleexcludedTrue quando un collega ha escluso il costo dal riepilogo della pratica: non viene fatturato ed è escluso dai totali fatturabili.
lockedTrue quando il costo è gestito da Flowyer, replicato da una fattura in entrata o da una maggiorazione di esborso, e non può essere modificato tramite l'API (costs.update risponde con 409 record_locked, details.reason indica quale).
approved_for_billingTrue quando un collega ha approvato il costo per la fatturazione nel riepilogo della pratica. Rimane modificabile tramite l'API (come nel web) e l'approvazione NON viene richiesta di nuovo in seguito: lo segnali prima di modificare l'importo di un costo approvato.
created_atupdated_atRinvii questo valore come expected_updated_at durante l'aggiornamento.
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl 'https://www.flowyer.it/api/agent/costs/1234' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.it/api/agent/costs/1234", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.it/api/agent/costs/1234",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Esempi di risposta
{
"data": {
"id": 1234,
"matter_id": 1234,
"date": "2026-10-30",
"activity": "string",
"cost": 0,
"cost_invoiceable": 0,
"currency_id": 1234,
"currency": "string",
"responsible_user_id": 1234,
"responsible": "string",
"excluded": true,
"locked": true,
"approved_for_billing": true,
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00"
}
}
{
"error": "not_found",
"message": "The record was not found, or it is not visible to the user who owns this API key.",
"message_localized": "Il record non è stato trovato oppure non è visibile al titolare di questa chiave API.",
"locale": "it",
"details": {
"record_type": "cost",
"record_id": 1234
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Registra un costo
/api/agent/costs
Registra un costo (esborso) su una pratica: data, testo (subject, restituito come activity), importo netto, importo netto addebitato al cliente e valuta (predefinito: la valuta dello studio). Gli importi sono al netto (IVA esclusa). Il collega responsabile è per impostazione predefinita l'utente della chiave e, in caso contrario, viene notificato.
Parametri di intestazione
Idempotency-KeyConsigliato a ogni creazione. Un valore univoco per operazione logica (ad es. un UUID). Lo stesso valore restituisce lo stesso record: riprovare con esso restituisce il record creato la prima volta invece di crearne un secondo. Valori diversi creano sempre record diversi. I client che non possono inviare header possono passare lo stesso valore nel campo del corpo idempotency_key. Lettere, cifre, _, -, : o ., al massimo 128 caratteri.
^[A-Za-z0-9_\-:.]{1,128}$Corpo della richiesta application/json
matter_idobbligatorioPratica a cui appartiene il costo (deve essere visibile).
1234dateobbligatorioData del costo, YYYY-MM-DD.
"2026-10-30"subjectDescrizione del costo; il lato di lettura la restituisce come activity e qui è accettato uno dei due nomi (uno dei due è obbligatorio). Testo semplice; "<" e ">" non sono consentiti.
^[^<>]*$"Court filing fee"activityLo stesso campo di subject, con il nome usato dal lato di lettura. Ne invii uno dei due.
^[^<>]*$costobbligatorioImporto netto del costo (IVA esclusa), un numero intero nell'unità principale della valuta (i centesimi non vengono memorizzati).
15000cost_invoiceableImporto netto da addebitare al cliente, un numero intero (lo ometta se non addebitato). Conta ai fini della fatturazione solo finché il costo non è escluso dal riepilogo.
15000currency_idId della valuta dall'elenco valute di Flowyer (non un codice ISO). Lo ometta per usare la valuta dello studio (GET /me office.currency_id / office.currency); un id sconosciuto risponde con 422 e gli id e i codici accettati in details.allowed.
responsible_user_idCollega responsabile: un id utente da colleagues.list (cerchi lì un nome dettato). Predefinito: l'utente della chiave.
idempotency_keyStesso ruolo dell'header Idempotency-Key, per i client che non possono inviare header personalizzati. Lettere, cifre, _, -, : o ., al massimo 128 caratteri.
^[A-Za-z0-9_\-:.]{1,128}$"b8f1c2e0-6f7a-4d2e-9c1b-2a3d4e5f6a7b"Risposte
201
Creato.
dataobbligatorioCampi di data
idId del costo.
matter_idPratica a cui appartiene il costo.
dateactivityDescrizione del costo (testo semplice).
costImporto netto del costo (IVA esclusa).
cost_invoiceableImporto netto da addebitare al cliente. Conta ai fini della fatturazione solo finché excluded è false.
currency_idId della valuta (elenco valute di Flowyer).
currencyCodice ISO della valuta, ad es. HUF, EUR.
responsible_user_idresponsibleexcludedTrue quando un collega ha escluso il costo dal riepilogo della pratica: non viene fatturato ed è escluso dai totali fatturabili.
lockedTrue quando il costo è gestito da Flowyer, replicato da una fattura in entrata o da una maggiorazione di esborso, e non può essere modificato tramite l'API (costs.update risponde con 409 record_locked, details.reason indica quale).
approved_for_billingTrue quando un collega ha approvato il costo per la fatturazione nel riepilogo della pratica. Rimane modificabile tramite l'API (come nel web) e l'approvazione NON viene richiesta di nuovo in seguito: lo segnali prima di modificare l'importo di un costo approvato.
created_atupdated_atRinvii questo valore come expected_updated_at durante l'aggiornamento.
createdtrue
200
Replay idempotente: questo Idempotency-Key (o, senza chiave, una richiesta identica entro 120 secondi) ha già creato il record; viene restituito di nuovo, nulla di nuovo è stato creato.
dataobbligatorioCampi di data
idId del costo.
matter_idPratica a cui appartiene il costo.
dateactivityDescrizione del costo (testo semplice).
costImporto netto del costo (IVA esclusa).
cost_invoiceableImporto netto da addebitare al cliente. Conta ai fini della fatturazione solo finché excluded è false.
currency_idId della valuta (elenco valute di Flowyer).
currencyCodice ISO della valuta, ad es. HUF, EUR.
responsible_user_idresponsibleexcludedTrue quando un collega ha escluso il costo dal riepilogo della pratica: non viene fatturato ed è escluso dai totali fatturabili.
lockedTrue quando il costo è gestito da Flowyer, replicato da una fattura in entrata o da una maggiorazione di esborso, e non può essere modificato tramite l'API (costs.update risponde con 409 record_locked, details.reason indica quale).
approved_for_billingTrue quando un collega ha approvato il costo per la fatturazione nel riepilogo della pratica. Rimane modificabile tramite l'API (come nel web) e l'approvazione NON viene richiesta di nuovo in seguito: lo segnali prima di modificare l'importo di un costo approvato.
created_atupdated_atRinvii questo valore come expected_updated_at durante l'aggiornamento.
createdfalseidempotent_replaytrue
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente. replay_not_visible: questo Idempotency-Key (o, senza chiave, una richiesta identica) ha già creato il record (details.record_id), ma da allora è stato eliminato o non è visibile all'utente; nulla di nuovo è stato creato, non lo ricrei.
replay_not_visible: questo Idempotency-Key (o, senza chiave, una richiesta identica) ha già creato il record (details.record_id), ma da allora è stato eliminato o non è visibile all'utente; nulla di nuovo è stato creato, non lo ricrei.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
409
L'Idempotency-Key è stato usato per un altro tipo di risorsa (idempotency_key_reused), oppure, senza chiave, una richiesta identica è in fase di elaborazione in questo momento (duplicate_in_progress; riprovi a breve).
idempotency_key_reused), oppure, senza chiave, una richiesta identica è in fase di elaborazione in questo momento (duplicate_in_progress; riprovi a breve).
413
Il corpo della richiesta è troppo grande (request_too_large).
request_too_large).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl -X POST 'https://www.flowyer.it/api/agent/costs' \
-H 'Authorization: Bearer flw_...' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: 7f3a9c21-1b2c-4d5e-8f90-0a1b2c3d4e5f' \
-d '{
"matter_id": 1234,
"date": "2026-10-30",
"subject": "Court filing fee",
"cost": 15000,
"cost_invoiceable": 15000
}'
const response = await fetch("https://www.flowyer.it/api/agent/costs", {
method: "POST",
headers: {
"Authorization": "Bearer flw_...",
"Content-Type": "application/json",
"Idempotency-Key": crypto.randomUUID(),
},
body: JSON.stringify({
"matter_id": 1234,
"date": "2026-10-30",
"subject": "Court filing fee",
"cost": 15000,
"cost_invoiceable": 15000
}),
});
const result = await response.json();
import uuid
import requests
response = requests.post(
"https://www.flowyer.it/api/agent/costs",
headers={
"Authorization": "Bearer flw_...",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"matter_id": 1234,
"date": "2026-10-30",
"subject": "Court filing fee",
"cost": 15000,
"cost_invoiceable": 15000,
},
timeout=30,
)
print(response.status_code, response.json())
{
"matter_id": 1234,
"date": "2026-10-30",
"subject": "Court filing fee",
"cost": 15000,
"cost_invoiceable": 15000
}
Esempi di risposta
{
"data": {
"id": 1234,
"matter_id": 1234,
"date": "2026-10-30",
"activity": "string",
"cost": 0,
"cost_invoiceable": 0,
"currency_id": 1234,
"currency": "string",
"responsible_user_id": 1234,
"responsible": "string",
"excluded": true,
"locked": true,
"approved_for_billing": true,
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00"
},
"created": true
}
{
"data": {
"id": 1234,
"matter_id": 1234,
"date": "2026-10-30",
"activity": "string",
"cost": 0,
"cost_invoiceable": 0,
"currency_id": 1234,
"currency": "string",
"responsible_user_id": 1234,
"responsible": "string",
"excluded": true,
"locked": true,
"approved_for_billing": true,
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00"
},
"created": false,
"idempotent_replay": true
}
{
"error": "validation_failed",
"message": "The request is invalid. See \"details.fields\" for the field-level errors.",
"message_localized": "La richiesta non è valida. Gli errori per campo sono in \"details.fields\".",
"locale": "it",
"details": {
"fields": {
"matter_id": [
"Il campo matter id è obbligatorio."
]
}
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Aggiorna il costo
/api/agent/costs/{id}
Modifica un costo attivo: testo (subject, restituito come activity), data, importi netti, valuta e collega responsabile. Un costo contrassegnato con locked: true non può essere modificato (409 record_locked, details.reason). Passi expected_updated_at; una modifica in conflitto risponde con 409.
Parametri di percorso
idobbligatorioId del record da modificare.
Corpo della richiesta application/json
expected_updated_atIl valore updated_at dalla sua lettura più recente di questo record (obbligatorio ogni volta che il record ne ha uno). Se il record è cambiato da allora (un collega lo ha modificato), l'API risponde 409 e deve rileggere prima di riprovare. Un record legacy il cui updated_at è null accetta null.
dateData del costo, YYYY-MM-DD. null mantiene la data corrente.
subjectDescrizione del costo, il valore che il lato di lettura restituisce come activity (è accettato uno dei due nomi; null sotto uno di essi significa "non fornito", vengono rifiutati solo due testi diversi). Testo semplice, al massimo 1000 caratteri come NUOVO valore; non è possibile introdurre nemmeno "<" e ">", ma un testo memorizzato più lungo o che li contiene può essere restituito invariato. null mantiene il testo corrente.
activityLo stesso campo di subject, con il nome usato dal lato di lettura. Ne invii uno dei due (null sotto l'altro va bene).
costImporto netto del costo (IVA esclusa), un numero intero nell'unità principale della valuta (i centesimi non vengono memorizzati). null cancella l'importo.
cost_invoiceableImporto netto da addebitare al cliente, un numero intero; null lo cancella. Conta ai fini della fatturazione solo finché il costo non è escluso dal riepilogo (excluded è false).
currency_idId della valuta dall'elenco valute di Flowyer (non un codice ISO; la valuta dello studio è GET /me office.currency_id). Un id sconosciuto risponde con 422 e gli id e i codici accettati in details.allowed. null, o lo 0 con cui viene restituito un costo legacy non impostato, mantiene la valuta corrente.
responsible_user_idNuovo collega responsabile: l'id utente di un collega attivo da colleagues.list. Inviare quello corrente, o null / 0 con cui viene restituito un costo senza responsabile, non cambia nulla.
Risposte
200
Aggiornato.
dataobbligatorioCampi di data
idId del costo.
matter_idPratica a cui appartiene il costo.
dateactivityDescrizione del costo (testo semplice).
costImporto netto del costo (IVA esclusa).
cost_invoiceableImporto netto da addebitare al cliente. Conta ai fini della fatturazione solo finché excluded è false.
currency_idId della valuta (elenco valute di Flowyer).
currencyCodice ISO della valuta, ad es. HUF, EUR.
responsible_user_idresponsibleexcludedTrue quando un collega ha escluso il costo dal riepilogo della pratica: non viene fatturato ed è escluso dai totali fatturabili.
lockedTrue quando il costo è gestito da Flowyer, replicato da una fattura in entrata o da una maggiorazione di esborso, e non può essere modificato tramite l'API (costs.update risponde con 409 record_locked, details.reason indica quale).
approved_for_billingTrue quando un collega ha approvato il costo per la fatturazione nel riepilogo della pratica. Rimane modificabile tramite l'API (come nel web) e l'approvazione NON viene richiesta di nuovo in seguito: lo segnali prima di modificare l'importo di un costo approvato.
created_atupdated_atRinvii questo valore come expected_updated_at durante l'aggiornamento.
updatedtrue
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
409
Il record è cambiato da quando lo ha letto (record_conflict: expected_updated_at non corrisponde più; lo rilegga e riprovi con il nuovo updated_at), oppure è stato fatturato / bloccato e non può più essere modificato tramite l'API (record_locked; effettui la modifica in Flowyer).
record_conflict: expected_updated_at non corrisponde più; lo rilegga e riprovi con il nuovo updated_at), oppure è stato fatturato / bloccato e non può più essere modificato tramite l'API (record_locked; effettui la modifica in Flowyer).
413
Il corpo della richiesta è troppo grande (request_too_large).
request_too_large).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl -X PATCH 'https://www.flowyer.it/api/agent/costs/1234' \
-H 'Authorization: Bearer flw_...' \
-H 'Content-Type: application/json' \
-d '{
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"date": "2026-10-30"
}'
const response = await fetch("https://www.flowyer.it/api/agent/costs/1234", {
method: "PATCH",
headers: {
"Authorization": "Bearer flw_...",
"Content-Type": "application/json",
},
body: JSON.stringify({
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"date": "2026-10-30"
}),
});
const result = await response.json();
import requests
response = requests.patch(
"https://www.flowyer.it/api/agent/costs/1234",
headers={
"Authorization": "Bearer flw_...",
},
json={
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"date": "2026-10-30",
},
timeout=30,
)
print(response.status_code, response.json())
{
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"date": "2026-10-30"
}
Esempi di risposta
{
"data": {
"id": 1234,
"matter_id": 1234,
"date": "2026-10-30",
"activity": "string",
"cost": 0,
"cost_invoiceable": 0,
"currency_id": 1234,
"currency": "string",
"responsible_user_id": 1234,
"responsible": "string",
"excluded": true,
"locked": true,
"approved_for_billing": true,
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00"
},
"updated": true
}
{
"error": "record_conflict",
"message": "The record changed since you read it (someone edited it). Read it again and retry with the new updated_at.",
"message_localized": "Il record è cambiato dall'ultima lettura (qualcuno lo ha modificato). Rileggerlo e riprovare con il nuovo updated_at.",
"locale": "it",
"details": {
"current_updated_at": "2026-10-30T10:42:05+01:00",
"reason": "modified_since_read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Fatture
Elenca le fatture
/api/agent/invoices
Elenca le fatture (emesse e ricevute), prima la data di emissione più recente. direction=outgoing è l'elenco delle fatture emesse dallo studio ed esclude le proforma (direction=proforma le elenca). Di sola lettura: le fatture non possono essere create o modificate tramite l'API. Le fatture di pratiche che l'utente non può vedere sono nascoste.
Parametri di query
directionI tre elenchi propri dello studio: outgoing = fatture emesse dallo studio, proforma escluse (una riga legacy senza tipo di documento conta come fattura, come nella dashboard dello studio); proforma = richieste di pagamento (díjbekérő) emesse dallo studio; incoming = ricevute.
"incoming" "outgoing" "proforma" paid_status"unpaid" "paid" "partially_paid" "cancelled" client_idmatter_idissued_fromData di emissione a partire da questa data inclusa.
"2026-01-01"issued_toData di emissione fino a questa data inclusa.
"2026-12-31"limitDimensione della pagina, 1-100. Valore predefinito 25.
2525offsetNumero di record da saltare. Usi offset + limit della pagina precedente per ottenere quella successiva; pagination.total è il conteggio totale.
00Risposte
200
OK.
dataobbligatorioCampi di data
id301invoice_number"FLW-2026-0042"directionoutgoing = emesse dallo studio, incoming = ricevute dallo studio.
"incoming" "outgoing" document_type"proforma" è una richiesta di pagamento, non una fattura emessa: non è un ricavo e non deve essere conteggiata con quelle emesse. invoices.list direction=outgoing esclude le proforma, direction=proforma le elenca. Null su una riga legacy, che conta come fattura.
"invoice" "proforma" "receipt" source"manual" "szamlazz_outgoing" "szamlazz_imported" paid_status"unpaid" "paid" "partially_paid" "cancelled" issued_datedue_datepaid_datecompletion_datenet_amountgross_amountcurrency"HUF"payment_method_idpayment_methodNome localizzato del metodo di pagamento (ad es. bonifico bancario); in inglese quando la lingua dello studio non ne ha una traduzione, null quando il metodo non ha alcun nome. Identifichi il metodo tramite payment_method_id.
supplierEmittente di una fattura in entrata.
clientCampi di client
idnamematter_idcreated_atupdated_atpaginationobbligatorioCampi di pagination
limitobbligatoriooffsetobbligatoriototalobbligatorioNumero totale di record corrispondenti.
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl 'https://www.flowyer.it/api/agent/invoices?issued_from=2026-01-01&issued_to=2026-12-31&limit=25' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.it/api/agent/invoices?issued_from=2026-01-01&issued_to=2026-12-31&limit=25", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.it/api/agent/invoices?issued_from=2026-01-01&issued_to=2026-12-31&limit=25",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Esempi di risposta
{
"data": [
{
"id": 301,
"invoice_number": "FLW-2026-0042",
"direction": "incoming",
"document_type": "invoice",
"source": "manual",
"paid_status": "unpaid",
"issued_date": "2026-10-30",
"due_date": "2026-10-30",
"paid_date": "2026-10-30",
"completion_date": "2026-10-30",
"net_amount": 0,
"gross_amount": 0,
"currency": "HUF",
"payment_method_id": 1234,
"payment_method": "string",
"supplier": "string",
"client": {
"id": 1234,
"name": "string"
},
"matter_id": 1234,
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00"
}
],
"pagination": {
"limit": 25,
"offset": 0,
"total": 1
}
}
{
"error": "scope_missing",
"message": "This API key does not have the \"invoices:read\" permission. The permissions of an existing key cannot be changed, so the key owner needs to create a new key with this permission in Flowyer under Settings > API keys and use it in place of the old one.",
"message_localized": "Questa chiave API non ha il permesso \"invoices:read\". I permessi di una chiave esistente non possono essere modificati, quindi il titolare della chiave deve creare in Flowyer, in Impostazioni > Chiavi API, una nuova chiave con questo permesso e usarla al posto di quella vecchia.",
"locale": "it",
"details": {
"required_scope": "invoices:read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Ottieni la fattura
/api/agent/invoices/{id}
Restituisce una fattura. Di sola lettura. Risponde con 404 quando non esiste o appartiene a una pratica che l'utente non può vedere.
Parametri di percorso
idobbligatorioId della fattura.
301Risposte
200
OK.
dataobbligatorioCampi di data
id301invoice_number"FLW-2026-0042"directionoutgoing = emesse dallo studio, incoming = ricevute dallo studio.
"incoming" "outgoing" document_type"proforma" è una richiesta di pagamento, non una fattura emessa: non è un ricavo e non deve essere conteggiata con quelle emesse. invoices.list direction=outgoing esclude le proforma, direction=proforma le elenca. Null su una riga legacy, che conta come fattura.
"invoice" "proforma" "receipt" source"manual" "szamlazz_outgoing" "szamlazz_imported" paid_status"unpaid" "paid" "partially_paid" "cancelled" issued_datedue_datepaid_datecompletion_datenet_amountgross_amountcurrency"HUF"payment_method_idpayment_methodNome localizzato del metodo di pagamento (ad es. bonifico bancario); in inglese quando la lingua dello studio non ne ha una traduzione, null quando il metodo non ha alcun nome. Identifichi il metodo tramite payment_method_id.
supplierEmittente di una fattura in entrata.
clientCampi di client
idnamematter_idcreated_atupdated_atnotesreceived_datesent_dateproforma_invoice_id
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl 'https://www.flowyer.it/api/agent/invoices/301' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.it/api/agent/invoices/301", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.it/api/agent/invoices/301",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Esempi di risposta
{
"data": {
"id": 301,
"invoice_number": "FLW-2026-0042",
"direction": "incoming",
"document_type": "invoice",
"source": "manual",
"paid_status": "unpaid",
"issued_date": "2026-10-30",
"due_date": "2026-10-30",
"paid_date": "2026-10-30",
"completion_date": "2026-10-30",
"net_amount": 0,
"gross_amount": 0,
"currency": "HUF",
"payment_method_id": 1234,
"payment_method": "string",
"supplier": "string",
"client": {
"id": 1234,
"name": "string"
},
"matter_id": 1234,
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"notes": "string",
"received_date": "2026-10-30",
"sent_date": "2026-10-30",
"proforma_invoice_id": 1234
}
}
{
"error": "not_found",
"message": "The record was not found, or it is not visible to the user who owns this API key.",
"message_localized": "Il record non è stato trovato oppure non è visibile al titolare di questa chiave API.",
"locale": "it",
"details": {
"invoice_id": 301
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Documenti
Elenca i documenti della pratica
/api/agent/matters/{id}/documents
Elenca le versioni correnti dei documenti archiviati sotto una pratica: nomi, dimensioni, cartelle e chi li ha caricati. Solo metadati; usi documents.download (scope documents:download) per un link firmato al contenuto. I documenti con nome vengono prima, in ordine alfabetico, poi quelli importati che non hanno nome.
Parametri di percorso
idobbligatorioId della pratica.
1234Parametri di query
qFiltra per nome del file.
"contract"limitDimensione della pagina, 1-100. Valore predefinito 25.
2525offsetNumero di record da saltare. Usi offset + limit della pagina precedente per ottenere quella successiva; pagination.total è il conteggio totale.
00Risposte
200
OK.
dataobbligatorioCampi di data
idnameNome del file come mostrato in Flowyer: il nome memorizzato con il documento, oppure il suo nome di archiviazione quando è stato importato da un sistema più vecchio senza nome. documents.list è ordinato per nome memorizzato: i documenti che ne hanno uno vengono prima, in ordine alfabetico, poi quelli importati senza nome memorizzato, dal più vecchio (l'ordine in cui sono stati archiviati in Flowyer), che pertanto non sono ordinati per il nome qui mostrato. L'ordine è lo stesso in ogni pagina, quindi limit e offset scorrono l'elenco senza ripetizioni né lacune.
"Contract_v2.docx"sizeByte.
versionNumero di versione corrente del file.
folderLa cartella in cui è archiviato il documento, oppure null alla radice della pratica. documents.upload.complete risponde null quando la cartella scelta in documents.upload.init è stata eliminata mentre i byte venivano caricati: il documento viene allora archiviato alla radice della pratica, dove Flowyer lo mostra. Se la radice contiene già un documento con quel nome, il caricamento viene archiviato con un nome con suffisso ("Contract_2.pdf") invece di diventare una nuova versione di quel documento non correlato; il 201 restituisce il name memorizzato.
Campi di folder
idnamepathPercorso della cartella all'interno della pratica, separato da "/".
folder_deletedTrue quando il documento è archiviato in una cartella che non esiste più, che l'elenco file di Flowyer non mostra (folder è null per esso, come per un documento alla radice della pratica). documents.upload.complete risponde true solo se la cartella è stata eliminata mentre i byte venivano caricati E lo spostamento del file memorizzato alla radice della pratica non è riuscito: il documento viene allora mantenuto nella cartella eliminata, dove il suo contenuto è ancora raggiungibile. False per tutto il resto, inclusa una normale archiviazione alla radice.
created_by_user_idcreated_bycreated_atupdated_atpaginationobbligatorioCampi di pagination
limitobbligatoriooffsetobbligatoriototalobbligatorioNumero totale di record corrispondenti.
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl 'https://www.flowyer.it/api/agent/matters/1234/documents?q=contract&limit=25' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.it/api/agent/matters/1234/documents?q=contract&limit=25", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.it/api/agent/matters/1234/documents?q=contract&limit=25",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Esempi di risposta
{
"data": [
{
"id": 1234,
"name": "Contract_v2.docx",
"size": 0,
"version": 0,
"folder": {
"id": 1234,
"name": "string",
"path": "string"
},
"folder_deleted": true,
"created_by_user_id": 1234,
"created_by": "string",
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00"
}
],
"pagination": {
"limit": 25,
"offset": 0,
"total": 1
}
}
{
"error": "matter_not_visible",
"message": "The matter 1234 does not exist, is archived, or is not visible to the user who owns this API key.",
"message_localized": "La pratica 1234 non esiste, è archiviata oppure non è visibile al titolare di questa chiave API.",
"locale": "it",
"details": {
"matter_id": 1234
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Elenca le cartelle della pratica
/api/agent/matters/{id}/folders
Elenca ogni cartella di una pratica, incluse quelle vuote: id, name, parent_id e il percorso separato da "/", ordinate per percorso. Passi un id di cartella come folder_id a documents.upload.init. Risponde 404 quando la pratica non è visibile all'utente.
Parametri di percorso
idobbligatorioId della pratica.
1234Parametri di query
qSolo le cartelle il cui percorso contiene questo testo (maiuscole/minuscole e accenti ignorati), ad es. un nome di cartella.
"Beadványok"limitDimensione della pagina, 1-100. Valore predefinito 25.
2525offsetNumero di record da saltare. Usi offset + limit della pagina precedente per ottenere quella successiva; pagination.total è il conteggio totale.
00Risposte
200
OK.
dataobbligatorioCampi di data
idId della cartella: lo passi come folder_id a documents.upload.init.
nameNome della cartella come mostrato in Flowyer.
parent_idId della cartella padre; null per una cartella alla radice della pratica.
pathPercorso della cartella all'interno della pratica, separato da "/", ad es. "/Iratok/Beadványok" (lo stesso percorso che documents.list mostra per la cartella di un file).
updated_atPassi questo a documents.folders.rename come expected_updated_at.
paginationobbligatorioCampi di pagination
limitobbligatoriooffsetobbligatoriototalobbligatorioNumero totale di record corrispondenti.
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl 'https://www.flowyer.it/api/agent/matters/1234/folders?q=Beadv%C3%A1nyok&limit=25' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.it/api/agent/matters/1234/folders?q=Beadv%C3%A1nyok&limit=25", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.it/api/agent/matters/1234/folders?q=Beadv%C3%A1nyok&limit=25",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Esempi di risposta
{
"data": [
{
"id": 1234,
"name": "string",
"parent_id": 1234,
"path": "string",
"updated_at": "2026-10-30T09:15:00+01:00"
}
],
"pagination": {
"limit": 25,
"offset": 0,
"total": 1
}
}
{
"error": "matter_not_visible",
"message": "The matter 1234 does not exist, is archived, or is not visible to the user who owns this API key.",
"message_localized": "La pratica 1234 non esiste, è archiviata oppure non è visibile al titolare di questa chiave API.",
"locale": "it",
"details": {
"matter_id": 1234
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Crea una cartella della pratica
/api/agent/matters/{id}/folders
Crea una cartella in una pratica, alla radice o sotto parent_id (una cartella della STESSA pratica). Il nome è testo semplice ("<" e ">" non sono consentiti). Archivi un documento al suo interno passando l'id restituito come folder_id a documents.upload.init. Risponde 404 quando la pratica non è visibile.
Parametri di percorso
idobbligatorioPratica a cui appartiene la cartella (deve essere visibile).
1234Parametri di intestazione
Idempotency-KeyConsigliato a ogni creazione. Un valore univoco per operazione logica (ad es. un UUID). Lo stesso valore restituisce lo stesso record: riprovare con esso restituisce il record creato la prima volta invece di crearne un secondo. Valori diversi creano sempre record diversi. I client che non possono inviare header possono passare lo stesso valore nel campo del corpo idempotency_key. Lettere, cifre, _, -, : o ., al massimo 128 caratteri.
^[A-Za-z0-9_\-:.]{1,128}$Corpo della richiesta application/json
nameobbligatorioNome della cartella, al massimo 255 caratteri. Testo semplice; "<" e ">" non sono consentiti.
^[^<>]*$"Beadványok"parent_idId della cartella padre (da documents.folders) all'interno della STESSA pratica; ometta per una cartella alla radice della pratica.
idempotency_keyStesso ruolo dell'header Idempotency-Key, per i client che non possono inviare header personalizzati. Lettere, cifre, _, -, : o ., al massimo 128 caratteri.
^[A-Za-z0-9_\-:.]{1,128}$"b8f1c2e0-6f7a-4d2e-9c1b-2a3d4e5f6a7b"Risposte
201
Creato.
dataobbligatorioCampi di data
idId della cartella: lo passi come folder_id a documents.upload.init, oppure come parent_id a documents.folders.create.
nameNome della cartella come mostrato in Flowyer.
parent_idId della cartella padre; null per una cartella alla radice della pratica.
pathPercorso della cartella all'interno della pratica, separato da "/", ad es. "/Iratok/Beadványok".
updated_atPassi questo a documents.folders.rename come expected_updated_at.
createdtrue
200
Replay idempotente: questo Idempotency-Key (o, senza chiave, una richiesta identica entro 120 secondi) ha già creato il record; viene restituito di nuovo, nulla di nuovo è stato creato.
dataobbligatorioCampi di data
idId della cartella: lo passi come folder_id a documents.upload.init, oppure come parent_id a documents.folders.create.
nameNome della cartella come mostrato in Flowyer.
parent_idId della cartella padre; null per una cartella alla radice della pratica.
pathPercorso della cartella all'interno della pratica, separato da "/", ad es. "/Iratok/Beadványok".
updated_atPassi questo a documents.folders.rename come expected_updated_at.
createdfalseidempotent_replaytrue
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente. replay_not_visible: questo Idempotency-Key (o, senza chiave, una richiesta identica) ha già creato il record (details.record_id), ma da allora è stato eliminato o non è visibile all'utente; nulla di nuovo è stato creato, non lo ricrei.
replay_not_visible: questo Idempotency-Key (o, senza chiave, una richiesta identica) ha già creato il record (details.record_id), ma da allora è stato eliminato o non è visibile all'utente; nulla di nuovo è stato creato, non lo ricrei.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
409
L'Idempotency-Key è stato usato per un altro tipo di risorsa (idempotency_key_reused), oppure, senza chiave, una richiesta identica è in fase di elaborazione in questo momento (duplicate_in_progress; riprovi a breve).
idempotency_key_reused), oppure, senza chiave, una richiesta identica è in fase di elaborazione in questo momento (duplicate_in_progress; riprovi a breve).
413
Il corpo della richiesta è troppo grande (request_too_large).
request_too_large).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl -X POST 'https://www.flowyer.it/api/agent/matters/1234/folders' \
-H 'Authorization: Bearer flw_...' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: 7f3a9c21-1b2c-4d5e-8f90-0a1b2c3d4e5f' \
-d '{
"name": "Beadványok"
}'
const response = await fetch("https://www.flowyer.it/api/agent/matters/1234/folders", {
method: "POST",
headers: {
"Authorization": "Bearer flw_...",
"Content-Type": "application/json",
"Idempotency-Key": crypto.randomUUID(),
},
body: JSON.stringify({
"name": "Beadványok"
}),
});
const result = await response.json();
import uuid
import requests
response = requests.post(
"https://www.flowyer.it/api/agent/matters/1234/folders",
headers={
"Authorization": "Bearer flw_...",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"name": "Beadványok",
},
timeout=30,
)
print(response.status_code, response.json())
{
"name": "Beadványok"
}
Esempi di risposta
{
"data": {
"id": 1234,
"name": "string",
"parent_id": 1234,
"path": "string",
"updated_at": "2026-10-30T09:15:00+01:00"
},
"created": true
}
{
"data": {
"id": 1234,
"name": "string",
"parent_id": 1234,
"path": "string",
"updated_at": "2026-10-30T09:15:00+01:00"
},
"created": false,
"idempotent_replay": true
}
{
"error": "validation_failed",
"message": "The request is invalid. See \"details.fields\" for the field-level errors.",
"message_localized": "La richiesta non è valida. Gli errori per campo sono in \"details.fields\".",
"locale": "it",
"details": {
"fields": {
"name": [
"Il campo name è obbligatorio."
]
}
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Avvia il caricamento del documento
/api/agent/matters/{id}/documents/uploads
Avvia un caricamento di documento: restituisce un upload_url firmato e un upload_token. Invii i byte lì con PUT, quindi richiami documents.upload.complete. La PUT è una semplice richiesta HTTPS esterna a questa API ed esterna agli strumenti MCP: un assistente privo di un proprio client HTTP dovrebbe chiedere all'utente di caricare il file in Flowyer.
Parametri di percorso
idobbligatorioPratica a cui appartiene il documento (deve essere visibile).
Corpo della richiesta application/json
filenameobbligatorioNome del file con estensione, ad es. "Contract.pdf". Testo semplice; "<" e ">" non sono consentiti. I tipi di file eseguibili e web vengono rifiutati (422 blocked_file_type).
^[^<>]*$"Contract.pdf"content_typeobbligatorioTipo MIME inviato sulla PUT, ad es. "application/pdf". Fa parte della firma e deve corrispondere esattamente.
"application/pdf"sizeobbligatorioDimensione del file in byte, al massimo 104857600 (il limite di caricamento); una dimensione maggiore risponde 413 file_too_large.
248000folder_idCartella all'interno della pratica: un id di cartella da documents.folders (elenca anche le cartelle vuote). Ometta per la radice della pratica.
Risposte
200
OK.
dataobbligatorioCampi di data
upload_urlURL firmato. Invii qui i byte del file con PUT usando il content type indicato E l'header if_generation_match riportato di seguito: una semplice richiesta HTTPS effettuata dal suo client HTTP (nessuno strumento API o MCP la invia).
upload_tokenPassi questo a documents.upload.complete dopo che la PUT è riuscita.
content_typeInvii esattamente questo Content-Type sulla PUT.
if_generation_matchInvii questo valore come header "x-goog-if-generation-match" sulla PUT (sempre "0"). Rende il caricamento monouso: la PUT viene accettata solo finché l'oggetto non esiste ancora, così l'URL firmato non può sovrascrivere un documento già archiviato.
object_keyNome di archiviazione interno (per riferimento).
expires_inSecondi prima che l'URL di caricamento e il token scadano.
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
413
Il corpo della richiesta è troppo grande (request_too_large), oppure il file supera il limite di caricamento (file_too_large; details.max indica il limite in byte).
request_too_large), oppure il file supera il limite di caricamento (file_too_large; details.max indica il limite in byte).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl -X POST 'https://www.flowyer.it/api/agent/matters/1234/documents/uploads' \
-H 'Authorization: Bearer flw_...' \
-H 'Content-Type: application/json' \
-d '{
"filename": "Contract.pdf",
"content_type": "application/pdf",
"size": 248000
}'
const response = await fetch("https://www.flowyer.it/api/agent/matters/1234/documents/uploads", {
method: "POST",
headers: {
"Authorization": "Bearer flw_...",
"Content-Type": "application/json",
},
body: JSON.stringify({
"filename": "Contract.pdf",
"content_type": "application/pdf",
"size": 248000
}),
});
const result = await response.json();
import requests
response = requests.post(
"https://www.flowyer.it/api/agent/matters/1234/documents/uploads",
headers={
"Authorization": "Bearer flw_...",
},
json={
"filename": "Contract.pdf",
"content_type": "application/pdf",
"size": 248000,
},
timeout=30,
)
print(response.status_code, response.json())
{
"filename": "Contract.pdf",
"content_type": "application/pdf",
"size": 248000
}
Esempi di risposta
{
"data": {
"upload_url": "string",
"upload_token": "string",
"content_type": "string",
"if_generation_match": "string",
"object_key": "string",
"expires_in": 0
}
}
{
"error": "validation_failed",
"message": "The request is invalid. See \"details.fields\" for the field-level errors.",
"message_localized": "La richiesta non è valida. Gli errori per campo sono in \"details.fields\".",
"locale": "it",
"details": {
"fields": {
"filename": [
"Il campo filename è obbligatorio."
]
}
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Completa il caricamento del documento
/api/agent/matters/{id}/documents
Completa un caricamento di documento: dopo che i byte sono stati inviati con PUT all'upload_url, registra il file sulla pratica come nuova versione. Passi l'upload_token da documents.upload.init. I metadati del file sono presi dal token, non da questa richiesta. Una cartella eliminata nel frattempo archivia il documento alla radice.
Parametri di percorso
idobbligatorioPratica a cui appartiene il documento (la stessa di init).
Parametri di intestazione
Idempotency-KeyConsigliato a ogni creazione. Un valore univoco per operazione logica (ad es. un UUID). Lo stesso valore restituisce lo stesso record: riprovare con esso restituisce il record creato la prima volta invece di crearne un secondo. Valori diversi creano sempre record diversi. I client che non possono inviare header possono passare lo stesso valore nel campo del corpo idempotency_key. Lettere, cifre, _, -, : o ., al massimo 128 caratteri.
^[A-Za-z0-9_\-:.]{1,128}$Corpo della richiesta application/json
upload_tokenobbligatorioIl token restituito da documents.upload.init.
idempotency_keyStesso ruolo dell'header Idempotency-Key, per i client che non possono inviare header personalizzati. Lettere, cifre, _, -, : o ., al massimo 128 caratteri.
^[A-Za-z0-9_\-:.]{1,128}$"b8f1c2e0-6f7a-4d2e-9c1b-2a3d4e5f6a7b"Risposte
201
Creato.
dataobbligatorioCampi di data
idnameNome del file come mostrato in Flowyer: il nome memorizzato con il documento, oppure il suo nome di archiviazione quando è stato importato da un sistema più vecchio senza nome. documents.list è ordinato per nome memorizzato: i documenti che ne hanno uno vengono prima, in ordine alfabetico, poi quelli importati senza nome memorizzato, dal più vecchio (l'ordine in cui sono stati archiviati in Flowyer), che pertanto non sono ordinati per il nome qui mostrato. L'ordine è lo stesso in ogni pagina, quindi limit e offset scorrono l'elenco senza ripetizioni né lacune.
"Contract_v2.docx"sizeByte.
versionNumero di versione corrente del file.
folderLa cartella in cui è archiviato il documento, oppure null alla radice della pratica. documents.upload.complete risponde null quando la cartella scelta in documents.upload.init è stata eliminata mentre i byte venivano caricati: il documento viene allora archiviato alla radice della pratica, dove Flowyer lo mostra. Se la radice contiene già un documento con quel nome, il caricamento viene archiviato con un nome con suffisso ("Contract_2.pdf") invece di diventare una nuova versione di quel documento non correlato; il 201 restituisce il name memorizzato.
Campi di folder
idnamepathPercorso della cartella all'interno della pratica, separato da "/".
folder_deletedTrue quando il documento è archiviato in una cartella che non esiste più, che l'elenco file di Flowyer non mostra (folder è null per esso, come per un documento alla radice della pratica). documents.upload.complete risponde true solo se la cartella è stata eliminata mentre i byte venivano caricati E lo spostamento del file memorizzato alla radice della pratica non è riuscito: il documento viene allora mantenuto nella cartella eliminata, dove il suo contenuto è ancora raggiungibile. False per tutto il resto, inclusa una normale archiviazione alla radice.
created_by_user_idcreated_bycreated_atupdated_atcreatedtrue
200
Replay idempotente: questo Idempotency-Key (o, senza chiave, una richiesta identica entro 120 secondi) ha già creato il record; viene restituito di nuovo, nulla di nuovo è stato creato. È anche la risposta quando questo upload_token è già stato completato.
dataobbligatorioCampi di data
idnameNome del file come mostrato in Flowyer: il nome memorizzato con il documento, oppure il suo nome di archiviazione quando è stato importato da un sistema più vecchio senza nome. documents.list è ordinato per nome memorizzato: i documenti che ne hanno uno vengono prima, in ordine alfabetico, poi quelli importati senza nome memorizzato, dal più vecchio (l'ordine in cui sono stati archiviati in Flowyer), che pertanto non sono ordinati per il nome qui mostrato. L'ordine è lo stesso in ogni pagina, quindi limit e offset scorrono l'elenco senza ripetizioni né lacune.
"Contract_v2.docx"sizeByte.
versionNumero di versione corrente del file.
folderLa cartella in cui è archiviato il documento, oppure null alla radice della pratica. documents.upload.complete risponde null quando la cartella scelta in documents.upload.init è stata eliminata mentre i byte venivano caricati: il documento viene allora archiviato alla radice della pratica, dove Flowyer lo mostra. Se la radice contiene già un documento con quel nome, il caricamento viene archiviato con un nome con suffisso ("Contract_2.pdf") invece di diventare una nuova versione di quel documento non correlato; il 201 restituisce il name memorizzato.
Campi di folder
idnamepathPercorso della cartella all'interno della pratica, separato da "/".
folder_deletedTrue quando il documento è archiviato in una cartella che non esiste più, che l'elenco file di Flowyer non mostra (folder è null per esso, come per un documento alla radice della pratica). documents.upload.complete risponde true solo se la cartella è stata eliminata mentre i byte venivano caricati E lo spostamento del file memorizzato alla radice della pratica non è riuscito: il documento viene allora mantenuto nella cartella eliminata, dove il suo contenuto è ancora raggiungibile. False per tutto il resto, inclusa una normale archiviazione alla radice.
created_by_user_idcreated_bycreated_atupdated_atcreatedfalseidempotent_replaytrue
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente. upload_not_finished: il file non ha ancora raggiunto l'archiviazione; completi la PUT verso upload_url, quindi richiami complete. replay_not_visible: questo Idempotency-Key (o, senza chiave, una richiesta identica) ha già creato il record (details.record_id), ma da allora è stato eliminato o non è visibile all'utente; nulla di nuovo è stato creato, non lo ricrei.
upload_not_finished: il file non ha ancora raggiunto l'archiviazione; completi la PUT verso upload_url, quindi richiami complete. replay_not_visible: questo Idempotency-Key (o, senza chiave, una richiesta identica) ha già creato il record (details.record_id), ma da allora è stato eliminato o non è visibile all'utente; nulla di nuovo è stato creato, non lo ricrei.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
409
L'Idempotency-Key è stato usato per un altro tipo di risorsa (idempotency_key_reused), oppure, senza chiave, una richiesta identica è in fase di elaborazione in questo momento (duplicate_in_progress; riprovi a breve).
idempotency_key_reused), oppure, senza chiave, una richiesta identica è in fase di elaborazione in questo momento (duplicate_in_progress; riprovi a breve).
413
Il corpo della richiesta è troppo grande (request_too_large), oppure il file supera il limite di caricamento (file_too_large; details.max indica il limite in byte).
request_too_large), oppure il file supera il limite di caricamento (file_too_large; details.max indica il limite in byte).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl -X POST 'https://www.flowyer.it/api/agent/matters/1234/documents' \
-H 'Authorization: Bearer flw_...' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: 7f3a9c21-1b2c-4d5e-8f90-0a1b2c3d4e5f' \
-d '{
"upload_token": "string"
}'
const response = await fetch("https://www.flowyer.it/api/agent/matters/1234/documents", {
method: "POST",
headers: {
"Authorization": "Bearer flw_...",
"Content-Type": "application/json",
"Idempotency-Key": crypto.randomUUID(),
},
body: JSON.stringify({
"upload_token": "string"
}),
});
const result = await response.json();
import uuid
import requests
response = requests.post(
"https://www.flowyer.it/api/agent/matters/1234/documents",
headers={
"Authorization": "Bearer flw_...",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"upload_token": "string",
},
timeout=30,
)
print(response.status_code, response.json())
{
"upload_token": "string"
}
Esempi di risposta
{
"data": {
"id": 1234,
"name": "Contract_v2.docx",
"size": 0,
"version": 0,
"folder": {
"id": 1234,
"name": "string",
"path": "string"
},
"folder_deleted": true,
"created_by_user_id": 1234,
"created_by": "string",
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00"
},
"created": true
}
{
"data": {
"id": 1234,
"name": "Contract_v2.docx",
"size": 0,
"version": 0,
"folder": {
"id": 1234,
"name": "string",
"path": "string"
},
"folder_deleted": true,
"created_by_user_id": 1234,
"created_by": "string",
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00"
},
"created": false,
"idempotent_replay": true
}
{
"error": "validation_failed",
"message": "The request is invalid. See \"details.fields\" for the field-level errors.",
"message_localized": "La richiesta non è valida. Gli errori per campo sono in \"details.fields\".",
"locale": "it",
"details": {
"fields": {
"upload_token": [
"Il campo upload token è obbligatorio."
]
}
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Scarica il documento
/api/agent/documents/{id}/download
Restituisce un URL firmato di breve durata per scaricare un documento tramite id, se la relativa pratica è visibile. Esegua una GET sull'url per recuperare i byte; scade in pochi minuti.
Parametri di percorso
idobbligatorioId del documento (da documents.list).
Risposte
200
OK.
dataobbligatorioCampi di data
download_urlURL firmato. Esegua una GET per scaricare i byte del file.
filenameNome del file per il download.
sizeByte.
expires_inSecondi mancanti alla scadenza dell'URL.
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl 'https://www.flowyer.it/api/agent/documents/1234/download' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.it/api/agent/documents/1234/download", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.it/api/agent/documents/1234/download",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Esempi di risposta
{
"data": {
"download_url": "string",
"filename": "string",
"size": 0,
"expires_in": 0
}
}
{
"error": "not_found",
"message": "The record was not found, or it is not visible to the user who owns this API key.",
"message_localized": "Il record non è stato trovato oppure non è visibile al titolare di questa chiave API.",
"locale": "it",
"details": {
"record_type": "document",
"record_id": 1234
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Rinomina il documento
/api/agent/documents/{id}
Rinomina un documento (solo il nome visualizzato; il contenuto del file resta invariato). Il nuovo nome deve essere univoco nella stessa cartella della pratica. Passi expected_updated_at ottenuto dall'ultima lettura; una modifica in conflitto risponde con 409.
Parametri di percorso
idobbligatorioId del record da modificare.
Corpo della richiesta application/json
expected_updated_atIl valore updated_at dalla sua lettura più recente di questo record (obbligatorio ogni volta che il record ne ha uno). Se il record è cambiato da allora (un collega lo ha modificato), l'API risponde 409 e deve rileggere prima di riprovare. Un record legacy il cui updated_at è null accetta null.
nameobbligatorioNuovo nome del file, al massimo 255 caratteri COMPRESA l'estensione. L'estensione corrente viene mantenuta se non ne indica una, e conta ai fini dei 255 (quindi un nome senza estensione per "Beadvany.pdf" può avere al massimo 251 caratteri). Testo semplice; "<" e ">" non sono consentiti, quindi un documento il cui nome memorizzato ne contiene uno può essere rinominato solo in Flowyer.
^[^<>]*$"Contract_signed.pdf"Risposte
200
Aggiornato.
dataobbligatorioCampi di data
idnameNome del file come mostrato in Flowyer: il nome memorizzato con il documento, oppure il suo nome di archiviazione quando è stato importato da un sistema più vecchio senza nome. documents.list è ordinato per nome memorizzato: i documenti che ne hanno uno vengono prima, in ordine alfabetico, poi quelli importati senza nome memorizzato, dal più vecchio (l'ordine in cui sono stati archiviati in Flowyer), che pertanto non sono ordinati per il nome qui mostrato. L'ordine è lo stesso in ogni pagina, quindi limit e offset scorrono l'elenco senza ripetizioni né lacune.
"Contract_v2.docx"sizeByte.
versionNumero di versione corrente del file.
folderLa cartella in cui è archiviato il documento, oppure null alla radice della pratica. documents.upload.complete risponde null quando la cartella scelta in documents.upload.init è stata eliminata mentre i byte venivano caricati: il documento viene allora archiviato alla radice della pratica, dove Flowyer lo mostra. Se la radice contiene già un documento con quel nome, il caricamento viene archiviato con un nome con suffisso ("Contract_2.pdf") invece di diventare una nuova versione di quel documento non correlato; il 201 restituisce il name memorizzato.
Campi di folder
idnamepathPercorso della cartella all'interno della pratica, separato da "/".
folder_deletedTrue quando il documento è archiviato in una cartella che non esiste più, che l'elenco file di Flowyer non mostra (folder è null per esso, come per un documento alla radice della pratica). documents.upload.complete risponde true solo se la cartella è stata eliminata mentre i byte venivano caricati E lo spostamento del file memorizzato alla radice della pratica non è riuscito: il documento viene allora mantenuto nella cartella eliminata, dove il suo contenuto è ancora raggiungibile. False per tutto il resto, inclusa una normale archiviazione alla radice.
created_by_user_idcreated_bycreated_atupdated_atupdatedtrue
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
409
Il record è cambiato da quando lo ha letto (record_conflict: expected_updated_at non corrisponde più; lo rilegga e riprovi con il nuovo updated_at), oppure un altro documento nella stessa cartella ha già questo nome (duplicate_name; scelga un altro nome, non riprovi con lo stesso).
record_conflict: expected_updated_at non corrisponde più; lo rilegga e riprovi con il nuovo updated_at), oppure un altro documento nella stessa cartella ha già questo nome (duplicate_name; scelga un altro nome, non riprovi con lo stesso).
413
Il corpo della richiesta è troppo grande (request_too_large).
request_too_large).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl -X PATCH 'https://www.flowyer.it/api/agent/documents/1234' \
-H 'Authorization: Bearer flw_...' \
-H 'Content-Type: application/json' \
-d '{
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"name": "Contract_signed.pdf"
}'
const response = await fetch("https://www.flowyer.it/api/agent/documents/1234", {
method: "PATCH",
headers: {
"Authorization": "Bearer flw_...",
"Content-Type": "application/json",
},
body: JSON.stringify({
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"name": "Contract_signed.pdf"
}),
});
const result = await response.json();
import requests
response = requests.patch(
"https://www.flowyer.it/api/agent/documents/1234",
headers={
"Authorization": "Bearer flw_...",
},
json={
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"name": "Contract_signed.pdf",
},
timeout=30,
)
print(response.status_code, response.json())
{
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"name": "Contract_signed.pdf"
}
Esempi di risposta
{
"data": {
"id": 1234,
"name": "Contract_v2.docx",
"size": 0,
"version": 0,
"folder": {
"id": 1234,
"name": "string",
"path": "string"
},
"folder_deleted": true,
"created_by_user_id": 1234,
"created_by": "string",
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00"
},
"updated": true
}
{
"error": "record_conflict",
"message": "The record changed since you read it (someone edited it). Read it again and retry with the new updated_at.",
"message_localized": "Il record è cambiato dall'ultima lettura (qualcuno lo ha modificato). Rileggerlo e riprovare con il nuovo updated_at.",
"locale": "it",
"details": {
"current_updated_at": "2026-10-30T10:42:05+01:00",
"reason": "modified_since_read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Rinomina la cartella della pratica
/api/agent/folders/{id}
Rinomina una cartella (solo il suo nome; i suoi file e sottocartelle mantengono la loro posizione). Il nome è testo semplice ("<" e ">" non sono consentiti). Passi expected_updated_at dalla sua ultima lettura (documents.folders lo elenca); una modifica in conflitto risponde 409.
Parametri di percorso
idobbligatorioId del record da modificare.
Corpo della richiesta application/json
expected_updated_atIl valore updated_at dalla sua lettura più recente di questo record (obbligatorio ogni volta che il record ne ha uno). Se il record è cambiato da allora (un collega lo ha modificato), l'API risponde 409 e deve rileggere prima di riprovare. Un record legacy il cui updated_at è null accetta null.
nameobbligatorioNuovo nome della cartella, al massimo 255 caratteri. Testo semplice; "<" e ">" non sono consentiti.
^[^<>]*$"Beadványok"Risposte
200
Aggiornato.
dataobbligatorioCampi di data
idId della cartella: lo passi come folder_id a documents.upload.init, oppure come parent_id a documents.folders.create.
nameNome della cartella come mostrato in Flowyer.
parent_idId della cartella padre; null per una cartella alla radice della pratica.
pathPercorso della cartella all'interno della pratica, separato da "/", ad es. "/Iratok/Beadványok".
updated_atPassi questo a documents.folders.rename come expected_updated_at.
updatedtrue
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
409
Il record è cambiato da quando lo ha letto (record_conflict: expected_updated_at non corrisponde più; lo rilegga e riprovi con il nuovo updated_at).
record_conflict: expected_updated_at non corrisponde più; lo rilegga e riprovi con il nuovo updated_at).
413
Il corpo della richiesta è troppo grande (request_too_large).
request_too_large).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl -X PATCH 'https://www.flowyer.it/api/agent/folders/1234' \
-H 'Authorization: Bearer flw_...' \
-H 'Content-Type: application/json' \
-d '{
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"name": "Beadványok"
}'
const response = await fetch("https://www.flowyer.it/api/agent/folders/1234", {
method: "PATCH",
headers: {
"Authorization": "Bearer flw_...",
"Content-Type": "application/json",
},
body: JSON.stringify({
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"name": "Beadványok"
}),
});
const result = await response.json();
import requests
response = requests.patch(
"https://www.flowyer.it/api/agent/folders/1234",
headers={
"Authorization": "Bearer flw_...",
},
json={
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"name": "Beadványok",
},
timeout=30,
)
print(response.status_code, response.json())
{
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"name": "Beadványok"
}
Esempi di risposta
{
"data": {
"id": 1234,
"name": "string",
"parent_id": 1234,
"path": "string",
"updated_at": "2026-10-30T09:15:00+01:00"
},
"updated": true
}
{
"error": "record_conflict",
"message": "The record changed since you read it (someone edited it). Read it again and retry with the new updated_at.",
"message_localized": "Il record è cambiato dall'ultima lettura (qualcuno lo ha modificato). Rileggerlo e riprovare con il nuovo updated_at.",
"locale": "it",
"details": {
"current_updated_at": "2026-10-30T10:42:05+01:00",
"reason": "modified_since_read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Base di conoscenza
Elenca gli articoli della knowledge base
/api/agent/knowledge/articles
Elenca gli articoli della knowledge base che l'utente può vedere (quelli propri dell'autore, gli articoli globali e gli articoli condivisi con il ruolo dell'utente). Tutti gli stati per impostazione predefinita; filtri per stato, oppure passi q per effettuare una ricerca full-text su titoli, estratti, contenuto e tag.
Parametri di query
qTermine di ricerca full-text (titoli, estratti, contenuto e nomi dei tag). Gli operatori booleani vengono rimossi.
"felmondási idő"statusSolo gli articoli con questo stato. Lo ometta per elencare ogni stato.
"draft" "published" "archived" limitDimensione della pagina, 1-100. Valore predefinito 25.
2525offsetNumero di record da saltare. Usi offset + limit della pagina precedente per ottenere quella successiva; pagination.total è il conteggio totale.
00Risposte
200
OK.
dataobbligatorioCampi di data
id9876slugSlug dell'URL generato dal server.
"felmondasi-ido"title"Felmondási idő a munka törvénykönyvében"excerptBreve riassunto (HTML ricco, come memorizzato). Per il corpo completo usare knowledge.articles.get.
status"draft" "published" "archived" is_featuredSe l'articolo è fissato sulla home page della KB (non impostabile tramite l'API).
category_idcategory_nameauthor_idId utente dell'autore; 0 per un articolo globale (predefinito).
author_nameeditor_idId utente dell'ultimo editor, oppure null se mai modificato.
editor_nameviews_countdownloads_countshared_rolesId dei ruoli con cui l'articolo è condiviso (vuoto = solo l'autore/globale).
tagsNomi dei tag sull'articolo.
published_atQuando l'articolo è stato pubblicato per la prima volta, oppure null.
created_atupdated_atpaginationobbligatorioCampi di pagination
limitobbligatoriooffsetobbligatoriototalobbligatorioNumero totale di record corrispondenti.
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl 'https://www.flowyer.it/api/agent/knowledge/articles?q=felmond%C3%A1si%20id%C5%91&limit=25' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.it/api/agent/knowledge/articles?q=felmond%C3%A1si%20id%C5%91&limit=25", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.it/api/agent/knowledge/articles?q=felmond%C3%A1si%20id%C5%91&limit=25",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Esempi di risposta
{
"data": [
{
"id": 9876,
"slug": "felmondasi-ido",
"title": "Felmondási idő a munka törvénykönyvében",
"excerpt": "string",
"status": "draft",
"is_featured": true,
"category_id": 1234,
"category_name": "string",
"author_id": 1234,
"author_name": "string",
"editor_id": 1234,
"editor_name": "string",
"views_count": 0,
"downloads_count": 0,
"shared_roles": [
0
],
"tags": [
"string"
],
"published_at": "2026-10-30T09:15:00+01:00",
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00"
}
],
"pagination": {
"limit": 25,
"offset": 0,
"total": 1
}
}
{
"error": "scope_missing",
"message": "This API key does not have the \"knowledge:read\" permission. The permissions of an existing key cannot be changed, so the key owner needs to create a new key with this permission in Flowyer under Settings > API keys and use it in place of the old one.",
"message_localized": "Questa chiave API non ha il permesso \"knowledge:read\". I permessi di una chiave esistente non possono essere modificati, quindi il titolare della chiave deve creare in Flowyer, in Impostazioni > Chiavi API, una nuova chiave con questo permesso e usarla al posto di quella vecchia.",
"locale": "it",
"details": {
"required_scope": "knowledge:read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Ottieni l'articolo della knowledge base
/api/agent/knowledge/articles/{id}
Restituisce un articolo della knowledge base, incluso il suo contenuto completo, i tag e i ruoli con cui è condiviso. Risponde con 404 quando l'articolo non esiste o l'utente non può vederlo.
Parametri di percorso
idobbligatorioId dell'articolo.
9876Risposte
200
OK.
dataobbligatorioCampi di data
id9876slugSlug dell'URL generato dal server.
"felmondasi-ido"title"Felmondási idő a munka törvénykönyvében"excerptBreve riassunto (HTML ricco, come memorizzato). Per il corpo completo usare knowledge.articles.get.
status"draft" "published" "archived" is_featuredSe l'articolo è fissato sulla home page della KB (non impostabile tramite l'API).
category_idcategory_nameauthor_idId utente dell'autore; 0 per un articolo globale (predefinito).
author_nameeditor_idId utente dell'ultimo editor, oppure null se mai modificato.
editor_nameviews_countdownloads_countshared_rolesId dei ruoli con cui l'articolo è condiviso (vuoto = solo l'autore/globale).
tagsNomi dei tag sull'articolo.
published_atQuando l'articolo è stato pubblicato per la prima volta, oppure null.
created_atupdated_atcontentIl corpo completo dell'articolo come memorizzato (HTML ricco).
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl 'https://www.flowyer.it/api/agent/knowledge/articles/9876' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.it/api/agent/knowledge/articles/9876", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.it/api/agent/knowledge/articles/9876",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Esempi di risposta
{
"data": {
"id": 9876,
"slug": "felmondasi-ido",
"title": "Felmondási idő a munka törvénykönyvében",
"excerpt": "string",
"status": "draft",
"is_featured": true,
"category_id": 1234,
"category_name": "string",
"author_id": 1234,
"author_name": "string",
"editor_id": 1234,
"editor_name": "string",
"views_count": 0,
"downloads_count": 0,
"shared_roles": [
0
],
"tags": [
"string"
],
"published_at": "2026-10-30T09:15:00+01:00",
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"content": "string"
}
}
{
"error": "not_found",
"message": "The record was not found, or it is not visible to the user who owns this API key.",
"message_localized": "Il record non è stato trovato oppure non è visibile al titolare di questa chiave API.",
"locale": "it",
"details": {
"article_id": 9876
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Crea un articolo della knowledge base
/api/agent/knowledge/articles
Crea un articolo della knowledge base con l'utente della chiave come autore. Lo slug viene generato dal titolo. La categoria deve esistere ed essere attiva. Lo condivida con i ruoli tramite shared_roles (altrimenti lo vede solo l'autore). content ed excerpt sono HTML e vengono sanificati lato server.
Parametri di intestazione
Idempotency-KeyConsigliato a ogni creazione. Un valore univoco per operazione logica (ad es. un UUID). Lo stesso valore restituisce lo stesso record: riprovare con esso restituisce il record creato la prima volta invece di crearne un secondo. Valori diversi creano sempre record diversi. I client che non possono inviare header possono passare lo stesso valore nel campo del corpo idempotency_key. Lettere, cifre, _, -, : o ., al massimo 128 caratteri.
^[A-Za-z0-9_\-:.]{1,128}$Corpo della richiesta application/json
titleobbligatorioTitolo dell'articolo. Testo semplice.
"Felmondási idő a munka törvénykönyvében"excerptBreve riepilogo (HTML consentito, sanificato lato server), al massimo 200 caratteri.
contentobbligatorioIl corpo dell'articolo. HTML formattato, sanificato lato server con il profilo della knowledge base.
category_idobbligatorioId di una categoria della knowledge base esistente e attiva.
12statusobbligatoriodraft, published o archived. published imposta published_at.
"draft" "published" "archived" tagsNomi dei tag; i nuovi tag vengono creati secondo necessità.
shared_rolesId dei ruoli con cui condividere l'articolo. Vuoto significa che solo l'autore può vederlo.
idempotency_keyStesso ruolo dell'header Idempotency-Key, per i client che non possono inviare header personalizzati. Lettere, cifre, _, -, : o ., al massimo 128 caratteri.
^[A-Za-z0-9_\-:.]{1,128}$"b8f1c2e0-6f7a-4d2e-9c1b-2a3d4e5f6a7b"Risposte
201
Creato.
dataobbligatorioCampi di data
id9876slugSlug dell'URL generato dal server.
"felmondasi-ido"title"Felmondási idő a munka törvénykönyvében"excerptBreve riassunto (HTML ricco, come memorizzato). Per il corpo completo usare knowledge.articles.get.
status"draft" "published" "archived" is_featuredSe l'articolo è fissato sulla home page della KB (non impostabile tramite l'API).
category_idcategory_nameauthor_idId utente dell'autore; 0 per un articolo globale (predefinito).
author_nameeditor_idId utente dell'ultimo editor, oppure null se mai modificato.
editor_nameviews_countdownloads_countshared_rolesId dei ruoli con cui l'articolo è condiviso (vuoto = solo l'autore/globale).
tagsNomi dei tag sull'articolo.
published_atQuando l'articolo è stato pubblicato per la prima volta, oppure null.
created_atupdated_atcontentIl corpo completo dell'articolo come memorizzato (HTML ricco).
createdtrue
200
Replay idempotente: questo Idempotency-Key (o, senza chiave, una richiesta identica entro 120 secondi) ha già creato il record; viene restituito di nuovo, nulla di nuovo è stato creato.
dataobbligatorioCampi di data
id9876slugSlug dell'URL generato dal server.
"felmondasi-ido"title"Felmondási idő a munka törvénykönyvében"excerptBreve riassunto (HTML ricco, come memorizzato). Per il corpo completo usare knowledge.articles.get.
status"draft" "published" "archived" is_featuredSe l'articolo è fissato sulla home page della KB (non impostabile tramite l'API).
category_idcategory_nameauthor_idId utente dell'autore; 0 per un articolo globale (predefinito).
author_nameeditor_idId utente dell'ultimo editor, oppure null se mai modificato.
editor_nameviews_countdownloads_countshared_rolesId dei ruoli con cui l'articolo è condiviso (vuoto = solo l'autore/globale).
tagsNomi dei tag sull'articolo.
published_atQuando l'articolo è stato pubblicato per la prima volta, oppure null.
created_atupdated_atcontentIl corpo completo dell'articolo come memorizzato (HTML ricco).
createdfalseidempotent_replaytrue
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente. replay_not_visible: questo Idempotency-Key (o, senza chiave, una richiesta identica) ha già creato il record (details.record_id), ma da allora è stato eliminato o non è visibile all'utente; nulla di nuovo è stato creato, non lo ricrei.
replay_not_visible: questo Idempotency-Key (o, senza chiave, una richiesta identica) ha già creato il record (details.record_id), ma da allora è stato eliminato o non è visibile all'utente; nulla di nuovo è stato creato, non lo ricrei.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
409
L'Idempotency-Key è stato usato per un altro tipo di risorsa (idempotency_key_reused), oppure, senza chiave, una richiesta identica è in fase di elaborazione in questo momento (duplicate_in_progress; riprovi a breve).
idempotency_key_reused), oppure, senza chiave, una richiesta identica è in fase di elaborazione in questo momento (duplicate_in_progress; riprovi a breve).
413
Il corpo della richiesta è troppo grande (request_too_large).
request_too_large).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl -X POST 'https://www.flowyer.it/api/agent/knowledge/articles' \
-H 'Authorization: Bearer flw_...' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: 7f3a9c21-1b2c-4d5e-8f90-0a1b2c3d4e5f' \
-d '{
"title": "Felmondási idő a munka törvénykönyvében",
"content": "string",
"category_id": 12,
"status": "draft"
}'
const response = await fetch("https://www.flowyer.it/api/agent/knowledge/articles", {
method: "POST",
headers: {
"Authorization": "Bearer flw_...",
"Content-Type": "application/json",
"Idempotency-Key": crypto.randomUUID(),
},
body: JSON.stringify({
"title": "Felmondási idő a munka törvénykönyvében",
"content": "string",
"category_id": 12,
"status": "draft"
}),
});
const result = await response.json();
import uuid
import requests
response = requests.post(
"https://www.flowyer.it/api/agent/knowledge/articles",
headers={
"Authorization": "Bearer flw_...",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"title": "Felmondási idő a munka törvénykönyvében",
"content": "string",
"category_id": 12,
"status": "draft",
},
timeout=30,
)
print(response.status_code, response.json())
{
"title": "Felmondási idő a munka törvénykönyvében",
"content": "string",
"category_id": 12,
"status": "draft"
}
Esempi di risposta
{
"data": {
"id": 9876,
"slug": "felmondasi-ido",
"title": "Felmondási idő a munka törvénykönyvében",
"excerpt": "string",
"status": "draft",
"is_featured": true,
"category_id": 1234,
"category_name": "string",
"author_id": 1234,
"author_name": "string",
"editor_id": 1234,
"editor_name": "string",
"views_count": 0,
"downloads_count": 0,
"shared_roles": [
0
],
"tags": [
"string"
],
"published_at": "2026-10-30T09:15:00+01:00",
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"content": "string"
},
"created": true
}
{
"data": {
"id": 9876,
"slug": "felmondasi-ido",
"title": "Felmondási idő a munka törvénykönyvében",
"excerpt": "string",
"status": "draft",
"is_featured": true,
"category_id": 1234,
"category_name": "string",
"author_id": 1234,
"author_name": "string",
"editor_id": 1234,
"editor_name": "string",
"views_count": 0,
"downloads_count": 0,
"shared_roles": [
0
],
"tags": [
"string"
],
"published_at": "2026-10-30T09:15:00+01:00",
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"content": "string"
},
"created": false,
"idempotent_replay": true
}
{
"error": "validation_failed",
"message": "The request is invalid. See \"details.fields\" for the field-level errors.",
"message_localized": "La richiesta non è valida. Gli errori per campo sono in \"details.fields\".",
"locale": "it",
"details": {
"fields": {
"title": [
"Il campo title è obbligatorio."
]
}
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Aggiorna l'articolo della knowledge base
/api/agent/knowledge/articles/{id}
Modifica un articolo della knowledge base: titolo (lo slug viene ricalcolato), estratto, contenuto, categoria, stato, tag o ruoli condivisi. Solo l'autore (o chiunque, per un articolo globale) può modificarlo. Passi expected_updated_at; una modifica in conflitto risponde con 409. content ed excerpt vengono sanificati lato server.
Parametri di percorso
idobbligatorioId del record da modificare.
Corpo della richiesta application/json
expected_updated_atIl valore updated_at dalla sua lettura più recente di questo record (obbligatorio ogni volta che il record ne ha uno). Se il record è cambiato da allora (un collega lo ha modificato), l'API risponde 409 e deve rileggere prima di riprovare. Un record legacy il cui updated_at è null accetta null.
titleTitolo dell'articolo (testo semplice). null mantiene il titolo corrente; un nuovo titolo ricalcola lo slug.
excerptBreve riepilogo (HTML consentito, sanificato), al massimo 200 caratteri come NUOVO valore. Vuoto/null lo cancella; lo ometta per mantenerlo.
contentIl corpo dell'articolo (HTML formattato, sanificato). null mantiene il contenuto corrente; non può essere cancellato.
category_idSposta l'articolo in questa categoria esistente e attiva. null mantiene quella corrente.
statusdraft, published o archived. Il primo passaggio a published imposta published_at; non viene mai cancellato. null mantiene lo stato corrente.
"draft" "published" "archived" tagsSostituisce l'intero insieme di tag (i nuovi tag vengono creati). Un array vuoto cancella tutti i tag; lo ometta per mantenerli.
shared_rolesSostituisce l'intero insieme di ruoli condivisi. Un array vuoto rimuove tutte le condivisioni (lo vede solo l'autore); lo ometta per mantenerlo.
Risposte
200
Aggiornato.
dataobbligatorioCampi di data
id9876slugSlug dell'URL generato dal server.
"felmondasi-ido"title"Felmondási idő a munka törvénykönyvében"excerptBreve riassunto (HTML ricco, come memorizzato). Per il corpo completo usare knowledge.articles.get.
status"draft" "published" "archived" is_featuredSe l'articolo è fissato sulla home page della KB (non impostabile tramite l'API).
category_idcategory_nameauthor_idId utente dell'autore; 0 per un articolo globale (predefinito).
author_nameeditor_idId utente dell'ultimo editor, oppure null se mai modificato.
editor_nameviews_countdownloads_countshared_rolesId dei ruoli con cui l'articolo è condiviso (vuoto = solo l'autore/globale).
tagsNomi dei tag sull'articolo.
published_atQuando l'articolo è stato pubblicato per la prima volta, oppure null.
created_atupdated_atcontentIl corpo completo dell'articolo come memorizzato (HTML ricco).
updatedtrue
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
409
Il record è cambiato da quando lo ha letto (record_conflict: expected_updated_at non corrisponde più; lo rilegga e riprovi con il nuovo updated_at).
record_conflict: expected_updated_at non corrisponde più; lo rilegga e riprovi con il nuovo updated_at).
413
Il corpo della richiesta è troppo grande (request_too_large).
request_too_large).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl -X PATCH 'https://www.flowyer.it/api/agent/knowledge/articles/1234' \
-H 'Authorization: Bearer flw_...' \
-H 'Content-Type: application/json' \
-d '{
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"title": "string"
}'
const response = await fetch("https://www.flowyer.it/api/agent/knowledge/articles/1234", {
method: "PATCH",
headers: {
"Authorization": "Bearer flw_...",
"Content-Type": "application/json",
},
body: JSON.stringify({
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"title": "string"
}),
});
const result = await response.json();
import requests
response = requests.patch(
"https://www.flowyer.it/api/agent/knowledge/articles/1234",
headers={
"Authorization": "Bearer flw_...",
},
json={
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"title": "string",
},
timeout=30,
)
print(response.status_code, response.json())
{
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"title": "string"
}
Esempi di risposta
{
"data": {
"id": 9876,
"slug": "felmondasi-ido",
"title": "Felmondási idő a munka törvénykönyvében",
"excerpt": "string",
"status": "draft",
"is_featured": true,
"category_id": 1234,
"category_name": "string",
"author_id": 1234,
"author_name": "string",
"editor_id": 1234,
"editor_name": "string",
"views_count": 0,
"downloads_count": 0,
"shared_roles": [
0
],
"tags": [
"string"
],
"published_at": "2026-10-30T09:15:00+01:00",
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"content": "string"
},
"updated": true
}
{
"error": "record_conflict",
"message": "The record changed since you read it (someone edited it). Read it again and retry with the new updated_at.",
"message_localized": "Il record è cambiato dall'ultima lettura (qualcuno lo ha modificato). Rileggerlo e riprovare con il nuovo updated_at.",
"locale": "it",
"details": {
"current_updated_at": "2026-10-30T10:42:05+01:00",
"reason": "modified_since_read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Elenca le categorie della knowledge base
/api/agent/knowledge/categories
Elenca le categorie della knowledge base che l'utente può vedere: categorie predefinite integrate, quelle proprie dell'utente e quelle condivise con il ruolo dell'utente. Ordinate come in Flowyer (posizione di ordinamento, poi nome).
Parametri di query
limitDimensione della pagina, 1-100. Valore predefinito 25.
2525offsetNumero di record da saltare. Usi offset + limit della pagina precedente per ottenere quella successiva; pagination.total è il conteggio totale.
00Risposte
200
OK.
dataobbligatorioCampi di data
id42slugSlug dell'URL, generato dal nome.
"munkajog"name"Munkajog"descriptionDescrizione in testo semplice, oppure null.
iconIdentificatore dell'icona mostrata accanto alla categoria, oppure null.
order_columnPosizione di ordinamento tra le categorie dello stesso livello.
0is_activeparent_idId della categoria padre, oppure null per una categoria radice.
author_idId utente del creatore; 0 per una categoria predefinita integrata visibile a tutti.
author_nameNome visualizzato del creatore, oppure null per una categoria predefinita.
articles_countNumero di articoli pubblicati in questa categoria che il chiamante può vedere.
shared_rolesId dei ruoli con cui questa categoria è condivisa. Vuoto significa che la vede solo l'autore (una categoria predefinita con author_id 0 è visibile a tutti).
created_atupdated_atpaginationobbligatorioCampi di pagination
limitobbligatoriooffsetobbligatoriototalobbligatorioNumero totale di record corrispondenti.
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl 'https://www.flowyer.it/api/agent/knowledge/categories?limit=25' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.it/api/agent/knowledge/categories?limit=25", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.it/api/agent/knowledge/categories?limit=25",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Esempi di risposta
{
"data": [
{
"id": 42,
"slug": "munkajog",
"name": "Munkajog",
"description": "string",
"icon": "string",
"order_column": 0,
"is_active": true,
"parent_id": 1234,
"author_id": 1234,
"author_name": "string",
"articles_count": 0,
"shared_roles": [
1
],
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00"
}
],
"pagination": {
"limit": 25,
"offset": 0,
"total": 1
}
}
{
"error": "scope_missing",
"message": "This API key does not have the \"knowledge:read\" permission. The permissions of an existing key cannot be changed, so the key owner needs to create a new key with this permission in Flowyer under Settings > API keys and use it in place of the old one.",
"message_localized": "Questa chiave API non ha il permesso \"knowledge:read\". I permessi di una chiave esistente non possono essere modificati, quindi il titolare della chiave deve creare in Flowyer, in Impostazioni > Chiavi API, una nuova chiave con questo permesso e usarla al posto di quella vecchia.",
"locale": "it",
"details": {
"required_scope": "knowledge:read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Ottieni la categoria della knowledge base
/api/agent/knowledge/categories/{id}
Restituisce una categoria della knowledge base. Risponde con 404 quando la categoria non esiste o non è visibile all'utente proprietario di questa chiave API.
Parametri di percorso
idobbligatorioId della categoria.
42Risposte
200
OK.
dataobbligatorioCampi di data
id42slugSlug dell'URL, generato dal nome.
"munkajog"name"Munkajog"descriptionDescrizione in testo semplice, oppure null.
iconIdentificatore dell'icona mostrata accanto alla categoria, oppure null.
order_columnPosizione di ordinamento tra le categorie dello stesso livello.
0is_activeparent_idId della categoria padre, oppure null per una categoria radice.
author_idId utente del creatore; 0 per una categoria predefinita integrata visibile a tutti.
author_nameNome visualizzato del creatore, oppure null per una categoria predefinita.
articles_countNumero di articoli pubblicati in questa categoria che il chiamante può vedere.
shared_rolesId dei ruoli con cui questa categoria è condivisa. Vuoto significa che la vede solo l'autore (una categoria predefinita con author_id 0 è visibile a tutti).
created_atupdated_at
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl 'https://www.flowyer.it/api/agent/knowledge/categories/42' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.it/api/agent/knowledge/categories/42", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.it/api/agent/knowledge/categories/42",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Esempi di risposta
{
"data": {
"id": 42,
"slug": "munkajog",
"name": "Munkajog",
"description": "string",
"icon": "string",
"order_column": 0,
"is_active": true,
"parent_id": 1234,
"author_id": 1234,
"author_name": "string",
"articles_count": 0,
"shared_roles": [
1
],
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00"
}
}
{
"error": "not_found",
"message": "The record was not found, or it is not visible to the user who owns this API key.",
"message_localized": "Il record non è stato trovato oppure non è visibile al titolare di questa chiave API.",
"locale": "it",
"details": {
"category_id": 42
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Crea una categoria della knowledge base
/api/agent/knowledge/categories
Crea una categoria della knowledge base. Lo slug dell'URL viene generato dal nome. La condivida con i ruoli tramite shared_roles, oppure li ometta in modo che solo Lei (l'autore) possa vederla. Un parent_id, se fornito, deve essere una categoria esistente e attiva.
Parametri di intestazione
Idempotency-KeyConsigliato a ogni creazione. Un valore univoco per operazione logica (ad es. un UUID). Lo stesso valore restituisce lo stesso record: riprovare con esso restituisce il record creato la prima volta invece di crearne un secondo. Valori diversi creano sempre record diversi. I client che non possono inviare header possono passare lo stesso valore nel campo del corpo idempotency_key. Lettere, cifre, _, -, : o ., al massimo 128 caratteri.
^[A-Za-z0-9_\-:.]{1,128}$Corpo della richiesta application/json
nameobbligatorioNome della categoria. Testo semplice; "<" e ">" non sono consentiti.
^[^<>]*$"Munkajog"descriptionDescrizione facoltativa, testo semplice.
parent_idId della categoria padre (deve esistere ed essere attiva). Lo ometta per una categoria radice.
iconIdentificatore dell'icona facoltativo. Testo semplice; "<" e ">" non sono consentiti.
^[^<>]*$is_activeSe la categoria è attiva. Predefinito true.
trueorder_columnPosizione di ordinamento tra le categorie dello stesso livello. Predefinito 0.
0shared_rolesId dei ruoli con cui condividere questa categoria. Li ometta in modo che solo Lei (l'autore) possa vederla.
idempotency_keyStesso ruolo dell'header Idempotency-Key, per i client che non possono inviare header personalizzati. Lettere, cifre, _, -, : o ., al massimo 128 caratteri.
^[A-Za-z0-9_\-:.]{1,128}$"b8f1c2e0-6f7a-4d2e-9c1b-2a3d4e5f6a7b"Risposte
201
Creato.
dataobbligatorioCampi di data
id42slugSlug dell'URL, generato dal nome.
"munkajog"name"Munkajog"descriptionDescrizione in testo semplice, oppure null.
iconIdentificatore dell'icona mostrata accanto alla categoria, oppure null.
order_columnPosizione di ordinamento tra le categorie dello stesso livello.
0is_activeparent_idId della categoria padre, oppure null per una categoria radice.
author_idId utente del creatore; 0 per una categoria predefinita integrata visibile a tutti.
author_nameNome visualizzato del creatore, oppure null per una categoria predefinita.
articles_countNumero di articoli pubblicati in questa categoria che il chiamante può vedere.
shared_rolesId dei ruoli con cui questa categoria è condivisa. Vuoto significa che la vede solo l'autore (una categoria predefinita con author_id 0 è visibile a tutti).
created_atupdated_atcreatedtrue
200
Replay idempotente: questo Idempotency-Key (o, senza chiave, una richiesta identica entro 120 secondi) ha già creato il record; viene restituito di nuovo, nulla di nuovo è stato creato.
dataobbligatorioCampi di data
id42slugSlug dell'URL, generato dal nome.
"munkajog"name"Munkajog"descriptionDescrizione in testo semplice, oppure null.
iconIdentificatore dell'icona mostrata accanto alla categoria, oppure null.
order_columnPosizione di ordinamento tra le categorie dello stesso livello.
0is_activeparent_idId della categoria padre, oppure null per una categoria radice.
author_idId utente del creatore; 0 per una categoria predefinita integrata visibile a tutti.
author_nameNome visualizzato del creatore, oppure null per una categoria predefinita.
articles_countNumero di articoli pubblicati in questa categoria che il chiamante può vedere.
shared_rolesId dei ruoli con cui questa categoria è condivisa. Vuoto significa che la vede solo l'autore (una categoria predefinita con author_id 0 è visibile a tutti).
created_atupdated_atcreatedfalseidempotent_replaytrue
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente. replay_not_visible: questo Idempotency-Key (o, senza chiave, una richiesta identica) ha già creato il record (details.record_id), ma da allora è stato eliminato o non è visibile all'utente; nulla di nuovo è stato creato, non lo ricrei.
replay_not_visible: questo Idempotency-Key (o, senza chiave, una richiesta identica) ha già creato il record (details.record_id), ma da allora è stato eliminato o non è visibile all'utente; nulla di nuovo è stato creato, non lo ricrei.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
409
L'Idempotency-Key è stato usato per un altro tipo di risorsa (idempotency_key_reused), oppure, senza chiave, una richiesta identica è in fase di elaborazione in questo momento (duplicate_in_progress; riprovi a breve).
idempotency_key_reused), oppure, senza chiave, una richiesta identica è in fase di elaborazione in questo momento (duplicate_in_progress; riprovi a breve).
413
Il corpo della richiesta è troppo grande (request_too_large).
request_too_large).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl -X POST 'https://www.flowyer.it/api/agent/knowledge/categories' \
-H 'Authorization: Bearer flw_...' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: 7f3a9c21-1b2c-4d5e-8f90-0a1b2c3d4e5f' \
-d '{
"name": "Munkajog",
"order_column": 0
}'
const response = await fetch("https://www.flowyer.it/api/agent/knowledge/categories", {
method: "POST",
headers: {
"Authorization": "Bearer flw_...",
"Content-Type": "application/json",
"Idempotency-Key": crypto.randomUUID(),
},
body: JSON.stringify({
"name": "Munkajog",
"order_column": 0
}),
});
const result = await response.json();
import uuid
import requests
response = requests.post(
"https://www.flowyer.it/api/agent/knowledge/categories",
headers={
"Authorization": "Bearer flw_...",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"name": "Munkajog",
"order_column": 0,
},
timeout=30,
)
print(response.status_code, response.json())
{
"name": "Munkajog",
"order_column": 0
}
Esempi di risposta
{
"data": {
"id": 42,
"slug": "munkajog",
"name": "Munkajog",
"description": "string",
"icon": "string",
"order_column": 0,
"is_active": true,
"parent_id": 1234,
"author_id": 1234,
"author_name": "string",
"articles_count": 0,
"shared_roles": [
1
],
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00"
},
"created": true
}
{
"data": {
"id": 42,
"slug": "munkajog",
"name": "Munkajog",
"description": "string",
"icon": "string",
"order_column": 0,
"is_active": true,
"parent_id": 1234,
"author_id": 1234,
"author_name": "string",
"articles_count": 0,
"shared_roles": [
1
],
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00"
},
"created": false,
"idempotent_replay": true
}
{
"error": "validation_failed",
"message": "The request is invalid. See \"details.fields\" for the field-level errors.",
"message_localized": "La richiesta non è valida. Gli errori per campo sono in \"details.fields\".",
"locale": "it",
"details": {
"fields": {
"name": [
"Il campo name è obbligatorio."
]
}
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Aggiorna la categoria della knowledge base
/api/agent/knowledge/categories/{id}
Modifica una categoria della knowledge base: nome (lo slug lo segue), descrizione, icona, categoria padre, flag di attività, posizione di ordinamento o i ruoli con cui è condivisa. Solo l'autore può modificarla (una categoria predefinita integrata è modificabile da chiunque). Passi expected_updated_at; una modifica in conflitto risponde con 409.
Parametri di percorso
idobbligatorioId del record da modificare.
Corpo della richiesta application/json
expected_updated_atIl valore updated_at dalla sua lettura più recente di questo record (obbligatorio ogni volta che il record ne ha uno). Se il record è cambiato da allora (un collega lo ha modificato), l'API risponde 409 e deve rileggere prima di riprovare. Un record legacy il cui updated_at è null accetta null.
nameNome della categoria. Al massimo 255 caratteri come NUOVO valore; non è possibile introdurre "<" e ">", ma un nome memorizzato più lungo o che li contiene può essere restituito invariato. null mantiene il nome corrente.
descriptionDescrizione in testo semplice. null la cancella.
parent_idSposta la categoria sotto questa categoria padre (deve esistere, essere attiva e non creare un ciclo), oppure null per renderla una categoria radice.
iconIdentificatore dell'icona. Al massimo 100 caratteri come NUOVO valore; non è possibile introdurre "<" e ">". null lo cancella.
is_activeFlag di attività. Lo ometta o usi null per mantenere il valore corrente.
order_columnPosizione di ordinamento tra le categorie dello stesso livello. Lo ometta o usi null per mantenere il valore corrente.
shared_rolesSostituisce l'insieme di id dei ruoli con cui questa categoria è condivisa. Un array vuoto rimuove tutte le condivisioni (la vede solo l'autore). Lo ometta per lasciare invariata la condivisione.
Risposte
200
Aggiornato.
dataobbligatorioCampi di data
id42slugSlug dell'URL, generato dal nome.
"munkajog"name"Munkajog"descriptionDescrizione in testo semplice, oppure null.
iconIdentificatore dell'icona mostrata accanto alla categoria, oppure null.
order_columnPosizione di ordinamento tra le categorie dello stesso livello.
0is_activeparent_idId della categoria padre, oppure null per una categoria radice.
author_idId utente del creatore; 0 per una categoria predefinita integrata visibile a tutti.
author_nameNome visualizzato del creatore, oppure null per una categoria predefinita.
articles_countNumero di articoli pubblicati in questa categoria che il chiamante può vedere.
shared_rolesId dei ruoli con cui questa categoria è condivisa. Vuoto significa che la vede solo l'autore (una categoria predefinita con author_id 0 è visibile a tutti).
created_atupdated_atupdatedtrue
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
409
Il record è cambiato da quando lo ha letto (record_conflict: expected_updated_at non corrisponde più; lo rilegga e riprovi con il nuovo updated_at).
record_conflict: expected_updated_at non corrisponde più; lo rilegga e riprovi con il nuovo updated_at).
413
Il corpo della richiesta è troppo grande (request_too_large).
request_too_large).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl -X PATCH 'https://www.flowyer.it/api/agent/knowledge/categories/1234' \
-H 'Authorization: Bearer flw_...' \
-H 'Content-Type: application/json' \
-d '{
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"name": "string"
}'
const response = await fetch("https://www.flowyer.it/api/agent/knowledge/categories/1234", {
method: "PATCH",
headers: {
"Authorization": "Bearer flw_...",
"Content-Type": "application/json",
},
body: JSON.stringify({
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"name": "string"
}),
});
const result = await response.json();
import requests
response = requests.patch(
"https://www.flowyer.it/api/agent/knowledge/categories/1234",
headers={
"Authorization": "Bearer flw_...",
},
json={
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"name": "string",
},
timeout=30,
)
print(response.status_code, response.json())
{
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"name": "string"
}
Esempi di risposta
{
"data": {
"id": 42,
"slug": "munkajog",
"name": "Munkajog",
"description": "string",
"icon": "string",
"order_column": 0,
"is_active": true,
"parent_id": 1234,
"author_id": 1234,
"author_name": "string",
"articles_count": 0,
"shared_roles": [
1
],
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00"
},
"updated": true
}
{
"error": "record_conflict",
"message": "The record changed since you read it (someone edited it). Read it again and retry with the new updated_at.",
"message_localized": "Il record è cambiato dall'ultima lettura (qualcuno lo ha modificato). Rileggerlo e riprovare con il nuovo updated_at.",
"locale": "it",
"details": {
"current_updated_at": "2026-10-30T10:42:05+01:00",
"reason": "modified_since_read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Elenca le email della pratica
/api/agent/matters/{id}/emails
Elenca le email salvate su una pratica: nome e indirizzo del mittente, oggetto, dimensione e il collega che ha salvato ciascuna, prima le più recenti per data di invio. Solo intestazione e metadati, mai il corpo o l'HTML grezzo. Usi emails.get per il corpo in testo semplice di un singolo messaggio.
Parametri di percorso
idobbligatorioId della pratica.
1234Parametri di query
qFiltra per oggetto, nome del mittente o indirizzo del mittente (ignorando accenti e maiuscole/minuscole). Non il corpo.
"invoice"limitDimensione della pagina, 1-100. Valore predefinito 25.
2525offsetNumero di record da saltare. Usi offset + limit della pagina precedente per ottenere quella successiva; pagination.total è il conteggio totale.
00Risposte
200
OK.
dataobbligatorioCampi di data
idId dell'email (da usare con emails.get).
1234from_nameNome visualizzato della parte esterna. L'archivio non conserva colonne di direzione o destinatario, quindi questa è sempre la parte esterna, mai un collega, e l'API non può dire se l'email fosse in entrata o in uscita.
from_addressIndirizzo SMTP della parte esterna.
subjectsent_atQuando il messaggio è stato inviato. Il fuso orario del valore memorizzato è incoerente a seconda del percorso di acquisizione (il worker IMAP memorizza UTC, il componente aggiuntivo di Outlook memorizza un'ora locale del fuso dello studio), quindi è al meglio possibile e l'ordinamento dell'elenco in base ad esso può discostarsi dell'offset UTC dello studio tra le varie sorgenti. created_at è il timestamp affidabile.
sizeByte del file .eml/.msg memorizzato.
extension"msg" (componente aggiuntivo di Outlook) o "eml" (IMAP / predefinito); null su alcune righe legacy.
saved_by_user_idId utente del collega che ha salvato l'email in Flowyer.
saved_byNome visualizzato di quel collega.
created_atQuando l'email è stata salvata in Flowyer (ora locale del fuso dello studio). Il timestamp affidabile per una paginazione stabile.
paginationobbligatorioCampi di pagination
limitobbligatoriooffsetobbligatoriototalobbligatorioNumero totale di record corrispondenti.
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl 'https://www.flowyer.it/api/agent/matters/1234/emails?q=invoice&limit=25' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.it/api/agent/matters/1234/emails?q=invoice&limit=25", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.it/api/agent/matters/1234/emails?q=invoice&limit=25",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Esempi di risposta
{
"data": [
{
"id": 1234,
"from_name": "string",
"from_address": "string",
"subject": "string",
"sent_at": "2026-10-30T09:15:00+01:00",
"size": 0,
"extension": "string",
"saved_by_user_id": 1234,
"saved_by": "string",
"created_at": "2026-10-30T09:15:00+01:00"
}
],
"pagination": {
"limit": 25,
"offset": 0,
"total": 1
}
}
{
"error": "matter_not_visible",
"message": "The matter 1234 does not exist, is archived, or is not visible to the user who owns this API key.",
"message_localized": "La pratica 1234 non esiste, è archiviata oppure non è visibile al titolare di questa chiave API.",
"locale": "it",
"details": {
"matter_id": 1234
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Ottieni l'email
/api/agent/emails/{id}
Restituisce un'email salvata di una pratica con il suo corpo in testo semplice (mittente, oggetto, dimensione e chi l'ha salvata). Il corpo HTML grezzo non viene mai restituito. Risponde 404 quando l'email non esiste o la sua pratica non è visibile all'utente proprietario di questa chiave API.
Parametri di percorso
idobbligatorioId dell'email.
1234Risposte
200
OK.
dataobbligatorioCampi di data
id1234matterLa pratica sotto cui è archiviata l'email, oppure null per un'email senza pratica (salvata al di fuori di qualsiasi causa).
Campi di matter
idcase_numberfrom_nameNome visualizzato della parte esterna (mai un collega; l'archivio non ha una colonna di direzione).
from_addressIndirizzo SMTP della parte esterna.
subjectbodyIl corpo del messaggio in testo semplice. Il corpo HTML grezzo non viene deliberatamente mai restituito (HTML di terze parti non attendibile). Testo semplice ottenuto al meglio possibile: se l'HTML originale conteneva <style>/<script>, il loro testo interno potrebbe sopravvivere al suo interno.
sent_atQuando il messaggio è stato inviato. Il fuso orario è incoerente a seconda del percorso di acquisizione (IMAP memorizza UTC, il componente aggiuntivo di Outlook un'ora locale del fuso dello studio); created_at è il timestamp affidabile.
sizeByte del file .eml/.msg memorizzato.
extension"msg" o "eml"; null su alcune righe legacy.
saved_by_user_idId utente del collega che ha salvato l'email in Flowyer.
saved_byNome visualizzato di quel collega.
created_atQuando l'email è stata salvata in Flowyer (ora locale del fuso dello studio).
updated_at
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl 'https://www.flowyer.it/api/agent/emails/1234' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.it/api/agent/emails/1234", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.it/api/agent/emails/1234",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Esempi di risposta
{
"data": {
"id": 1234,
"matter": {
"id": 1234,
"case_number": "string"
},
"from_name": "string",
"from_address": "string",
"subject": "string",
"body": "string",
"sent_at": "2026-10-30T09:15:00+01:00",
"size": 0,
"extension": "string",
"saved_by_user_id": 1234,
"saved_by": "string",
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00"
}
}
{
"error": "email_not_visible",
"message": "The email :id does not exist, or is on a matter that is not visible to the user who owns this API key.",
"message_localized": "L'email :id non esiste o appartiene a una pratica non visibile all'utente proprietario di questa chiave API.",
"locale": "it",
"details": {
"email_id": 1234
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Cronologia processuale
Elenca la cronologia processuale della pratica
/api/agent/matters/{id}/litigation
Elenca le voci della cronologia processuale (pertörténet) di una pratica, prima l'evento più recente: una nota datata con un titolo, una descrizione HTML e un luogo. Risponde 404 quando la pratica non è visibile all'utente.
Parametri di percorso
idobbligatorioId della pratica.
1234Parametri di query
limitDimensione della pagina, 1-100. Valore predefinito 25.
2525offsetNumero di record da saltare. Usi offset + limit della pagina precedente per ottenere quella successiva; pagination.total è il conteggio totale.
00Risposte
200
OK.
dataobbligatorioCampi di data
id4521titleTitolo della voce. Testo semplice.
"Első tárgyalás elhalasztva"descriptionDettagli della voce come HTML formattato, sanificato lato server.
locationDove è avvenuto (testo semplice), ad es. un'aula di tribunale; può essere null.
event_dateGiorno della voce, YYYY-MM-DD. Flowyer registra solo la data, non l'ora del giorno.
user_idAutore (l'utente che ha creato la voce).
created_byNome visualizzato dell'autore.
last_editor_idUtente che ha modificato per ultimo la voce.
last_editorNome visualizzato dell'ultimo editor.
created_atupdated_atPassi questo a litigation.update come expected_updated_at.
created_via_apiPresente quando un agente esterno ha creato la voce tramite questa API.
Campi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduseratpaginationobbligatorioCampi di pagination
limitobbligatoriooffsetobbligatoriototalobbligatorioNumero totale di record corrispondenti.
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl 'https://www.flowyer.it/api/agent/matters/1234/litigation?limit=25' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.it/api/agent/matters/1234/litigation?limit=25", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.it/api/agent/matters/1234/litigation?limit=25",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Esempi di risposta
{
"data": [
{
"id": 4521,
"title": "Első tárgyalás elhalasztva",
"description": "string",
"location": "string",
"event_date": "2026-10-30",
"user_id": 1234,
"created_by": "string",
"last_editor_id": 1234,
"last_editor": "string",
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
}
}
],
"pagination": {
"limit": 25,
"offset": 0,
"total": 1
}
}
{
"error": "matter_not_visible",
"message": "The matter 1234 does not exist, is archived, or is not visible to the user who owns this API key.",
"message_localized": "La pratica 1234 non esiste, è archiviata oppure non è visibile al titolare di questa chiave API.",
"locale": "it",
"details": {
"matter_id": 1234
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Crea una voce della cronologia processuale
/api/agent/matters/{id}/litigation
Aggiunge una voce della cronologia processuale (pertörténet) a una pratica: un titolo (testo semplice, "<"/">" non consentiti), una descrizione HTML facoltativa (sanificata lato server), un luogo facoltativo e una data dell'evento (predefinita a oggi). Risponde 404 quando la pratica non è visibile.
Parametri di percorso
idobbligatorioPratica a cui appartiene la voce (deve essere visibile).
1234Parametri di intestazione
Idempotency-KeyConsigliato a ogni creazione. Un valore univoco per operazione logica (ad es. un UUID). Lo stesso valore restituisce lo stesso record: riprovare con esso restituisce il record creato la prima volta invece di crearne un secondo. Valori diversi creano sempre record diversi. I client che non possono inviare header possono passare lo stesso valore nel campo del corpo idempotency_key. Lettere, cifre, _, -, : o ., al massimo 128 caratteri.
^[A-Za-z0-9_\-:.]{1,128}$Corpo della richiesta application/json
titleobbligatorioTitolo della voce, al massimo 2000 caratteri. Testo semplice; "<" e ">" non sono consentiti.
^[^<>]*$"Első tárgyalás elhalasztva"descriptionDettagli della voce. HTML formattato, sanificato lato server con il profilo della knowledge base.
locationDove è avvenuto (testo semplice, al massimo 255 caratteri); "<" e ">" non sono consentiti.
^[^<>]*$"Fővárosi Törvényszék, 215. tárgyaló"event_dateGiorno della voce, YYYY-MM-DD. Predefinito a oggi (fuso orario dello studio).
"2026-11-15"idempotency_keyStesso ruolo dell'header Idempotency-Key, per i client che non possono inviare header personalizzati. Lettere, cifre, _, -, : o ., al massimo 128 caratteri.
^[A-Za-z0-9_\-:.]{1,128}$"b8f1c2e0-6f7a-4d2e-9c1b-2a3d4e5f6a7b"Risposte
201
Creato.
dataobbligatorioCampi di data
id4521titleTitolo della voce. Testo semplice.
"Első tárgyalás elhalasztva"descriptionDettagli della voce come HTML formattato, sanificato lato server.
locationDove è avvenuto (testo semplice), ad es. un'aula di tribunale; può essere null.
event_dateGiorno della voce, YYYY-MM-DD. Flowyer registra solo la data, non l'ora del giorno.
user_idAutore (l'utente che ha creato la voce).
created_byNome visualizzato dell'autore.
last_editor_idUtente che ha modificato per ultimo la voce.
last_editorNome visualizzato dell'ultimo editor.
created_atupdated_atPassi questo a litigation.update come expected_updated_at.
created_via_apiPresente quando un agente esterno ha creato la voce tramite questa API.
Campi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduseratcreatedtrue
200
Replay idempotente: questo Idempotency-Key (o, senza chiave, una richiesta identica entro 120 secondi) ha già creato il record; viene restituito di nuovo, nulla di nuovo è stato creato.
dataobbligatorioCampi di data
id4521titleTitolo della voce. Testo semplice.
"Első tárgyalás elhalasztva"descriptionDettagli della voce come HTML formattato, sanificato lato server.
locationDove è avvenuto (testo semplice), ad es. un'aula di tribunale; può essere null.
event_dateGiorno della voce, YYYY-MM-DD. Flowyer registra solo la data, non l'ora del giorno.
user_idAutore (l'utente che ha creato la voce).
created_byNome visualizzato dell'autore.
last_editor_idUtente che ha modificato per ultimo la voce.
last_editorNome visualizzato dell'ultimo editor.
created_atupdated_atPassi questo a litigation.update come expected_updated_at.
created_via_apiPresente quando un agente esterno ha creato la voce tramite questa API.
Campi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduseratcreatedfalseidempotent_replaytrue
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente. replay_not_visible: questo Idempotency-Key (o, senza chiave, una richiesta identica) ha già creato il record (details.record_id), ma da allora è stato eliminato o non è visibile all'utente; nulla di nuovo è stato creato, non lo ricrei.
replay_not_visible: questo Idempotency-Key (o, senza chiave, una richiesta identica) ha già creato il record (details.record_id), ma da allora è stato eliminato o non è visibile all'utente; nulla di nuovo è stato creato, non lo ricrei.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
409
L'Idempotency-Key è stato usato per un altro tipo di risorsa (idempotency_key_reused), oppure, senza chiave, una richiesta identica è in fase di elaborazione in questo momento (duplicate_in_progress; riprovi a breve).
idempotency_key_reused), oppure, senza chiave, una richiesta identica è in fase di elaborazione in questo momento (duplicate_in_progress; riprovi a breve).
413
Il corpo della richiesta è troppo grande (request_too_large).
request_too_large).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl -X POST 'https://www.flowyer.it/api/agent/matters/1234/litigation' \
-H 'Authorization: Bearer flw_...' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: 7f3a9c21-1b2c-4d5e-8f90-0a1b2c3d4e5f' \
-d '{
"title": "Első tárgyalás elhalasztva",
"location": "Fővárosi Törvényszék, 215. tárgyaló",
"event_date": "2026-11-15"
}'
const response = await fetch("https://www.flowyer.it/api/agent/matters/1234/litigation", {
method: "POST",
headers: {
"Authorization": "Bearer flw_...",
"Content-Type": "application/json",
"Idempotency-Key": crypto.randomUUID(),
},
body: JSON.stringify({
"title": "Első tárgyalás elhalasztva",
"location": "Fővárosi Törvényszék, 215. tárgyaló",
"event_date": "2026-11-15"
}),
});
const result = await response.json();
import uuid
import requests
response = requests.post(
"https://www.flowyer.it/api/agent/matters/1234/litigation",
headers={
"Authorization": "Bearer flw_...",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"title": "Első tárgyalás elhalasztva",
"location": "Fővárosi Törvényszék, 215. tárgyaló",
"event_date": "2026-11-15",
},
timeout=30,
)
print(response.status_code, response.json())
{
"title": "Első tárgyalás elhalasztva",
"location": "Fővárosi Törvényszék, 215. tárgyaló",
"event_date": "2026-11-15"
}
Esempi di risposta
{
"data": {
"id": 4521,
"title": "Első tárgyalás elhalasztva",
"description": "string",
"location": "string",
"event_date": "2026-10-30",
"user_id": 1234,
"created_by": "string",
"last_editor_id": 1234,
"last_editor": "string",
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
}
},
"created": true
}
{
"data": {
"id": 4521,
"title": "Első tárgyalás elhalasztva",
"description": "string",
"location": "string",
"event_date": "2026-10-30",
"user_id": 1234,
"created_by": "string",
"last_editor_id": 1234,
"last_editor": "string",
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
}
},
"created": false,
"idempotent_replay": true
}
{
"error": "validation_failed",
"message": "The request is invalid. See \"details.fields\" for the field-level errors.",
"message_localized": "La richiesta non è valida. Gli errori per campo sono in \"details.fields\".",
"locale": "it",
"details": {
"fields": {
"title": [
"Il campo title è obbligatorio."
]
}
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Aggiorna la voce della cronologia processuale
/api/agent/litigation/{id}
Modifica una voce della cronologia processuale (pertörténet): titolo, descrizione, luogo o data dell'evento. Vengono scritti solo i campi che invia; la descrizione viene sanificata lato server. Passi expected_updated_at dalla sua ultima lettura; una modifica in conflitto risponde 409.
Parametri di percorso
idobbligatorioId del record da modificare.
Corpo della richiesta application/json
expected_updated_atIl valore updated_at dalla sua lettura più recente di questo record (obbligatorio ogni volta che il record ne ha uno). Se il record è cambiato da allora (un collega lo ha modificato), l'API risponde 409 e deve rileggere prima di riprovare. Un record legacy il cui updated_at è null accetta null.
titleNuovo titolo, al massimo 2000 caratteri (testo semplice; "<"/">" non consentiti). Lo ometta per mantenere quello corrente.
^[^<>]*$"Ítélethirdetés elhalasztva"descriptionNuovi dettagli (HTML formattato, sanificato). Li ometta per mantenere quelli correnti; null/vuoto li cancella.
locationNuovo luogo (testo semplice, al massimo 255 caratteri; "<"/">" non consentiti). Lo ometta per mantenerlo; null/vuoto lo cancella.
^[^<>]*$event_dateNuovo giorno dell'evento, YYYY-MM-DD. Lo ometta per mantenerlo; null lo cancella.
Risposte
200
Aggiornato.
dataobbligatorioCampi di data
id4521titleTitolo della voce. Testo semplice.
"Első tárgyalás elhalasztva"descriptionDettagli della voce come HTML formattato, sanificato lato server.
locationDove è avvenuto (testo semplice), ad es. un'aula di tribunale; può essere null.
event_dateGiorno della voce, YYYY-MM-DD. Flowyer registra solo la data, non l'ora del giorno.
user_idAutore (l'utente che ha creato la voce).
created_byNome visualizzato dell'autore.
last_editor_idUtente che ha modificato per ultimo la voce.
last_editorNome visualizzato dell'ultimo editor.
created_atupdated_atPassi questo a litigation.update come expected_updated_at.
created_via_apiPresente quando un agente esterno ha creato la voce tramite questa API.
Campi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduseratupdatedtrue
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
409
Il record è cambiato da quando lo ha letto (record_conflict: expected_updated_at non corrisponde più; lo rilegga e riprovi con il nuovo updated_at).
record_conflict: expected_updated_at non corrisponde più; lo rilegga e riprovi con il nuovo updated_at).
413
Il corpo della richiesta è troppo grande (request_too_large).
request_too_large).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl -X PATCH 'https://www.flowyer.it/api/agent/litigation/1234' \
-H 'Authorization: Bearer flw_...' \
-H 'Content-Type: application/json' \
-d '{
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"title": "Ítélethirdetés elhalasztva"
}'
const response = await fetch("https://www.flowyer.it/api/agent/litigation/1234", {
method: "PATCH",
headers: {
"Authorization": "Bearer flw_...",
"Content-Type": "application/json",
},
body: JSON.stringify({
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"title": "Ítélethirdetés elhalasztva"
}),
});
const result = await response.json();
import requests
response = requests.patch(
"https://www.flowyer.it/api/agent/litigation/1234",
headers={
"Authorization": "Bearer flw_...",
},
json={
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"title": "Ítélethirdetés elhalasztva",
},
timeout=30,
)
print(response.status_code, response.json())
{
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"title": "Ítélethirdetés elhalasztva"
}
Esempi di risposta
{
"data": {
"id": 4521,
"title": "Első tárgyalás elhalasztva",
"description": "string",
"location": "string",
"event_date": "2026-10-30",
"user_id": 1234,
"created_by": "string",
"last_editor_id": 1234,
"last_editor": "string",
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
}
},
"updated": true
}
{
"error": "record_conflict",
"message": "The record changed since you read it (someone edited it). Read it again and retry with the new updated_at.",
"message_localized": "Il record è cambiato dall'ultima lettura (qualcuno lo ha modificato). Rileggerlo e riprovare con il nuovo updated_at.",
"locale": "it",
"details": {
"current_updated_at": "2026-10-30T10:42:05+01:00",
"reason": "modified_since_read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Registro postale
Elenca il registro postale
/api/agent/mail-register
Elenca le voci del registro postale (Postakönyv) archiviate sulle pratiche che l'utente può vedere, prima le più recenti. Filtra per pratica, direzione, testo libero (oggetto/mittente/destinatario/numero di tracciamento) e intervallo di date. La posta delle pratiche archiviate è nascosta a meno che include_archived non sia true.
Parametri di query
matter_idSolo le voci di questa pratica (deve essere visibile all'utente).
1234directionSolo le voci in entrata (ricevute) o in uscita (inviate).
"incoming" "outgoing" qRicerca a testo libero su oggetto, mittente, destinatario, ricevente e numero di tracciamento (maiuscole/minuscole ignorate).
"Kúria"date_fromSolo le voci la cui data è a partire da questo giorno incluso (YYYY-MM-DD).
"2026-01-01"date_toSolo le voci la cui data è fino a questo giorno incluso (YYYY-MM-DD).
"2026-12-31"updated_sinceSolo le voci modificate a partire da questo momento (ISO 8601).
"2026-10-01T00:00:00+02:00"include_archivedIncludi le voci delle pratiche archiviate.
falselimitDimensione della pagina, 1-100. Valore predefinito 25.
2525offsetNumero di record da saltare. Usi offset + limit della pagina precedente per ottenere quella successiva; pagination.total è il conteggio totale.
00Risposte
200
OK.
dataobbligatorioCampi di data
idId della voce del registro postale (da usare con mail_register.get / .update).
4321matterLa pratica su cui è archiviata la voce.
Campi di matter
idcase_numberdirectionincoming = ricevuta, outgoing = inviata.
"incoming" "outgoing" dateData postale/di registrazione, YYYY-MM-DD (nessuna ora del giorno).
subjectsenderFeladó: il mittente (testo libero).
toCímzett: il destinatario (testo libero).
recipientPer una posta in entrata: il nome visualizzato del collega che l'ha ricevuta. Per una posta in uscita: il destinatario/ricevuto da a testo libero.
recipient_user_idImpostato solo per una posta in entrata il cui destinatario è un collega (un id utente); null per una posta in uscita.
electronicTrue quando l'elemento è stato registrato come elettronico (type_of_mail).
delivery_method_idId del metodo di consegna (mail_delivery_methods).
delivery_methodEtichetta localizzata del metodo di consegna (Posta, Cégkapu, Perkapu, ...), oppure il fallback elettronico/non elettronico per una riga legacy.
tracking_noAzonosító: numero di tracciamento.
folder_pathrecorded_by_user_idIl collega che ha registrato la voce.
recorded_bycreated_atupdated_atPassi questo a mail_register.update come expected_updated_at.
created_via_apiPresente quando un agente esterno ha creato la voce tramite questa API.
Campi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduseratpaginationobbligatorioCampi di pagination
limitobbligatoriooffsetobbligatoriototalobbligatorioNumero totale di record corrispondenti.
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl 'https://www.flowyer.it/api/agent/mail-register?matter_id=1234&q=K%C3%BAria&date_from=2026-01-01' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.it/api/agent/mail-register?matter_id=1234&q=K%C3%BAria&date_from=2026-01-01", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.it/api/agent/mail-register?matter_id=1234&q=K%C3%BAria&date_from=2026-01-01",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Esempi di risposta
{
"data": [
{
"id": 4321,
"matter": {
"id": 1234,
"case_number": "string"
},
"direction": "incoming",
"date": "2026-10-30",
"subject": "string",
"sender": "string",
"to": "string",
"recipient": "string",
"recipient_user_id": 1234,
"electronic": true,
"delivery_method_id": 1234,
"delivery_method": "string",
"tracking_no": "string",
"folder_path": "string",
"recorded_by_user_id": 1234,
"recorded_by": "string",
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
}
}
],
"pagination": {
"limit": 25,
"offset": 0,
"total": 1
}
}
{
"error": "scope_missing",
"message": "This API key does not have the \"mail_register:read\" permission. The permissions of an existing key cannot be changed, so the key owner needs to create a new key with this permission in Flowyer under Settings > API keys and use it in place of the old one.",
"message_localized": "Questa chiave API non ha il permesso \"mail_register:read\". I permessi di una chiave esistente non possono essere modificati, quindi il titolare della chiave deve creare in Flowyer, in Impostazioni > Chiavi API, una nuova chiave con questo permesso e usarla al posto di quella vecchia.",
"locale": "it",
"details": {
"required_scope": "mail_register:read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Ottieni la voce del registro postale
/api/agent/mail-register/{id}
Restituisce una voce del registro postale (Postakönyv) per id, con il suo updated_at (il token che mail_register.update accetta). Risponde 404 quando la voce non esiste o la sua pratica non è visibile all'utente.
Parametri di percorso
idobbligatorioId della voce del registro postale.
4321Risposte
200
OK.
dataobbligatorioCampi di data
idId della voce del registro postale (da usare con mail_register.get / .update).
4321matterLa pratica su cui è archiviata la voce.
Campi di matter
idcase_numberdirectionincoming = ricevuta, outgoing = inviata.
"incoming" "outgoing" dateData postale/di registrazione, YYYY-MM-DD (nessuna ora del giorno).
subjectsenderFeladó: il mittente (testo libero).
toCímzett: il destinatario (testo libero).
recipientPer una posta in entrata: il nome visualizzato del collega che l'ha ricevuta. Per una posta in uscita: il destinatario/ricevuto da a testo libero.
recipient_user_idImpostato solo per una posta in entrata il cui destinatario è un collega (un id utente); null per una posta in uscita.
electronicTrue quando l'elemento è stato registrato come elettronico (type_of_mail).
delivery_method_idId del metodo di consegna (mail_delivery_methods).
delivery_methodEtichetta localizzata del metodo di consegna (Posta, Cégkapu, Perkapu, ...), oppure il fallback elettronico/non elettronico per una riga legacy.
tracking_noAzonosító: numero di tracciamento.
folder_pathrecorded_by_user_idIl collega che ha registrato la voce.
recorded_bycreated_atupdated_atPassi questo a mail_register.update come expected_updated_at.
created_via_apiPresente quando un agente esterno ha creato la voce tramite questa API.
Campi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduserat
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl 'https://www.flowyer.it/api/agent/mail-register/4321' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.it/api/agent/mail-register/4321", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.it/api/agent/mail-register/4321",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Esempi di risposta
{
"data": {
"id": 4321,
"matter": {
"id": 1234,
"case_number": "string"
},
"direction": "incoming",
"date": "2026-10-30",
"subject": "string",
"sender": "string",
"to": "string",
"recipient": "string",
"recipient_user_id": 1234,
"electronic": true,
"delivery_method_id": 1234,
"delivery_method": "string",
"tracking_no": "string",
"folder_path": "string",
"recorded_by_user_id": 1234,
"recorded_by": "string",
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
}
}
}
{
"error": "not_found",
"message": "The record was not found, or it is not visible to the user who owns this API key.",
"message_localized": "Il record non è stato trovato oppure non è visibile al titolare di questa chiave API.",
"locale": "it",
"details": {
"record_type": "mail",
"record_id": 4321
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Crea una voce del registro postale
/api/agent/mail-register
Archivia una nuova voce del registro postale (Postakönyv) su una pratica. Usi recipient_user_id per una posta in entrata ricevuta da un collega, oppure recipient (testo libero) per una in uscita. delivery_method_id deve essere un metodo noto. Risponde 404 quando la pratica non è visibile.
Parametri di intestazione
Idempotency-KeyConsigliato a ogni creazione. Un valore univoco per operazione logica (ad es. un UUID). Lo stesso valore restituisce lo stesso record: riprovare con esso restituisce il record creato la prima volta invece di crearne un secondo. Valori diversi creano sempre record diversi. I client che non possono inviare header possono passare lo stesso valore nel campo del corpo idempotency_key. Lettere, cifre, _, -, : o ., al massimo 128 caratteri.
^[A-Za-z0-9_\-:.]{1,128}$Corpo della richiesta application/json
matter_idobbligatorioPratica a cui appartiene la voce (deve essere visibile).
1234directionobbligatorioincoming = ricevuta, outgoing = inviata.
"incoming" "outgoing" dateobbligatorioData postale/di registrazione, YYYY-MM-DD (nessuna ora del giorno).
"2026-11-03"subjectobbligatorioOggetto della corrispondenza. Testo semplice; "<" e ">" non sono consentiti.
^[^<>]*$"Fellebbezés a Kúriához"senderFeladó: il mittente (testo libero). Testo semplice; "<" e ">" non sono consentiti.
^[^<>]*$toCímzett: il destinatario (testo libero). Testo semplice; "<" e ">" non sono consentiti.
^[^<>]*$recipientPosta in uscita: il destinatario/ricevuto da a testo libero. Non consentito insieme a recipient_user_id. Testo semplice; "<" e ">" non sono consentiti.
^[^<>]*$recipient_user_idPosta in entrata: il collega che l'ha ricevuta (un id utente da colleagues.list), memorizzato come destinatario numerico. Non consentito insieme a recipient.
electronicSe l'elemento è elettronico (type_of_mail); indipendente dal metodo di consegna. Predefinito false.
falsedelivery_method_idId del metodo di consegna (mail_delivery_methods): ad es. 1 Posta, 4 Cégkapu, 7 Perkapu. 422 quando sconosciuto.
tracking_noAzonosító: numero di tracciamento. Testo semplice; "<" e ">" non sono consentiti.
^[^<>]*$folder_path^[^<>]*$idempotency_keyStesso ruolo dell'header Idempotency-Key, per i client che non possono inviare header personalizzati. Lettere, cifre, _, -, : o ., al massimo 128 caratteri.
^[A-Za-z0-9_\-:.]{1,128}$"b8f1c2e0-6f7a-4d2e-9c1b-2a3d4e5f6a7b"Risposte
201
Creato.
dataobbligatorioCampi di data
idId della voce del registro postale (da usare con mail_register.get / .update).
4321matterLa pratica su cui è archiviata la voce.
Campi di matter
idcase_numberdirectionincoming = ricevuta, outgoing = inviata.
"incoming" "outgoing" dateData postale/di registrazione, YYYY-MM-DD (nessuna ora del giorno).
subjectsenderFeladó: il mittente (testo libero).
toCímzett: il destinatario (testo libero).
recipientPer una posta in entrata: il nome visualizzato del collega che l'ha ricevuta. Per una posta in uscita: il destinatario/ricevuto da a testo libero.
recipient_user_idImpostato solo per una posta in entrata il cui destinatario è un collega (un id utente); null per una posta in uscita.
electronicTrue quando l'elemento è stato registrato come elettronico (type_of_mail).
delivery_method_idId del metodo di consegna (mail_delivery_methods).
delivery_methodEtichetta localizzata del metodo di consegna (Posta, Cégkapu, Perkapu, ...), oppure il fallback elettronico/non elettronico per una riga legacy.
tracking_noAzonosító: numero di tracciamento.
folder_pathrecorded_by_user_idIl collega che ha registrato la voce.
recorded_bycreated_atupdated_atPassi questo a mail_register.update come expected_updated_at.
created_via_apiPresente quando un agente esterno ha creato la voce tramite questa API.
Campi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduseratcreatedtrue
200
Replay idempotente: questo Idempotency-Key (o, senza chiave, una richiesta identica entro 120 secondi) ha già creato il record; viene restituito di nuovo, nulla di nuovo è stato creato.
dataobbligatorioCampi di data
idId della voce del registro postale (da usare con mail_register.get / .update).
4321matterLa pratica su cui è archiviata la voce.
Campi di matter
idcase_numberdirectionincoming = ricevuta, outgoing = inviata.
"incoming" "outgoing" dateData postale/di registrazione, YYYY-MM-DD (nessuna ora del giorno).
subjectsenderFeladó: il mittente (testo libero).
toCímzett: il destinatario (testo libero).
recipientPer una posta in entrata: il nome visualizzato del collega che l'ha ricevuta. Per una posta in uscita: il destinatario/ricevuto da a testo libero.
recipient_user_idImpostato solo per una posta in entrata il cui destinatario è un collega (un id utente); null per una posta in uscita.
electronicTrue quando l'elemento è stato registrato come elettronico (type_of_mail).
delivery_method_idId del metodo di consegna (mail_delivery_methods).
delivery_methodEtichetta localizzata del metodo di consegna (Posta, Cégkapu, Perkapu, ...), oppure il fallback elettronico/non elettronico per una riga legacy.
tracking_noAzonosító: numero di tracciamento.
folder_pathrecorded_by_user_idIl collega che ha registrato la voce.
recorded_bycreated_atupdated_atPassi questo a mail_register.update come expected_updated_at.
created_via_apiPresente quando un agente esterno ha creato la voce tramite questa API.
Campi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduseratcreatedfalseidempotent_replaytrue
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente. replay_not_visible: questo Idempotency-Key (o, senza chiave, una richiesta identica) ha già creato il record (details.record_id), ma da allora è stato eliminato o non è visibile all'utente; nulla di nuovo è stato creato, non lo ricrei.
replay_not_visible: questo Idempotency-Key (o, senza chiave, una richiesta identica) ha già creato il record (details.record_id), ma da allora è stato eliminato o non è visibile all'utente; nulla di nuovo è stato creato, non lo ricrei.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
409
L'Idempotency-Key è stato usato per un altro tipo di risorsa (idempotency_key_reused), oppure, senza chiave, una richiesta identica è in fase di elaborazione in questo momento (duplicate_in_progress; riprovi a breve).
idempotency_key_reused), oppure, senza chiave, una richiesta identica è in fase di elaborazione in questo momento (duplicate_in_progress; riprovi a breve).
413
Il corpo della richiesta è troppo grande (request_too_large).
request_too_large).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl -X POST 'https://www.flowyer.it/api/agent/mail-register' \
-H 'Authorization: Bearer flw_...' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: 7f3a9c21-1b2c-4d5e-8f90-0a1b2c3d4e5f' \
-d '{
"matter_id": 1234,
"direction": "incoming",
"date": "2026-11-03",
"subject": "Fellebbezés a Kúriához"
}'
const response = await fetch("https://www.flowyer.it/api/agent/mail-register", {
method: "POST",
headers: {
"Authorization": "Bearer flw_...",
"Content-Type": "application/json",
"Idempotency-Key": crypto.randomUUID(),
},
body: JSON.stringify({
"matter_id": 1234,
"direction": "incoming",
"date": "2026-11-03",
"subject": "Fellebbezés a Kúriához"
}),
});
const result = await response.json();
import uuid
import requests
response = requests.post(
"https://www.flowyer.it/api/agent/mail-register",
headers={
"Authorization": "Bearer flw_...",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"matter_id": 1234,
"direction": "incoming",
"date": "2026-11-03",
"subject": "Fellebbezés a Kúriához",
},
timeout=30,
)
print(response.status_code, response.json())
{
"matter_id": 1234,
"direction": "incoming",
"date": "2026-11-03",
"subject": "Fellebbezés a Kúriához"
}
Esempi di risposta
{
"data": {
"id": 4321,
"matter": {
"id": 1234,
"case_number": "string"
},
"direction": "incoming",
"date": "2026-10-30",
"subject": "string",
"sender": "string",
"to": "string",
"recipient": "string",
"recipient_user_id": 1234,
"electronic": true,
"delivery_method_id": 1234,
"delivery_method": "string",
"tracking_no": "string",
"folder_path": "string",
"recorded_by_user_id": 1234,
"recorded_by": "string",
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
}
},
"created": true
}
{
"data": {
"id": 4321,
"matter": {
"id": 1234,
"case_number": "string"
},
"direction": "incoming",
"date": "2026-10-30",
"subject": "string",
"sender": "string",
"to": "string",
"recipient": "string",
"recipient_user_id": 1234,
"electronic": true,
"delivery_method_id": 1234,
"delivery_method": "string",
"tracking_no": "string",
"folder_path": "string",
"recorded_by_user_id": 1234,
"recorded_by": "string",
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
}
},
"created": false,
"idempotent_replay": true
}
{
"error": "validation_failed",
"message": "The request is invalid. See \"details.fields\" for the field-level errors.",
"message_localized": "La richiesta non è valida. Gli errori per campo sono in \"details.fields\".",
"locale": "it",
"details": {
"fields": {
"matter_id": [
"Il campo matter id è obbligatorio."
]
}
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Aggiorna la voce del registro postale
/api/agent/mail-register/{id}
Aggiorna una voce del registro postale (Postakönyv); vengono modificati solo i campi che invia. La voce rimane sulla sua pratica. Passi expected_updated_at dalla sua ultima lettura; una modifica in conflitto risponde 409. Risponde 404 quando la voce non è visibile.
Parametri di percorso
idobbligatorioId del record da modificare.
Corpo della richiesta application/json
expected_updated_atIl valore updated_at dalla sua lettura più recente di questo record (obbligatorio ogni volta che il record ne ha uno). Se il record è cambiato da allora (un collega lo ha modificato), l'API risponde 409 e deve rileggere prima di riprovare. Un record legacy il cui updated_at è null accetta null.
directionincoming = ricevuta, outgoing = inviata.
"incoming" "outgoing" dateData postale/di registrazione, YYYY-MM-DD.
subjectOggetto. Testo semplice; "<" e ">" non sono consentiti.
^[^<>]*$senderFeladó: il mittente (testo libero). Testo semplice; "<" e ">" non sono consentiti.
^[^<>]*$toCímzett: il destinatario (testo libero). Testo semplice; "<" e ">" non sono consentiti.
^[^<>]*$recipientPosta in uscita: il destinatario a testo libero. Non consentito insieme a recipient_user_id. Testo semplice; "<" e ">" non sono consentiti.
^[^<>]*$recipient_user_idPosta in entrata: il collega ricevente (un id utente), memorizzato come destinatario numerico. Non consentito insieme a recipient.
electronicSe l'elemento è elettronico (type_of_mail).
delivery_method_idId del metodo di consegna (mail_delivery_methods); 422 quando sconosciuto.
tracking_noAzonosító: numero di tracciamento. Testo semplice; "<" e ">" non sono consentiti.
^[^<>]*$folder_path^[^<>]*$Risposte
200
Aggiornato.
dataobbligatorioCampi di data
idId della voce del registro postale (da usare con mail_register.get / .update).
4321matterLa pratica su cui è archiviata la voce.
Campi di matter
idcase_numberdirectionincoming = ricevuta, outgoing = inviata.
"incoming" "outgoing" dateData postale/di registrazione, YYYY-MM-DD (nessuna ora del giorno).
subjectsenderFeladó: il mittente (testo libero).
toCímzett: il destinatario (testo libero).
recipientPer una posta in entrata: il nome visualizzato del collega che l'ha ricevuta. Per una posta in uscita: il destinatario/ricevuto da a testo libero.
recipient_user_idImpostato solo per una posta in entrata il cui destinatario è un collega (un id utente); null per una posta in uscita.
electronicTrue quando l'elemento è stato registrato come elettronico (type_of_mail).
delivery_method_idId del metodo di consegna (mail_delivery_methods).
delivery_methodEtichetta localizzata del metodo di consegna (Posta, Cégkapu, Perkapu, ...), oppure il fallback elettronico/non elettronico per una riga legacy.
tracking_noAzonosító: numero di tracciamento.
folder_pathrecorded_by_user_idIl collega che ha registrato la voce.
recorded_bycreated_atupdated_atPassi questo a mail_register.update come expected_updated_at.
created_via_apiPresente quando un agente esterno ha creato la voce tramite questa API.
Campi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduseratupdatedtrue
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
409
Il record è cambiato da quando lo ha letto (record_conflict: expected_updated_at non corrisponde più; lo rilegga e riprovi con il nuovo updated_at).
record_conflict: expected_updated_at non corrisponde più; lo rilegga e riprovi con il nuovo updated_at).
413
Il corpo della richiesta è troppo grande (request_too_large).
request_too_large).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl -X PATCH 'https://www.flowyer.it/api/agent/mail-register/1234' \
-H 'Authorization: Bearer flw_...' \
-H 'Content-Type: application/json' \
-d '{
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"direction": "incoming"
}'
const response = await fetch("https://www.flowyer.it/api/agent/mail-register/1234", {
method: "PATCH",
headers: {
"Authorization": "Bearer flw_...",
"Content-Type": "application/json",
},
body: JSON.stringify({
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"direction": "incoming"
}),
});
const result = await response.json();
import requests
response = requests.patch(
"https://www.flowyer.it/api/agent/mail-register/1234",
headers={
"Authorization": "Bearer flw_...",
},
json={
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"direction": "incoming",
},
timeout=30,
)
print(response.status_code, response.json())
{
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"direction": "incoming"
}
Esempi di risposta
{
"data": {
"id": 4321,
"matter": {
"id": 1234,
"case_number": "string"
},
"direction": "incoming",
"date": "2026-10-30",
"subject": "string",
"sender": "string",
"to": "string",
"recipient": "string",
"recipient_user_id": 1234,
"electronic": true,
"delivery_method_id": 1234,
"delivery_method": "string",
"tracking_no": "string",
"folder_path": "string",
"recorded_by_user_id": 1234,
"recorded_by": "string",
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
}
},
"updated": true
}
{
"error": "record_conflict",
"message": "The record changed since you read it (someone edited it). Read it again and retry with the new updated_at.",
"message_localized": "Il record è cambiato dall'ultima lettura (qualcuno lo ha modificato). Rileggerlo e riprovare con il nuovo updated_at.",
"locale": "it",
"details": {
"current_updated_at": "2026-10-30T10:42:05+01:00",
"reason": "modified_since_read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Commenti
Elenca i commenti della pratica
/api/agent/matters/{id}/comments
Elenca i commenti di una pratica, prima i più vecchi: id, autore, corpo (HTML formattato) e il parent_id di una risposta. Piatto, non annidato - ricostruisca i thread di un solo livello da parent_id. Passi top_level_only per escludere le risposte. Risponde 404 quando la pratica non è visibile all'utente.
Parametri di percorso
idobbligatorioId della pratica (deve essere visibile).
1234Parametri di query
top_level_onlySolo i commenti di primo livello (escludi le risposte). Predefinito false.
falselimitDimensione della pagina, 1-100. Valore predefinito 25.
2525offsetNumero di record da saltare. Usi offset + limit della pagina precedente per ottenere quella successiva; pagination.total è il conteggio totale.
00Risposte
200
OK.
dataobbligatorioCampi di data
id9876matter_idLa pratica (= case_id) a cui appartiene il commento.
parent_idIl commento di primo livello a cui questo risponde; null per un commento di primo livello. Le risposte sono di un solo livello di profondità.
author_user_idId utente dell'autore (null per un'importazione legacy).
author_nameNome visualizzato dell'autore, oppure null.
bodyIl commento come memorizzato: HTML formattato, già ripulito con HTMLPurifier per i commenti scritti tramite questa API.
created_atQuando il commento è stato pubblicato, ISO 8601 nel fuso dello studio.
updated_atToken di blocco ottimistico: lo passi a comments.update come expected_updated_at. Non è un orario di visualizzazione; null per un commento legacy che non ne ha uno.
editedTrue quando il commento è stato modificato dopo la pubblicazione.
paginationobbligatorioCampi di pagination
limitobbligatoriooffsetobbligatoriototalobbligatorioNumero totale di record corrispondenti.
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl 'https://www.flowyer.it/api/agent/matters/1234/comments?limit=25' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.it/api/agent/matters/1234/comments?limit=25", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.it/api/agent/matters/1234/comments?limit=25",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Esempi di risposta
{
"data": [
{
"id": 9876,
"matter_id": 1234,
"parent_id": 1234,
"author_user_id": 1234,
"author_name": "string",
"body": "string",
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"edited": true
}
],
"pagination": {
"limit": 25,
"offset": 0,
"total": 1
}
}
{
"error": "matter_not_visible",
"message": "The matter 1234 does not exist, is archived, or is not visible to the user who owns this API key.",
"message_localized": "La pratica 1234 non esiste, è archiviata oppure non è visibile al titolare di questa chiave API.",
"locale": "it",
"details": {
"matter_id": 1234
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Pubblica un commento della pratica
/api/agent/matters/{id}/comments
Pubblica un commento su una pratica, oppure una risposta di un solo livello (parent_id = un commento di PRIMO LIVELLO della STESSA pratica). Il corpo è HTML formattato, sanificato lato server prima della memorizzazione. Risponde 404 quando la pratica non è visibile, 422 quando parent_id non è un commento di primo livello della pratica.
Parametri di percorso
idobbligatorioId della pratica (deve essere visibile).
1234Parametri di intestazione
Idempotency-KeyConsigliato a ogni creazione. Un valore univoco per operazione logica (ad es. un UUID). Lo stesso valore restituisce lo stesso record: riprovare con esso restituisce il record creato la prima volta invece di crearne un secondo. Valori diversi creano sempre record diversi. I client che non possono inviare header possono passare lo stesso valore nel campo del corpo idempotency_key. Lettere, cifre, _, -, : o ., al massimo 128 caratteri.
^[A-Za-z0-9_\-:.]{1,128}$Corpo della richiesta application/json
bodyobbligatorioIl commento, HTML formattato (come lo produce TinyMCE). Ripulito lato server con HTMLPurifier prima della memorizzazione. Al massimo 100000 caratteri.
"<p>Egyetértek, a határidő tartható.</p>"parent_idRispondi a questo commento di PRIMO LIVELLO della STESSA pratica (da comments.list, parent_id = null); ometta per un nuovo commento di primo livello.
idempotency_keyStesso ruolo dell'header Idempotency-Key, per i client che non possono inviare header personalizzati. Lettere, cifre, _, -, : o ., al massimo 128 caratteri.
^[A-Za-z0-9_\-:.]{1,128}$"b8f1c2e0-6f7a-4d2e-9c1b-2a3d4e5f6a7b"Risposte
201
Creato.
dataobbligatorioCampi di data
id9876matter_idLa pratica (= case_id) a cui appartiene il commento.
parent_idIl commento di primo livello a cui questo risponde; null per un commento di primo livello. Le risposte sono di un solo livello di profondità.
author_user_idId utente dell'autore (null per un'importazione legacy).
author_nameNome visualizzato dell'autore, oppure null.
bodyIl commento come memorizzato: HTML formattato, già ripulito con HTMLPurifier per i commenti scritti tramite questa API.
created_atQuando il commento è stato pubblicato, ISO 8601 nel fuso dello studio.
updated_atToken di blocco ottimistico: lo passi a comments.update come expected_updated_at. Non è un orario di visualizzazione; null per un commento legacy che non ne ha uno.
editedTrue quando il commento è stato modificato dopo la pubblicazione.
createdtrue
200
Replay idempotente: questo Idempotency-Key (o, senza chiave, una richiesta identica entro 120 secondi) ha già creato il record; viene restituito di nuovo, nulla di nuovo è stato creato.
dataobbligatorioCampi di data
id9876matter_idLa pratica (= case_id) a cui appartiene il commento.
parent_idIl commento di primo livello a cui questo risponde; null per un commento di primo livello. Le risposte sono di un solo livello di profondità.
author_user_idId utente dell'autore (null per un'importazione legacy).
author_nameNome visualizzato dell'autore, oppure null.
bodyIl commento come memorizzato: HTML formattato, già ripulito con HTMLPurifier per i commenti scritti tramite questa API.
created_atQuando il commento è stato pubblicato, ISO 8601 nel fuso dello studio.
updated_atToken di blocco ottimistico: lo passi a comments.update come expected_updated_at. Non è un orario di visualizzazione; null per un commento legacy che non ne ha uno.
editedTrue quando il commento è stato modificato dopo la pubblicazione.
createdfalseidempotent_replaytrue
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente. replay_not_visible: questo Idempotency-Key (o, senza chiave, una richiesta identica) ha già creato il record (details.record_id), ma da allora è stato eliminato o non è visibile all'utente; nulla di nuovo è stato creato, non lo ricrei.
replay_not_visible: questo Idempotency-Key (o, senza chiave, una richiesta identica) ha già creato il record (details.record_id), ma da allora è stato eliminato o non è visibile all'utente; nulla di nuovo è stato creato, non lo ricrei.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
409
L'Idempotency-Key è stato usato per un altro tipo di risorsa (idempotency_key_reused), oppure, senza chiave, una richiesta identica è in fase di elaborazione in questo momento (duplicate_in_progress; riprovi a breve).
idempotency_key_reused), oppure, senza chiave, una richiesta identica è in fase di elaborazione in questo momento (duplicate_in_progress; riprovi a breve).
413
Il corpo della richiesta è troppo grande (request_too_large).
request_too_large).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl -X POST 'https://www.flowyer.it/api/agent/matters/1234/comments' \
-H 'Authorization: Bearer flw_...' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: 7f3a9c21-1b2c-4d5e-8f90-0a1b2c3d4e5f' \
-d '{
"body": "<p>Egyetértek, a határidő tartható.</p>"
}'
const response = await fetch("https://www.flowyer.it/api/agent/matters/1234/comments", {
method: "POST",
headers: {
"Authorization": "Bearer flw_...",
"Content-Type": "application/json",
"Idempotency-Key": crypto.randomUUID(),
},
body: JSON.stringify({
"body": "<p>Egyetértek, a határidő tartható.</p>"
}),
});
const result = await response.json();
import uuid
import requests
response = requests.post(
"https://www.flowyer.it/api/agent/matters/1234/comments",
headers={
"Authorization": "Bearer flw_...",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"body": "<p>Egyetértek, a határidő tartható.</p>",
},
timeout=30,
)
print(response.status_code, response.json())
{
"body": "<p>Egyetértek, a határidő tartható.</p>"
}
Esempi di risposta
{
"data": {
"id": 9876,
"matter_id": 1234,
"parent_id": 1234,
"author_user_id": 1234,
"author_name": "string",
"body": "string",
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"edited": true
},
"created": true
}
{
"data": {
"id": 9876,
"matter_id": 1234,
"parent_id": 1234,
"author_user_id": 1234,
"author_name": "string",
"body": "string",
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"edited": true
},
"created": false,
"idempotent_replay": true
}
{
"error": "validation_failed",
"message": "The request is invalid. See \"details.fields\" for the field-level errors.",
"message_localized": "La richiesta non è valida. Gli errori per campo sono in \"details.fields\".",
"locale": "it",
"details": {
"fields": {
"body": [
"Il campo body è obbligatorio."
]
}
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Modifica un proprio commento della pratica
/api/agent/comments/{id}
Modifica uno dei SUOI commenti (solo il suo corpo; HTML formattato, sanificato lato server prima della memorizzazione). Passi expected_updated_at dalla sua ultima lettura; una modifica in conflitto risponde 409. Risponde 404 per un commento che non è suo o su una pratica che non può vedere.
Parametri di percorso
idobbligatorioId del record da modificare.
Corpo della richiesta application/json
expected_updated_atIl valore updated_at dalla sua lettura più recente di questo record (obbligatorio ogni volta che il record ne ha uno). Se il record è cambiato da allora (un collega lo ha modificato), l'API risponde 409 e deve rileggere prima di riprovare. Un record legacy il cui updated_at è null accetta null.
bodyobbligatorioNuovo corpo del commento, HTML formattato (come lo produce TinyMCE). Ripulito lato server con HTMLPurifier prima della memorizzazione. Al massimo 100000 caratteri.
"<p>Pontosítás: a határidő november 15.</p>"Risposte
200
Aggiornato.
dataobbligatorioCampi di data
id9876matter_idLa pratica (= case_id) a cui appartiene il commento.
parent_idIl commento di primo livello a cui questo risponde; null per un commento di primo livello. Le risposte sono di un solo livello di profondità.
author_user_idId utente dell'autore (null per un'importazione legacy).
author_nameNome visualizzato dell'autore, oppure null.
bodyIl commento come memorizzato: HTML formattato, già ripulito con HTMLPurifier per i commenti scritti tramite questa API.
created_atQuando il commento è stato pubblicato, ISO 8601 nel fuso dello studio.
updated_atToken di blocco ottimistico: lo passi a comments.update come expected_updated_at. Non è un orario di visualizzazione; null per un commento legacy che non ne ha uno.
editedTrue quando il commento è stato modificato dopo la pubblicazione.
updatedtrue
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
409
Il record è cambiato da quando lo ha letto (record_conflict: expected_updated_at non corrisponde più; lo rilegga e riprovi con il nuovo updated_at).
record_conflict: expected_updated_at non corrisponde più; lo rilegga e riprovi con il nuovo updated_at).
413
Il corpo della richiesta è troppo grande (request_too_large).
request_too_large).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl -X PATCH 'https://www.flowyer.it/api/agent/comments/1234' \
-H 'Authorization: Bearer flw_...' \
-H 'Content-Type: application/json' \
-d '{
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"body": "<p>Pontosítás: a határidő november 15.</p>"
}'
const response = await fetch("https://www.flowyer.it/api/agent/comments/1234", {
method: "PATCH",
headers: {
"Authorization": "Bearer flw_...",
"Content-Type": "application/json",
},
body: JSON.stringify({
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"body": "<p>Pontosítás: a határidő november 15.</p>"
}),
});
const result = await response.json();
import requests
response = requests.patch(
"https://www.flowyer.it/api/agent/comments/1234",
headers={
"Authorization": "Bearer flw_...",
},
json={
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"body": "<p>Pontosítás: a határidő november 15.</p>",
},
timeout=30,
)
print(response.status_code, response.json())
{
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"body": "<p>Pontosítás: a határidő november 15.</p>"
}
Esempi di risposta
{
"data": {
"id": 9876,
"matter_id": 1234,
"parent_id": 1234,
"author_user_id": 1234,
"author_name": "string",
"body": "string",
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"edited": true
},
"updated": true
}
{
"error": "record_conflict",
"message": "The record changed since you read it (someone edited it). Read it again and retry with the new updated_at.",
"message_localized": "Il record è cambiato dall'ultima lettura (qualcuno lo ha modificato). Rileggerlo e riprovare con il nuovo updated_at.",
"locale": "it",
"details": {
"current_updated_at": "2026-10-30T10:42:05+01:00",
"reason": "modified_since_read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Udienze
Elenca le udienze della pratica
/api/agent/matters/{id}/trials
Elenca le udienze (tárgyalások) di una pratica: data, tribunale, luogo, i colleghi presenti e il giudice, prima le più recenti. Facoltativamente filtrate per un intervallo di giorni da/a o per updated_since. Risponde 404 quando la pratica non è visibile all'utente.
Parametri di percorso
idobbligatorioId della pratica.
1234Parametri di query
fromSolo le udienze a partire da questo giorno incluso (YYYY-MM-DD), nel fuso orario dello studio.
"2026-01-01"toSolo le udienze fino a questo giorno incluso (YYYY-MM-DD), nel fuso orario dello studio.
"2026-12-31"updated_sinceSolo le udienze modificate a partire da questo momento ISO 8601.
limitDimensione della pagina, 1-100. Valore predefinito 25.
2525offsetNumero di record da saltare. Usi offset + limit della pagina precedente per ottenere quella successiva; pagination.total è il conteggio totale.
00Risposte
200
OK.
dataobbligatorioCampi di data
id4321matterLa pratica (causa) a cui appartiene l'udienza.
Campi di matter
idcase_numberdateData e ora dell'udienza, ISO 8601 nel fuso orario dello studio. È memorizzata in UTC, quindi confronti gli istanti invece del testo dell'ora di parete.
"2026-03-02T09:00:00+01:00"participationSe è richiesta la presenza di un collega: "required", "not_required", oppure null quando non impostato.
"required" "not_required" courtIl tribunale dell'udienza, risolto dal registro condiviso dei tribunali; null quando nessun tribunale è impostato.
Campi di court
idnamecityzipaddresssourceSempre "registry": il tribunale è un riferimento al registro condiviso dei tribunali (courts.list), non testo libero.
placeAula o luogo dell'udienza. Testo semplice.
name_of_the_judgeNome del giudice. Testo semplice.
notesNote a testo libero sull'udienza. Testo semplice.
responsiblesColleghi che partecipano all'udienza (id da colleagues.list).
Campi di responsibles
user_idnamerecorded_byIl collega che ha registrato l'udienza.
Campi di recorded_by
user_idnamecreated_atupdated_atPassi questo a trials.update come expected_updated_at.
created_via_apiPresente quando un agente esterno ha creato il record tramite questa API.
Campi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduseratpaginationobbligatorioCampi di pagination
limitobbligatoriooffsetobbligatoriototalobbligatorioNumero totale di record corrispondenti.
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl 'https://www.flowyer.it/api/agent/matters/1234/trials?from=2026-01-01&to=2026-12-31&limit=25' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.it/api/agent/matters/1234/trials?from=2026-01-01&to=2026-12-31&limit=25", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.it/api/agent/matters/1234/trials?from=2026-01-01&to=2026-12-31&limit=25",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Esempi di risposta
{
"data": [
{
"id": 4321,
"matter": {
"id": 1234,
"case_number": "string"
},
"date": "2026-03-02T09:00:00+01:00",
"participation": "required",
"court": {
"id": 1234,
"name": "string",
"city": "string",
"zip": "string",
"address": "string",
"source": "string"
},
"place": "string",
"name_of_the_judge": "string",
"notes": "string",
"responsibles": [
{
"user_id": 1234,
"name": "string"
}
],
"recorded_by": {
"user_id": 1234,
"name": "string"
},
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
}
}
],
"pagination": {
"limit": 25,
"offset": 0,
"total": 1
}
}
{
"error": "matter_not_visible",
"message": "The matter 1234 does not exist, is archived, or is not visible to the user who owns this API key.",
"message_localized": "La pratica 1234 non esiste, è archiviata oppure non è visibile al titolare di questa chiave API.",
"locale": "it",
"details": {
"matter_id": 1234
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Ottieni l'udienza
/api/agent/trials/{id}
Restituisce un'udienza (tárgyalás) con la sua pratica, il tribunale, i colleghi presenti e il token di blocco updated_at per trials.update. Risponde 404 quando l'udienza non esiste o l'utente non può vedere la sua pratica.
Parametri di percorso
idobbligatorioId dell'udienza.
4321Risposte
200
OK.
dataobbligatorioCampi di data
id4321matterLa pratica (causa) a cui appartiene l'udienza.
Campi di matter
idcase_numberdateData e ora dell'udienza, ISO 8601 nel fuso orario dello studio. È memorizzata in UTC, quindi confronti gli istanti invece del testo dell'ora di parete.
"2026-03-02T09:00:00+01:00"participationSe è richiesta la presenza di un collega: "required", "not_required", oppure null quando non impostato.
"required" "not_required" courtIl tribunale dell'udienza, risolto dal registro condiviso dei tribunali; null quando nessun tribunale è impostato.
Campi di court
idnamecityzipaddresssourceSempre "registry": il tribunale è un riferimento al registro condiviso dei tribunali (courts.list), non testo libero.
placeAula o luogo dell'udienza. Testo semplice.
name_of_the_judgeNome del giudice. Testo semplice.
notesNote a testo libero sull'udienza. Testo semplice.
responsiblesColleghi che partecipano all'udienza (id da colleagues.list).
Campi di responsibles
user_idnamerecorded_byIl collega che ha registrato l'udienza.
Campi di recorded_by
user_idnamecreated_atupdated_atPassi questo a trials.update come expected_updated_at.
created_via_apiPresente quando un agente esterno ha creato il record tramite questa API.
Campi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduserat
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl 'https://www.flowyer.it/api/agent/trials/4321' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.it/api/agent/trials/4321", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.it/api/agent/trials/4321",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Esempi di risposta
{
"data": {
"id": 4321,
"matter": {
"id": 1234,
"case_number": "string"
},
"date": "2026-03-02T09:00:00+01:00",
"participation": "required",
"court": {
"id": 1234,
"name": "string",
"city": "string",
"zip": "string",
"address": "string",
"source": "string"
},
"place": "string",
"name_of_the_judge": "string",
"notes": "string",
"responsibles": [
{
"user_id": 1234,
"name": "string"
}
],
"recorded_by": {
"user_id": 1234,
"name": "string"
},
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
}
}
}
{
"error": "not_found",
"message": "The record was not found, or it is not visible to the user who owns this API key.",
"message_localized": "Il record non è stato trovato oppure non è visibile al titolare di questa chiave API.",
"locale": "it",
"details": {
"record_type": "trial",
"record_id": 4321
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Crea un'udienza
/api/agent/matters/{id}/trials
Registra un'udienza (tárgyalás) su una pratica: ora, un tribunale facoltativo (court_id da courts.list), l'aula, il giudice, le note e i colleghi presenti. La pratica deve essere visibile e non archiviata; i partecipanti vengono notificati. Un orario senza offset viene letto nel fuso dello studio.
Parametri di percorso
idobbligatorioPratica a cui appartiene l'udienza (deve essere visibile e non archiviata).
1234Parametri di intestazione
Idempotency-KeyConsigliato a ogni creazione. Un valore univoco per operazione logica (ad es. un UUID). Lo stesso valore restituisce lo stesso record: riprovare con esso restituisce il record creato la prima volta invece di crearne un secondo. Valori diversi creano sempre record diversi. I client che non possono inviare header possono passare lo stesso valore nel campo del corpo idempotency_key. Lettere, cifre, _, -, : o ., al massimo 128 caratteri.
^[A-Za-z0-9_\-:.]{1,128}$Corpo della richiesta application/json
dateobbligatorioData e ora dell'udienza, ISO 8601. Con un offset viene rispettato; senza, viene letto nel fuso orario dello studio. Memorizzato in UTC.
"2026-03-02T09:00:00+01:00"court_idTribunale dell'udienza: un id da courts.list (il registro condiviso dei tribunali). Ometta quando il tribunale non è noto.
42participationSe è richiesta la presenza di un collega. Ometta per lasciarla non impostata.
"required" "not_required" placeAula o luogo dell'udienza. Testo semplice; "<" e ">" non sono consentiti.
^[^<>]*$"II. emelet 205."name_of_the_judgeNome del giudice. Testo semplice; "<" e ">" non sono consentiti.
^[^<>]*$notesNote a testo libero sull'udienza. Testo semplice; "<" e ">" non sono consentiti.
^[^<>]*$responsible_user_idsId utente dei colleghi (da colleagues.list) che partecipano all'udienza.
idempotency_keyStesso ruolo dell'header Idempotency-Key, per i client che non possono inviare header personalizzati. Lettere, cifre, _, -, : o ., al massimo 128 caratteri.
^[A-Za-z0-9_\-:.]{1,128}$"b8f1c2e0-6f7a-4d2e-9c1b-2a3d4e5f6a7b"Risposte
201
Creato.
dataobbligatorioCampi di data
id4321matterLa pratica (causa) a cui appartiene l'udienza.
Campi di matter
idcase_numberdateData e ora dell'udienza, ISO 8601 nel fuso orario dello studio. È memorizzata in UTC, quindi confronti gli istanti invece del testo dell'ora di parete.
"2026-03-02T09:00:00+01:00"participationSe è richiesta la presenza di un collega: "required", "not_required", oppure null quando non impostato.
"required" "not_required" courtIl tribunale dell'udienza, risolto dal registro condiviso dei tribunali; null quando nessun tribunale è impostato.
Campi di court
idnamecityzipaddresssourceSempre "registry": il tribunale è un riferimento al registro condiviso dei tribunali (courts.list), non testo libero.
placeAula o luogo dell'udienza. Testo semplice.
name_of_the_judgeNome del giudice. Testo semplice.
notesNote a testo libero sull'udienza. Testo semplice.
responsiblesColleghi che partecipano all'udienza (id da colleagues.list).
Campi di responsibles
user_idnamerecorded_byIl collega che ha registrato l'udienza.
Campi di recorded_by
user_idnamecreated_atupdated_atPassi questo a trials.update come expected_updated_at.
created_via_apiPresente quando un agente esterno ha creato il record tramite questa API.
Campi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduseratcreatedtrue
200
Replay idempotente: questo Idempotency-Key (o, senza chiave, una richiesta identica entro 120 secondi) ha già creato il record; viene restituito di nuovo, nulla di nuovo è stato creato.
dataobbligatorioCampi di data
id4321matterLa pratica (causa) a cui appartiene l'udienza.
Campi di matter
idcase_numberdateData e ora dell'udienza, ISO 8601 nel fuso orario dello studio. È memorizzata in UTC, quindi confronti gli istanti invece del testo dell'ora di parete.
"2026-03-02T09:00:00+01:00"participationSe è richiesta la presenza di un collega: "required", "not_required", oppure null quando non impostato.
"required" "not_required" courtIl tribunale dell'udienza, risolto dal registro condiviso dei tribunali; null quando nessun tribunale è impostato.
Campi di court
idnamecityzipaddresssourceSempre "registry": il tribunale è un riferimento al registro condiviso dei tribunali (courts.list), non testo libero.
placeAula o luogo dell'udienza. Testo semplice.
name_of_the_judgeNome del giudice. Testo semplice.
notesNote a testo libero sull'udienza. Testo semplice.
responsiblesColleghi che partecipano all'udienza (id da colleagues.list).
Campi di responsibles
user_idnamerecorded_byIl collega che ha registrato l'udienza.
Campi di recorded_by
user_idnamecreated_atupdated_atPassi questo a trials.update come expected_updated_at.
created_via_apiPresente quando un agente esterno ha creato il record tramite questa API.
Campi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduseratcreatedfalseidempotent_replaytrue
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente. replay_not_visible: questo Idempotency-Key (o, senza chiave, una richiesta identica) ha già creato il record (details.record_id), ma da allora è stato eliminato o non è visibile all'utente; nulla di nuovo è stato creato, non lo ricrei.
replay_not_visible: questo Idempotency-Key (o, senza chiave, una richiesta identica) ha già creato il record (details.record_id), ma da allora è stato eliminato o non è visibile all'utente; nulla di nuovo è stato creato, non lo ricrei.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
409
L'Idempotency-Key è stato usato per un altro tipo di risorsa (idempotency_key_reused), oppure, senza chiave, una richiesta identica è in fase di elaborazione in questo momento (duplicate_in_progress; riprovi a breve).
idempotency_key_reused), oppure, senza chiave, una richiesta identica è in fase di elaborazione in questo momento (duplicate_in_progress; riprovi a breve).
413
Il corpo della richiesta è troppo grande (request_too_large).
request_too_large).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl -X POST 'https://www.flowyer.it/api/agent/matters/1234/trials' \
-H 'Authorization: Bearer flw_...' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: 7f3a9c21-1b2c-4d5e-8f90-0a1b2c3d4e5f' \
-d '{
"date": "2026-03-02T09:00:00+01:00",
"court_id": 42,
"place": "II. emelet 205."
}'
const response = await fetch("https://www.flowyer.it/api/agent/matters/1234/trials", {
method: "POST",
headers: {
"Authorization": "Bearer flw_...",
"Content-Type": "application/json",
"Idempotency-Key": crypto.randomUUID(),
},
body: JSON.stringify({
"date": "2026-03-02T09:00:00+01:00",
"court_id": 42,
"place": "II. emelet 205."
}),
});
const result = await response.json();
import uuid
import requests
response = requests.post(
"https://www.flowyer.it/api/agent/matters/1234/trials",
headers={
"Authorization": "Bearer flw_...",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"date": "2026-03-02T09:00:00+01:00",
"court_id": 42,
"place": "II. emelet 205.",
},
timeout=30,
)
print(response.status_code, response.json())
{
"date": "2026-03-02T09:00:00+01:00",
"court_id": 42,
"place": "II. emelet 205."
}
Esempi di risposta
{
"data": {
"id": 4321,
"matter": {
"id": 1234,
"case_number": "string"
},
"date": "2026-03-02T09:00:00+01:00",
"participation": "required",
"court": {
"id": 1234,
"name": "string",
"city": "string",
"zip": "string",
"address": "string",
"source": "string"
},
"place": "string",
"name_of_the_judge": "string",
"notes": "string",
"responsibles": [
{
"user_id": 1234,
"name": "string"
}
],
"recorded_by": {
"user_id": 1234,
"name": "string"
},
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
}
},
"created": true
}
{
"data": {
"id": 4321,
"matter": {
"id": 1234,
"case_number": "string"
},
"date": "2026-03-02T09:00:00+01:00",
"participation": "required",
"court": {
"id": 1234,
"name": "string",
"city": "string",
"zip": "string",
"address": "string",
"source": "string"
},
"place": "string",
"name_of_the_judge": "string",
"notes": "string",
"responsibles": [
{
"user_id": 1234,
"name": "string"
}
],
"recorded_by": {
"user_id": 1234,
"name": "string"
},
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
}
},
"created": false,
"idempotent_replay": true
}
{
"error": "validation_failed",
"message": "The request is invalid. See \"details.fields\" for the field-level errors.",
"message_localized": "La richiesta non è valida. Gli errori per campo sono in \"details.fields\".",
"locale": "it",
"details": {
"fields": {
"date": [
"Il campo date è obbligatorio."
]
}
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Aggiorna l'udienza
/api/agent/trials/{id}
Aggiorna un'udienza (tárgyalás): la sua ora, il tribunale, il luogo, il giudice, le note, il flag di presenza e i partecipanti. Scrive solo i campi che invia; invii responsible_user_ids per sostituire l'intero elenco dei partecipanti. Passi expected_updated_at dalla sua ultima lettura; una modifica in conflitto risponde 409.
Parametri di percorso
idobbligatorioId del record da modificare.
Corpo della richiesta application/json
expected_updated_atIl valore updated_at dalla sua lettura più recente di questo record (obbligatorio ogni volta che il record ne ha uno). Se il record è cambiato da allora (un collega lo ha modificato), l'API risponde 409 e deve rileggere prima di riprovare. Un record legacy il cui updated_at è null accetta null.
dateNuova data e ora dell'udienza, ISO 8601 (un offset viene rispettato, un'ora naive viene letta nel fuso dello studio). Memorizzato in UTC.
"2026-03-02T09:00:00+01:00"court_idNuovo id del tribunale da courts.list; null per cancellare il tribunale.
participationSe è richiesta la presenza di un collega; null per cancellarla.
"required" "not_required" placeAula o luogo. Testo semplice; "<" e ">" non sono consentiti. "" lo cancella.
^[^<>]*$name_of_the_judgeNome del giudice. Testo semplice; "<" e ">" non sono consentiti. "" lo cancella.
^[^<>]*$notesNote a testo libero. Testo semplice; "<" e ">" non sono consentiti. "" le cancella.
^[^<>]*$responsible_user_idsInsieme completo sostitutivo di id utente dei partecipanti (da colleagues.list). Ometta per lasciare invariati i partecipanti.
Risposte
200
Aggiornato.
dataobbligatorioCampi di data
id4321matterLa pratica (causa) a cui appartiene l'udienza.
Campi di matter
idcase_numberdateData e ora dell'udienza, ISO 8601 nel fuso orario dello studio. È memorizzata in UTC, quindi confronti gli istanti invece del testo dell'ora di parete.
"2026-03-02T09:00:00+01:00"participationSe è richiesta la presenza di un collega: "required", "not_required", oppure null quando non impostato.
"required" "not_required" courtIl tribunale dell'udienza, risolto dal registro condiviso dei tribunali; null quando nessun tribunale è impostato.
Campi di court
idnamecityzipaddresssourceSempre "registry": il tribunale è un riferimento al registro condiviso dei tribunali (courts.list), non testo libero.
placeAula o luogo dell'udienza. Testo semplice.
name_of_the_judgeNome del giudice. Testo semplice.
notesNote a testo libero sull'udienza. Testo semplice.
responsiblesColleghi che partecipano all'udienza (id da colleagues.list).
Campi di responsibles
user_idnamerecorded_byIl collega che ha registrato l'udienza.
Campi di recorded_by
user_idnamecreated_atupdated_atPassi questo a trials.update come expected_updated_at.
created_via_apiPresente quando un agente esterno ha creato il record tramite questa API.
Campi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduseratupdatedtrue
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
409
Il record è cambiato da quando lo ha letto (record_conflict: expected_updated_at non corrisponde più; lo rilegga e riprovi con il nuovo updated_at).
record_conflict: expected_updated_at non corrisponde più; lo rilegga e riprovi con il nuovo updated_at).
413
Il corpo della richiesta è troppo grande (request_too_large).
request_too_large).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl -X PATCH 'https://www.flowyer.it/api/agent/trials/1234' \
-H 'Authorization: Bearer flw_...' \
-H 'Content-Type: application/json' \
-d '{
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"date": "2026-03-02T09:00:00+01:00"
}'
const response = await fetch("https://www.flowyer.it/api/agent/trials/1234", {
method: "PATCH",
headers: {
"Authorization": "Bearer flw_...",
"Content-Type": "application/json",
},
body: JSON.stringify({
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"date": "2026-03-02T09:00:00+01:00"
}),
});
const result = await response.json();
import requests
response = requests.patch(
"https://www.flowyer.it/api/agent/trials/1234",
headers={
"Authorization": "Bearer flw_...",
},
json={
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"date": "2026-03-02T09:00:00+01:00",
},
timeout=30,
)
print(response.status_code, response.json())
{
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"date": "2026-03-02T09:00:00+01:00"
}
Esempi di risposta
{
"data": {
"id": 4321,
"matter": {
"id": 1234,
"case_number": "string"
},
"date": "2026-03-02T09:00:00+01:00",
"participation": "required",
"court": {
"id": 1234,
"name": "string",
"city": "string",
"zip": "string",
"address": "string",
"source": "string"
},
"place": "string",
"name_of_the_judge": "string",
"notes": "string",
"responsibles": [
{
"user_id": 1234,
"name": "string"
}
],
"recorded_by": {
"user_id": 1234,
"name": "string"
},
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
}
},
"updated": true
}
{
"error": "record_conflict",
"message": "The record changed since you read it (someone edited it). Read it again and retry with the new updated_at.",
"message_localized": "Il record è cambiato dall'ultima lettura (qualcuno lo ha modificato). Rileggerlo e riprovare con il nuovo updated_at.",
"locale": "it",
"details": {
"current_updated_at": "2026-10-30T10:42:05+01:00",
"reason": "modified_since_read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Tribunali
Elenca i tribunali
/api/agent/courts
Elenca il registro condiviso dei tribunali (id, nome, città) per il court_id di trials.create / trials.update. Con q (un nome di tribunale così come ascoltato; accenti, maiuscole/minuscole e piccoli errori di battitura tollerati) risponde con lo stato exact/similar/none: solo "exact" è sicuro da usare direttamente. È l'elenco dei tribunali ungheresi.
Parametri di query
qUn nome di tribunale da cercare, così come ascoltato o dettato, in qualsiasi ordine delle parole. Lo ometta per elencare tutti i tribunali.
"Fővárosi Törvényszék"limitNumero massimo di tribunali da restituire (predefinito 200).
200Risposte
200
OK.
dataobbligatorioCampi di data
statusSolo con q: exact = una corrispondenza certa (sicuro usare il suo id), similar = corrispondenza approssimativa o più corrispondenze (prima confermi con l'utente), none = nessuna corrispondenza (chieda all'utente). Null senza q.
"exact" "similar" "none" courtsTribunali, prima la corrispondenza migliore con q, altrimenti per nome.
Campi di courts
idId del tribunale: lo passi come court_id a trials.create / trials.update.
nameNome del tribunale come mostrato in Flowyer.
cityzipaddresstotalQuanti tribunali hanno corrisposto (tutti i tribunali senza q) prima che l'elenco fosse ridotto a limit.
truncatedTrue quando hanno corrisposto più tribunali di quanti ne siano stati restituiti: restringa q o aumenti limit.
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl 'https://www.flowyer.it/api/agent/courts?q=F%C5%91v%C3%A1rosi%20T%C3%B6rv%C3%A9nysz%C3%A9k' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.it/api/agent/courts?q=F%C5%91v%C3%A1rosi%20T%C3%B6rv%C3%A9nysz%C3%A9k", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.it/api/agent/courts?q=F%C5%91v%C3%A1rosi%20T%C3%B6rv%C3%A9nysz%C3%A9k",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Esempi di risposta
{
"data": {
"status": "exact",
"courts": [
{
"id": 1234,
"name": "string",
"city": "string",
"zip": "string",
"address": "string"
}
],
"total": 1,
"truncated": true
}
}
{
"error": "scope_missing",
"message": "This API key does not have the \"courts:read\" permission. The permissions of an existing key cannot be changed, so the key owner needs to create a new key with this permission in Flowyer under Settings > API keys and use it in place of the old one.",
"message_localized": "Questa chiave API non ha il permesso \"courts:read\". I permessi di una chiave esistente non possono essere modificati, quindi il titolare della chiave deve creare in Flowyer, in Impostazioni > Chiavi API, una nuova chiave con questo permesso e usarla al posto di quella vecchia.",
"locale": "it",
"details": {
"required_scope": "courts:read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
HR
Elenca le assenze del personale
/api/agent/hr/leaves
Elenca le assenze approvate del personale (chi è o sarà in assenza): il collega, le date di inizio/fine, il conteggio dei giorni lavorativi, una categoria oscurata per privacy (leave/unpaid; sick è unito a leave e mai identificabile) ed eventuali sostituti. Non restituisce mai il tipo di assenza, le note o chi l'ha approvata.
Parametri di query
user_idSolo le assenze di questo collega. Un id utente centrale (da colleagues.list), associato al dipendente dietro l'assenza.
1234on_dateChi è in assenza in questo giorno esatto (start_date <= on_date <= end_date). Quando è impostato, ha la precedenza su date_from, date_to e timeframe.
date_fromSolo le assenze ancora in corso a partire da questa data inclusa (end_date >= date_from). Il valore predefinito è oggi, quindi le assenze interamente passate sono escluse per impostazione predefinita.
date_toSolo le assenze che iniziano entro questa data inclusa (start_date <= date_to). Ometta per un futuro senza limiti.
timeframeVincolo aggiuntivo sulla data di inizio rispetto a oggi: current = già iniziate (in corso), upcoming = non ancora iniziate, all = nessun vincolo aggiuntivo. Ignorato quando on_date è impostato.
"current" "upcoming" "all" "all"limitDimensione della pagina, 1-100. Valore predefinito 25.
2525offsetNumero di record da saltare. Usi offset + limit della pagina precedente per ottenere quella successiva; pagination.total è il conteggio totale.
00Risposte
200
OK.
dataobbligatorioCampi di data
idId della richiesta di assenza (solo un identificatore; non sensibile).
user_idIl collega in assenza (id utente centrale).
userIl nome visualizzato del collega.
start_datePrimo giorno di assenza (YYYY-MM-DD).
end_dateUltimo giorno di assenza, incluso (YYYY-MM-DD).
days_countGiorni lavorativi di assenza. Non rivela il tipo.
categoryTipo di assenza oscurato per privacy: sia annual che sick diventano "leave" (sick non è mai identificabile), unpaid rimane "unpaid". Il tipo di assenza grezzo non viene mai esposto.
"leave" "unpaid" statusSempre "approved" - vengono restituite solo le assenze approvate; pending, rejected e cancelled non compaiono mai.
"approved" substitute_user_idCollega sostituto per questa assenza (id utente centrale), oppure null.
substitute_userNome visualizzato del collega sostituto, oppure null.
paginationobbligatorioCampi di pagination
limitobbligatoriooffsetobbligatoriototalobbligatorioNumero totale di record corrispondenti.
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl 'https://www.flowyer.it/api/agent/hr/leaves?user_id=1234&limit=25' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.it/api/agent/hr/leaves?user_id=1234&limit=25", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.it/api/agent/hr/leaves?user_id=1234&limit=25",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Esempi di risposta
{
"data": [
{
"id": 1234,
"user_id": 1234,
"user": "string",
"start_date": "2026-10-30",
"end_date": "2026-10-30",
"days_count": 0,
"category": "leave",
"status": "approved",
"substitute_user_id": 1234,
"substitute_user": "string"
}
],
"pagination": {
"limit": 25,
"offset": 0,
"total": 1
}
}
{
"error": "scope_missing",
"message": "This API key does not have the \"hr:read\" permission. The permissions of an existing key cannot be changed, so the key owner needs to create a new key with this permission in Flowyer under Settings > API keys and use it in place of the old one.",
"message_localized": "Questa chiave API non ha il permesso \"hr:read\". I permessi di una chiave esistente non possono essere modificati, quindi il titolare della chiave deve creare in Flowyer, in Impostazioni > Chiavi API, una nuova chiave con questo permesso e usarla al posto di quella vecchia.",
"locale": "it",
"details": {
"required_scope": "hr:read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Calendario
Elenca gli eventi del calendario
/api/agent/calendar/events
Elenca gli eventi del calendario che si sovrappongono a un intervallo di date [from, to]: il calendario dello studio, il suo e i calendari condivisi con Lei. Gli eventi ricorrenti vengono restituiti una sola volta (is_recurring), NON espansi. Ordinati per inizio. Un evento personale non condiviso con Lei non appare mai.
Parametri di query
fromobbligatorioInizio dell'intervallo (incluso), ISO 8601. Vengono restituiti gli eventi che si sovrappongono a [from, to]. Un orario senza offset viene letto nel fuso dello studio.
"2026-03-01T00:00:00+01:00"toobbligatorioFine dell'intervallo (inclusa), ISO 8601. Deve essere pari o successiva a from (altrimenti 422) e al massimo 366 giorni dopo.
"2026-03-31T23:59:59+01:00"calendar_idsRestringe a questi id di calendari contenitore; ciascuno viene intersecato con i calendari che Lei può visualizzare, quindi un id che non può vedere viene scartato silenziosamente. Ometta per tutti i calendari visibili.
include_recurringIncludi gli eventi master ricorrenti la cui regola si sovrappone all'intervallo (restituiti non espansi, is_recurring = true). Predefinito true.
truelimitDimensione della pagina, 1-100. Valore predefinito 25.
2525offsetNumero di record da saltare. Usi offset + limit della pagina precedente per ottenere quella successiva; pagination.total è il conteggio totale.
00Risposte
200
OK.
dataobbligatorioCampi di data
id5501calendarIl calendario a cui appartiene l'evento.
Campi di calendar
idId del calendario contenitore, oppure null per il calendario condiviso dello studio implicito (un evento legacy senza contenitore).
nametype"office" = il calendario condiviso dello studio (ogni utente dello studio può visualizzarlo e modificarlo); "personal" = il calendario personale di un utente, visibile solo al suo proprietario e a coloro con cui è condiviso.
"office" "personal" ownerProprietario di un calendario personale; null per il calendario dello studio.
Campi di owner
user_idnametitleTitolo dell'evento. Testo semplice.
descriptionDescrizione dell'evento. Testo semplice.
locationLuogo. Testo semplice.
participantsPartecipanti, testo libero. Testo semplice.
startUn evento per tutto il giorno: la data di inizio "YYYY-MM-DD". Un evento con orario: ISO 8601 nel fuso orario dello studio (l'istante UTC memorizzato).
"2026-03-02T09:00:00+01:00"endStessa codifica di start. Per un evento per tutto il giorno la data di fine è INCLUSIVA (il valore memorizzato, non il valore +1 giorno che usa una griglia di calendario). Null quando l'evento non ha una fine.
all_dayTrue per un evento per tutto il giorno (start/end sono date semplici); false per un evento con orario (start/end sono istanti ISO 8601).
colorColore di visualizzazione, ad es. "#2c7be5".
is_recurringTrue quando l'evento è un master ricorrente. Gli eventi ricorrenti vengono restituiti una sola volta, NON espansi in occorrenze, e non possono essere modificati tramite calendar.events.update.
recurrenceLa regola di ricorrenza di un master ricorrente, oppure null per un evento singolo. Di sola lettura.
Campi di recurrence
freqdaily | weekly | monthly | yearly.
intervalbyweekdayCodici dei giorni della settimana separati da virgola (ad es. "MO,WE,FR").
untilcountcreated_byIl collega che ha creato l'evento.
Campi di created_by
user_idnamecreated_atupdated_atPassi questo a calendar.events.update come expected_updated_at.
created_via_apiPresente quando un agente esterno ha creato il record tramite questa API.
Campi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduseratpaginationobbligatorioCampi di pagination
limitobbligatoriooffsetobbligatoriototalobbligatorioNumero totale di record corrispondenti.
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl 'https://www.flowyer.it/api/agent/calendar/events?from=2026-03-01T00%3A00%3A00%2B01%3A00&to=2026-03-31T23%3A59%3A59%2B01%3A00&limit=25' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.it/api/agent/calendar/events?from=2026-03-01T00%3A00%3A00%2B01%3A00&to=2026-03-31T23%3A59%3A59%2B01%3A00&limit=25", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.it/api/agent/calendar/events?from=2026-03-01T00%3A00%3A00%2B01%3A00&to=2026-03-31T23%3A59%3A59%2B01%3A00&limit=25",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Esempi di risposta
{
"data": [
{
"id": 5501,
"calendar": {
"id": 1234,
"name": "string",
"type": "office",
"owner": {
"user_id": 1234,
"name": "string"
}
},
"title": "string",
"description": "string",
"location": "string",
"participants": "string",
"start": "2026-03-02T09:00:00+01:00",
"end": "string",
"all_day": true,
"color": "string",
"is_recurring": true,
"recurrence": {
"freq": "string",
"interval": 0,
"byweekday": "string",
"until": "string",
"count": 0
},
"created_by": {
"user_id": 1234,
"name": "string"
},
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
}
}
],
"pagination": {
"limit": 25,
"offset": 0,
"total": 1
}
}
{
"error": "scope_missing",
"message": "This API key does not have the \"calendar:read\" permission. The permissions of an existing key cannot be changed, so the key owner needs to create a new key with this permission in Flowyer under Settings > API keys and use it in place of the old one.",
"message_localized": "Questa chiave API non ha il permesso \"calendar:read\". I permessi di una chiave esistente non possono essere modificati, quindi il titolare della chiave deve creare in Flowyer, in Impostazioni > Chiavi API, una nuova chiave con questo permesso e usarla al posto di quella vecchia.",
"locale": "it",
"details": {
"required_scope": "calendar:read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Ottieni l'evento del calendario
/api/agent/calendar/events/{id}
Restituisce un evento del calendario con il suo calendario, il riepilogo della ricorrenza e il token di blocco updated_at per calendar.events.update. Risponde 404 quando l'evento non esiste o il suo calendario non è visibile all'utente.
Parametri di percorso
idobbligatorioId dell'evento.
5501Risposte
200
OK.
dataobbligatorioCampi di data
id5501calendarIl calendario a cui appartiene l'evento.
Campi di calendar
idId del calendario contenitore, oppure null per il calendario condiviso dello studio implicito (un evento legacy senza contenitore).
nametype"office" = il calendario condiviso dello studio (ogni utente dello studio può visualizzarlo e modificarlo); "personal" = il calendario personale di un utente, visibile solo al suo proprietario e a coloro con cui è condiviso.
"office" "personal" ownerProprietario di un calendario personale; null per il calendario dello studio.
Campi di owner
user_idnametitleTitolo dell'evento. Testo semplice.
descriptionDescrizione dell'evento. Testo semplice.
locationLuogo. Testo semplice.
participantsPartecipanti, testo libero. Testo semplice.
startUn evento per tutto il giorno: la data di inizio "YYYY-MM-DD". Un evento con orario: ISO 8601 nel fuso orario dello studio (l'istante UTC memorizzato).
"2026-03-02T09:00:00+01:00"endStessa codifica di start. Per un evento per tutto il giorno la data di fine è INCLUSIVA (il valore memorizzato, non il valore +1 giorno che usa una griglia di calendario). Null quando l'evento non ha una fine.
all_dayTrue per un evento per tutto il giorno (start/end sono date semplici); false per un evento con orario (start/end sono istanti ISO 8601).
colorColore di visualizzazione, ad es. "#2c7be5".
is_recurringTrue quando l'evento è un master ricorrente. Gli eventi ricorrenti vengono restituiti una sola volta, NON espansi in occorrenze, e non possono essere modificati tramite calendar.events.update.
recurrenceLa regola di ricorrenza di un master ricorrente, oppure null per un evento singolo. Di sola lettura.
Campi di recurrence
freqdaily | weekly | monthly | yearly.
intervalbyweekdayCodici dei giorni della settimana separati da virgola (ad es. "MO,WE,FR").
untilcountcreated_byIl collega che ha creato l'evento.
Campi di created_by
user_idnamecreated_atupdated_atPassi questo a calendar.events.update come expected_updated_at.
created_via_apiPresente quando un agente esterno ha creato il record tramite questa API.
Campi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduserat
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl 'https://www.flowyer.it/api/agent/calendar/events/5501' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.it/api/agent/calendar/events/5501", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.it/api/agent/calendar/events/5501",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Esempi di risposta
{
"data": {
"id": 5501,
"calendar": {
"id": 1234,
"name": "string",
"type": "office",
"owner": {
"user_id": 1234,
"name": "string"
}
},
"title": "string",
"description": "string",
"location": "string",
"participants": "string",
"start": "2026-03-02T09:00:00+01:00",
"end": "string",
"all_day": true,
"color": "string",
"is_recurring": true,
"recurrence": {
"freq": "string",
"interval": 0,
"byweekday": "string",
"until": "string",
"count": 0
},
"created_by": {
"user_id": 1234,
"name": "string"
},
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
}
}
}
{
"error": "not_found",
"message": "The record was not found, or it is not visible to the user who owns this API key.",
"message_localized": "Il record non è stato trovato oppure non è visibile al titolare di questa chiave API.",
"locale": "it",
"details": {
"record_type": "calendar_event",
"record_id": 5501
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Crea un evento del calendario
/api/agent/calendar/events
Crea un singolo evento del calendario (con orario o per tutto il giorno) sul calendario dello studio o su un calendario che Lei può modificare. Un inizio/fine con orario rispetta un offset ISO 8601, un'ora naive viene letta nel fuso dello studio; una data di fine per tutto il giorno è inclusiva. Gli eventi ricorrenti non vengono creati qui. Non vengono inviati ai calendari esterni.
Parametri di intestazione
Idempotency-KeyConsigliato a ogni creazione. Un valore univoco per operazione logica (ad es. un UUID). Lo stesso valore restituisce lo stesso record: riprovare con esso restituisce il record creato la prima volta invece di crearne un secondo. Valori diversi creano sempre record diversi. I client che non possono inviare header possono passare lo stesso valore nel campo del corpo idempotency_key. Lettere, cifre, _, -, : o ., al massimo 128 caratteri.
^[A-Za-z0-9_\-:.]{1,128}$Corpo della richiesta application/json
titleobbligatorioTitolo dell'evento. Testo semplice; "<" e ">" non sono consentiti (confluisce senza escape nella notifica di promemoria).
^[^<>]*$"Ügyfél egyeztetés"startobbligatorioPer tutto il giorno (all_day true): una data "YYYY-MM-DD". Con orario (all_day false): ISO 8601; un offset viene rispettato, un'ora naive viene letta nel fuso dello studio.
"2026-03-02T09:00:00+01:00"endStessa codifica di start. Predefinito = start. Per un evento per tutto il giorno la data di fine è INCLUSIVA. Non deve essere precedente a start (altrimenti 422).
all_daySe l'evento è per tutto il giorno. Predefinito false (con orario).
falsecalendar_idCalendario contenitore di destinazione; predefinito = il calendario dello studio. Deve possedere i diritti di modifica su di esso (altrimenti 403). Solo su un tenant con la funzionalità dei calendari personali.
locationLuogo. Testo semplice; "<" e ">" non sono consentiti.
^[^<>]*$descriptionDescrizione, testo semplice (non HTML); "<" e ">" non sono consentiti.
^[^<>]*$participantsPartecipanti, testo libero. Testo semplice; "<" e ">" non sono consentiti.
^[^<>]*$colorColore di visualizzazione, ad es. "#2c7be5".
^#?[A-Za-z0-9_-]{1,31}$idempotency_keyStesso ruolo dell'header Idempotency-Key, per i client che non possono inviare header personalizzati. Lettere, cifre, _, -, : o ., al massimo 128 caratteri.
^[A-Za-z0-9_\-:.]{1,128}$"b8f1c2e0-6f7a-4d2e-9c1b-2a3d4e5f6a7b"Risposte
201
Creato.
dataobbligatorioCampi di data
id5501calendarIl calendario a cui appartiene l'evento.
Campi di calendar
idId del calendario contenitore, oppure null per il calendario condiviso dello studio implicito (un evento legacy senza contenitore).
nametype"office" = il calendario condiviso dello studio (ogni utente dello studio può visualizzarlo e modificarlo); "personal" = il calendario personale di un utente, visibile solo al suo proprietario e a coloro con cui è condiviso.
"office" "personal" ownerProprietario di un calendario personale; null per il calendario dello studio.
Campi di owner
user_idnametitleTitolo dell'evento. Testo semplice.
descriptionDescrizione dell'evento. Testo semplice.
locationLuogo. Testo semplice.
participantsPartecipanti, testo libero. Testo semplice.
startUn evento per tutto il giorno: la data di inizio "YYYY-MM-DD". Un evento con orario: ISO 8601 nel fuso orario dello studio (l'istante UTC memorizzato).
"2026-03-02T09:00:00+01:00"endStessa codifica di start. Per un evento per tutto il giorno la data di fine è INCLUSIVA (il valore memorizzato, non il valore +1 giorno che usa una griglia di calendario). Null quando l'evento non ha una fine.
all_dayTrue per un evento per tutto il giorno (start/end sono date semplici); false per un evento con orario (start/end sono istanti ISO 8601).
colorColore di visualizzazione, ad es. "#2c7be5".
is_recurringTrue quando l'evento è un master ricorrente. Gli eventi ricorrenti vengono restituiti una sola volta, NON espansi in occorrenze, e non possono essere modificati tramite calendar.events.update.
recurrenceLa regola di ricorrenza di un master ricorrente, oppure null per un evento singolo. Di sola lettura.
Campi di recurrence
freqdaily | weekly | monthly | yearly.
intervalbyweekdayCodici dei giorni della settimana separati da virgola (ad es. "MO,WE,FR").
untilcountcreated_byIl collega che ha creato l'evento.
Campi di created_by
user_idnamecreated_atupdated_atPassi questo a calendar.events.update come expected_updated_at.
created_via_apiPresente quando un agente esterno ha creato il record tramite questa API.
Campi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduseratcreatedtrue
200
Replay idempotente: questo Idempotency-Key (o, senza chiave, una richiesta identica entro 120 secondi) ha già creato il record; viene restituito di nuovo, nulla di nuovo è stato creato.
dataobbligatorioCampi di data
id5501calendarIl calendario a cui appartiene l'evento.
Campi di calendar
idId del calendario contenitore, oppure null per il calendario condiviso dello studio implicito (un evento legacy senza contenitore).
nametype"office" = il calendario condiviso dello studio (ogni utente dello studio può visualizzarlo e modificarlo); "personal" = il calendario personale di un utente, visibile solo al suo proprietario e a coloro con cui è condiviso.
"office" "personal" ownerProprietario di un calendario personale; null per il calendario dello studio.
Campi di owner
user_idnametitleTitolo dell'evento. Testo semplice.
descriptionDescrizione dell'evento. Testo semplice.
locationLuogo. Testo semplice.
participantsPartecipanti, testo libero. Testo semplice.
startUn evento per tutto il giorno: la data di inizio "YYYY-MM-DD". Un evento con orario: ISO 8601 nel fuso orario dello studio (l'istante UTC memorizzato).
"2026-03-02T09:00:00+01:00"endStessa codifica di start. Per un evento per tutto il giorno la data di fine è INCLUSIVA (il valore memorizzato, non il valore +1 giorno che usa una griglia di calendario). Null quando l'evento non ha una fine.
all_dayTrue per un evento per tutto il giorno (start/end sono date semplici); false per un evento con orario (start/end sono istanti ISO 8601).
colorColore di visualizzazione, ad es. "#2c7be5".
is_recurringTrue quando l'evento è un master ricorrente. Gli eventi ricorrenti vengono restituiti una sola volta, NON espansi in occorrenze, e non possono essere modificati tramite calendar.events.update.
recurrenceLa regola di ricorrenza di un master ricorrente, oppure null per un evento singolo. Di sola lettura.
Campi di recurrence
freqdaily | weekly | monthly | yearly.
intervalbyweekdayCodici dei giorni della settimana separati da virgola (ad es. "MO,WE,FR").
untilcountcreated_byIl collega che ha creato l'evento.
Campi di created_by
user_idnamecreated_atupdated_atPassi questo a calendar.events.update come expected_updated_at.
created_via_apiPresente quando un agente esterno ha creato il record tramite questa API.
Campi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduseratcreatedfalseidempotent_replaytrue
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente. replay_not_visible: questo Idempotency-Key (o, senza chiave, una richiesta identica) ha già creato il record (details.record_id), ma da allora è stato eliminato o non è visibile all'utente; nulla di nuovo è stato creato, non lo ricrei.
replay_not_visible: questo Idempotency-Key (o, senza chiave, una richiesta identica) ha già creato il record (details.record_id), ma da allora è stato eliminato o non è visibile all'utente; nulla di nuovo è stato creato, non lo ricrei.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
409
L'Idempotency-Key è stato usato per un altro tipo di risorsa (idempotency_key_reused), oppure, senza chiave, una richiesta identica è in fase di elaborazione in questo momento (duplicate_in_progress; riprovi a breve).
idempotency_key_reused), oppure, senza chiave, una richiesta identica è in fase di elaborazione in questo momento (duplicate_in_progress; riprovi a breve).
413
Il corpo della richiesta è troppo grande (request_too_large).
request_too_large).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl -X POST 'https://www.flowyer.it/api/agent/calendar/events' \
-H 'Authorization: Bearer flw_...' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: 7f3a9c21-1b2c-4d5e-8f90-0a1b2c3d4e5f' \
-d '{
"title": "Ügyfél egyeztetés",
"start": "2026-03-02T09:00:00+01:00"
}'
const response = await fetch("https://www.flowyer.it/api/agent/calendar/events", {
method: "POST",
headers: {
"Authorization": "Bearer flw_...",
"Content-Type": "application/json",
"Idempotency-Key": crypto.randomUUID(),
},
body: JSON.stringify({
"title": "Ügyfél egyeztetés",
"start": "2026-03-02T09:00:00+01:00"
}),
});
const result = await response.json();
import uuid
import requests
response = requests.post(
"https://www.flowyer.it/api/agent/calendar/events",
headers={
"Authorization": "Bearer flw_...",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"title": "Ügyfél egyeztetés",
"start": "2026-03-02T09:00:00+01:00",
},
timeout=30,
)
print(response.status_code, response.json())
{
"title": "Ügyfél egyeztetés",
"start": "2026-03-02T09:00:00+01:00"
}
Esempi di risposta
{
"data": {
"id": 5501,
"calendar": {
"id": 1234,
"name": "string",
"type": "office",
"owner": {
"user_id": 1234,
"name": "string"
}
},
"title": "string",
"description": "string",
"location": "string",
"participants": "string",
"start": "2026-03-02T09:00:00+01:00",
"end": "string",
"all_day": true,
"color": "string",
"is_recurring": true,
"recurrence": {
"freq": "string",
"interval": 0,
"byweekday": "string",
"until": "string",
"count": 0
},
"created_by": {
"user_id": 1234,
"name": "string"
},
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
}
},
"created": true
}
{
"data": {
"id": 5501,
"calendar": {
"id": 1234,
"name": "string",
"type": "office",
"owner": {
"user_id": 1234,
"name": "string"
}
},
"title": "string",
"description": "string",
"location": "string",
"participants": "string",
"start": "2026-03-02T09:00:00+01:00",
"end": "string",
"all_day": true,
"color": "string",
"is_recurring": true,
"recurrence": {
"freq": "string",
"interval": 0,
"byweekday": "string",
"until": "string",
"count": 0
},
"created_by": {
"user_id": 1234,
"name": "string"
},
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
}
},
"created": false,
"idempotent_replay": true
}
{
"error": "validation_failed",
"message": "The request is invalid. See \"details.fields\" for the field-level errors.",
"message_localized": "La richiesta non è valida. Gli errori per campo sono in \"details.fields\".",
"locale": "it",
"details": {
"fields": {
"title": [
"Il campo title è obbligatorio."
]
}
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Aggiorna l'evento del calendario
/api/agent/calendar/events/{id}
Aggiorna un singolo evento del calendario: titolo, start/end, all_day, luogo, descrizione, partecipanti, colore. Scrive solo i campi che invia; "" cancella luogo/descrizione/partecipanti. Un evento ricorrente risponde 422. Passi expected_updated_at dalla sua ultima lettura; una modifica in conflitto risponde 409.
Parametri di percorso
idobbligatorioId del record da modificare.
Corpo della richiesta application/json
expected_updated_atIl valore updated_at dalla sua lettura più recente di questo record (obbligatorio ogni volta che il record ne ha uno). Se il record è cambiato da allora (un collega lo ha modificato), l'API risponde 409 e deve rileggere prima di riprovare. Un record legacy il cui updated_at è null accetta null.
titleNuovo titolo. Testo semplice; "<" e ">" non sono consentiti.
^[^<>]*$startNuovo inizio. Per tutto il giorno: "YYYY-MM-DD". Con orario: ISO 8601 (un offset viene rispettato, un'ora naive viene letta nel fuso dello studio). Ricodificato se all_day cambia.
endNuova fine, stessa codifica di start; "" la cancella. Per un evento per tutto il giorno la data di fine è inclusiva. Non deve essere precedente a start (altrimenti 422).
all_daySe inviato, start/end vengono ricodificati di conseguenza; se omesso, viene usato l'all_day corrente della riga.
locationLuogo. Testo semplice; "<" e ">" non sono consentiti. "" lo cancella.
^[^<>]*$descriptionDescrizione, testo semplice (non HTML); "<" e ">" non sono consentiti. "" la cancella.
^[^<>]*$participantsPartecipanti, testo libero. Testo semplice; "<" e ">" non sono consentiti. "" li cancella.
^[^<>]*$colorColore di visualizzazione, ad es. "#2c7be5". "" lo cancella.
^#?[A-Za-z0-9_-]{1,31}$Risposte
200
Aggiornato.
dataobbligatorioCampi di data
id5501calendarIl calendario a cui appartiene l'evento.
Campi di calendar
idId del calendario contenitore, oppure null per il calendario condiviso dello studio implicito (un evento legacy senza contenitore).
nametype"office" = il calendario condiviso dello studio (ogni utente dello studio può visualizzarlo e modificarlo); "personal" = il calendario personale di un utente, visibile solo al suo proprietario e a coloro con cui è condiviso.
"office" "personal" ownerProprietario di un calendario personale; null per il calendario dello studio.
Campi di owner
user_idnametitleTitolo dell'evento. Testo semplice.
descriptionDescrizione dell'evento. Testo semplice.
locationLuogo. Testo semplice.
participantsPartecipanti, testo libero. Testo semplice.
startUn evento per tutto il giorno: la data di inizio "YYYY-MM-DD". Un evento con orario: ISO 8601 nel fuso orario dello studio (l'istante UTC memorizzato).
"2026-03-02T09:00:00+01:00"endStessa codifica di start. Per un evento per tutto il giorno la data di fine è INCLUSIVA (il valore memorizzato, non il valore +1 giorno che usa una griglia di calendario). Null quando l'evento non ha una fine.
all_dayTrue per un evento per tutto il giorno (start/end sono date semplici); false per un evento con orario (start/end sono istanti ISO 8601).
colorColore di visualizzazione, ad es. "#2c7be5".
is_recurringTrue quando l'evento è un master ricorrente. Gli eventi ricorrenti vengono restituiti una sola volta, NON espansi in occorrenze, e non possono essere modificati tramite calendar.events.update.
recurrenceLa regola di ricorrenza di un master ricorrente, oppure null per un evento singolo. Di sola lettura.
Campi di recurrence
freqdaily | weekly | monthly | yearly.
intervalbyweekdayCodici dei giorni della settimana separati da virgola (ad es. "MO,WE,FR").
untilcountcreated_byIl collega che ha creato l'evento.
Campi di created_by
user_idnamecreated_atupdated_atPassi questo a calendar.events.update come expected_updated_at.
created_via_apiPresente quando un agente esterno ha creato il record tramite questa API.
Campi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduseratupdatedtrue
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
409
Il record è cambiato da quando lo ha letto (record_conflict: expected_updated_at non corrisponde più; lo rilegga e riprovi con il nuovo updated_at).
record_conflict: expected_updated_at non corrisponde più; lo rilegga e riprovi con il nuovo updated_at).
413
Il corpo della richiesta è troppo grande (request_too_large).
request_too_large).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl -X PATCH 'https://www.flowyer.it/api/agent/calendar/events/1234' \
-H 'Authorization: Bearer flw_...' \
-H 'Content-Type: application/json' \
-d '{
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"title": "string"
}'
const response = await fetch("https://www.flowyer.it/api/agent/calendar/events/1234", {
method: "PATCH",
headers: {
"Authorization": "Bearer flw_...",
"Content-Type": "application/json",
},
body: JSON.stringify({
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"title": "string"
}),
});
const result = await response.json();
import requests
response = requests.patch(
"https://www.flowyer.it/api/agent/calendar/events/1234",
headers={
"Authorization": "Bearer flw_...",
},
json={
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"title": "string",
},
timeout=30,
)
print(response.status_code, response.json())
{
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"title": "string"
}
Esempi di risposta
{
"data": {
"id": 5501,
"calendar": {
"id": 1234,
"name": "string",
"type": "office",
"owner": {
"user_id": 1234,
"name": "string"
}
},
"title": "string",
"description": "string",
"location": "string",
"participants": "string",
"start": "2026-03-02T09:00:00+01:00",
"end": "string",
"all_day": true,
"color": "string",
"is_recurring": true,
"recurrence": {
"freq": "string",
"interval": 0,
"byweekday": "string",
"until": "string",
"count": 0
},
"created_by": {
"user_id": 1234,
"name": "string"
},
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
}
},
"updated": true
}
{
"error": "record_conflict",
"message": "The record changed since you read it (someone edited it). Read it again and retry with the new updated_at.",
"message_localized": "Il record è cambiato dall'ultima lettura (qualcuno lo ha modificato). Rileggerlo e riprovare con il nuovo updated_at.",
"locale": "it",
"details": {
"current_updated_at": "2026-10-30T10:42:05+01:00",
"reason": "modified_since_read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Prenotazioni
Elenca le prenotazioni
/api/agent/bookings
Elenca le prenotazioni di appuntamento (időpontfoglalások) dello studio, prima le più recenti. Facoltativamente filtrate per un intervallo di giorni da/a (fuso orario della prenotazione), un avvocato (user_id), uno stato o updated_since. Ogni titolare di chiave vede le prenotazioni di tutti gli avvocati.
Parametri di query
fromSolo le prenotazioni a partire da questo giorno incluso (YYYY-MM-DD), confrontate letteralmente con la data del fuso della prenotazione.
"2026-01-01"toSolo le prenotazioni fino a questo giorno incluso (YYYY-MM-DD).
"2026-12-31"user_idFiltra su un solo avvocato (user_id da colleagues.list). Ometta per tutti gli avvocati dello studio.
statusFiltra per stato.
"pending" "confirmed" "cancelled" "completed" "awaiting_payment" "expired" updated_sinceSolo le prenotazioni modificate a partire da questo momento ISO 8601 (updated_at è naive nel fuso dello studio).
limitDimensione della pagina, 1-100. Valore predefinito 25.
2525offsetNumero di record da saltare. Usi offset + limit della pagina precedente per ottenere quella successiva; pagination.total è il conteggio totale.
00Risposte
200
OK.
dataobbligatorioCampi di data
id4321booking_numberNumero di prenotazione leggibile, ad es. "#B-0001".
statuspending = in attesa della conferma dell'avvocato; confirmed = approvata; cancelled/completed; awaiting_payment/expired appartengono al flusso paga-prima-della-conferma.
"pending" "confirmed" "cancelled" "completed" "awaiting_payment" "expired" sourceDa dove proviene la prenotazione. Una prenotazione creata tramite API è "manual".
"flowyer" "website" "embed_widget" "manual" lawyerL'avvocato (user_id da colleagues.list) con cui è fissato l'appuntamento.
Campi di lawyer
user_idnamedateData di calendario nel fuso orario della prenotazione (YYYY-MM-DD), memorizzata letteralmente.
start_timeOra di inizio HH:MM nel fuso orario della prenotazione.
end_timeOra di fine HH:MM nel fuso orario della prenotazione.
startIstante ISO 8601 non ambiguo dell'inizio, composto con il fuso orario della prenotazione. Lo usi per confrontare istanti tra fusi diversi.
endIstante ISO 8601 non ambiguo della fine.
timezoneIl fuso orario della prenotazione (booking_settings.timezone), ad es. "Europe/Budapest". Governa date, start_time e end_time.
location_preferenceSe la consulenza è in studio o online.
"office" "online" meeting_linkURL della riunione online, quando impostato.
clientIl cliente esterno che ha prenotato: nome, e-mail, telefono e l'oggetto/note. Dati personali, solo per il personale dello studio.
Campi di client
nameemailphonedescriptiongdpr_consentSe è registrato il consenso del cliente al trattamento dei dati.
gdpr_consent_atQuando è stato registrato il consenso.
cancel_reasonMotivo registrato all'annullamento.
paymentStato di pagamento di sola lettura. L'API non modifica mai il pagamento; le commissioni di prenotazione sono gestite in Flowyer.
Campi di payment
status"none" "awaiting" "partial" "paid" "refunded" method"card" "transfer" amountcurrencyinvoice_numberconfirmed_atcancelled_atcreated_atupdated_atPassi questo a bookings.update / bookings.confirm / bookings.cancel come expected_updated_at.
created_via_apiPresente quando un agente esterno ha creato la prenotazione tramite questa API.
Campi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduseratpaginationobbligatorioCampi di pagination
limitobbligatoriooffsetobbligatoriototalobbligatorioNumero totale di record corrispondenti.
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl 'https://www.flowyer.it/api/agent/bookings?from=2026-01-01&to=2026-12-31&limit=25' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.it/api/agent/bookings?from=2026-01-01&to=2026-12-31&limit=25", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.it/api/agent/bookings?from=2026-01-01&to=2026-12-31&limit=25",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Esempi di risposta
{
"data": [
{
"id": 4321,
"booking_number": "string",
"status": "pending",
"source": "flowyer",
"lawyer": {
"user_id": 1234,
"name": "string"
},
"date": "2026-10-30",
"start_time": "string",
"end_time": "string",
"start": "2026-10-30T09:15:00+01:00",
"end": "2026-10-30T09:15:00+01:00",
"timezone": "string",
"location_preference": "office",
"meeting_link": "string",
"client": {
"name": "string",
"email": "info@example.hu",
"phone": "string",
"description": "string"
},
"gdpr_consent": true,
"gdpr_consent_at": "2026-10-30T09:15:00+01:00",
"cancel_reason": "string",
"payment": {
"status": "none",
"method": "card",
"amount": 0,
"currency": "string",
"invoice_number": "string"
},
"confirmed_at": "2026-10-30T09:15:00+01:00",
"cancelled_at": "2026-10-30T09:15:00+01:00",
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
}
}
],
"pagination": {
"limit": 25,
"offset": 0,
"total": 1
}
}
{
"error": "scope_missing",
"message": "This API key does not have the \"bookings:read\" permission. The permissions of an existing key cannot be changed, so the key owner needs to create a new key with this permission in Flowyer under Settings > API keys and use it in place of the old one.",
"message_localized": "Questa chiave API non ha il permesso \"bookings:read\". I permessi di una chiave esistente non possono essere modificati, quindi il titolare della chiave deve creare in Flowyer, in Impostazioni > Chiavi API, una nuova chiave con questo permesso e usarla al posto di quella vecchia.",
"locale": "it",
"details": {
"required_scope": "bookings:read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Ottieni la prenotazione
/api/agent/bookings/{id}
Restituisce una prenotazione di appuntamento con l'avvocato, i dettagli del cliente, gli istanti di inizio/fine, lo stato di pagamento e il token di blocco updated_at per bookings.update / .confirm / .cancel. Risponde 404 quando la prenotazione non esiste in questo studio.
Parametri di percorso
idobbligatorioId della prenotazione.
4321Risposte
200
OK.
dataobbligatorioCampi di data
id4321booking_numberNumero di prenotazione leggibile, ad es. "#B-0001".
statuspending = in attesa della conferma dell'avvocato; confirmed = approvata; cancelled/completed; awaiting_payment/expired appartengono al flusso paga-prima-della-conferma.
"pending" "confirmed" "cancelled" "completed" "awaiting_payment" "expired" sourceDa dove proviene la prenotazione. Una prenotazione creata tramite API è "manual".
"flowyer" "website" "embed_widget" "manual" lawyerL'avvocato (user_id da colleagues.list) con cui è fissato l'appuntamento.
Campi di lawyer
user_idnamedateData di calendario nel fuso orario della prenotazione (YYYY-MM-DD), memorizzata letteralmente.
start_timeOra di inizio HH:MM nel fuso orario della prenotazione.
end_timeOra di fine HH:MM nel fuso orario della prenotazione.
startIstante ISO 8601 non ambiguo dell'inizio, composto con il fuso orario della prenotazione. Lo usi per confrontare istanti tra fusi diversi.
endIstante ISO 8601 non ambiguo della fine.
timezoneIl fuso orario della prenotazione (booking_settings.timezone), ad es. "Europe/Budapest". Governa date, start_time e end_time.
location_preferenceSe la consulenza è in studio o online.
"office" "online" meeting_linkURL della riunione online, quando impostato.
clientIl cliente esterno che ha prenotato: nome, e-mail, telefono e l'oggetto/note. Dati personali, solo per il personale dello studio.
Campi di client
nameemailphonedescriptiongdpr_consentSe è registrato il consenso del cliente al trattamento dei dati.
gdpr_consent_atQuando è stato registrato il consenso.
cancel_reasonMotivo registrato all'annullamento.
paymentStato di pagamento di sola lettura. L'API non modifica mai il pagamento; le commissioni di prenotazione sono gestite in Flowyer.
Campi di payment
status"none" "awaiting" "partial" "paid" "refunded" method"card" "transfer" amountcurrencyinvoice_numberconfirmed_atcancelled_atcreated_atupdated_atPassi questo a bookings.update / bookings.confirm / bookings.cancel come expected_updated_at.
created_via_apiPresente quando un agente esterno ha creato la prenotazione tramite questa API.
Campi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduserat
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl 'https://www.flowyer.it/api/agent/bookings/4321' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.it/api/agent/bookings/4321", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.it/api/agent/bookings/4321",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Esempi di risposta
{
"data": {
"id": 4321,
"booking_number": "string",
"status": "pending",
"source": "flowyer",
"lawyer": {
"user_id": 1234,
"name": "string"
},
"date": "2026-10-30",
"start_time": "string",
"end_time": "string",
"start": "2026-10-30T09:15:00+01:00",
"end": "2026-10-30T09:15:00+01:00",
"timezone": "string",
"location_preference": "office",
"meeting_link": "string",
"client": {
"name": "string",
"email": "info@example.hu",
"phone": "string",
"description": "string"
},
"gdpr_consent": true,
"gdpr_consent_at": "2026-10-30T09:15:00+01:00",
"cancel_reason": "string",
"payment": {
"status": "none",
"method": "card",
"amount": 0,
"currency": "string",
"invoice_number": "string"
},
"confirmed_at": "2026-10-30T09:15:00+01:00",
"cancelled_at": "2026-10-30T09:15:00+01:00",
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
}
}
}
{
"error": "not_found",
"message": "The record was not found, or it is not visible to the user who owns this API key.",
"message_localized": "Il record non è stato trovato oppure non è visibile al titolare di questa chiave API.",
"locale": "it",
"details": {
"record_type": "booking",
"record_id": 4321
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Crea una prenotazione
/api/agent/bookings
Fissa un appuntamento e INVIA UN'EMAIL AL CLIENTE con la conferma. Richiede uno slot libero per l'avvocato (altrimenti 409); il calendario dello studio non blocca mai. source è "manual". Un replay con Idempotency-Key non prenota di nuovo né invia di nuovo l'email.
Parametri di intestazione
Idempotency-KeyConsigliato a ogni creazione. Un valore univoco per operazione logica (ad es. un UUID). Lo stesso valore restituisce lo stesso record: riprovare con esso restituisce il record creato la prima volta invece di crearne un secondo. Valori diversi creano sempre record diversi. I client che non possono inviare header possono passare lo stesso valore nel campo del corpo idempotency_key. Lettere, cifre, _, -, : o ., al massimo 128 caratteri.
^[A-Za-z0-9_\-:.]{1,128}$Corpo della richiesta application/json
user_idobbligatorioAvvocato con cui è fissato l'appuntamento (user_id da colleagues.list; deve essere un collega attivo dello studio).
42dateobbligatorioGiorno dell'appuntamento (YYYY-MM-DD) nel fuso orario della prenotazione.
"2026-03-02"timeobbligatorioOra di inizio HH:MM (24h) nel fuso orario della prenotazione. L'ora di fine è time + la durata dello slot dello studio. Deve essere uno slot libero.
^([01]\d|2[0-3]):[0-5]\d$"09:00"client_nameobbligatorioIl nome del cliente. Testo semplice; "<" e ">" non sono consentiti.
^[^<>]*$"Kovács Anna"client_emailobbligatorioL'e-mail del cliente: il destinatario della conferma.
"anna@example.com"client_phoneIl telefono del cliente. Testo semplice.
^[^<>]*$client_descriptionOggetto / note dal cliente. Testo semplice.
^[^<>]*$location_preferenceConsulenza in studio o online. Predefinito "office".
"office" "online" "office"meeting_linkURL della riunione online (http/https), per una consulenza online.
gdpr_consentRegistra il consenso del cliente al trattamento dei dati. Predefinito true (il personale dello studio prenota per conto del cliente).
trueauto_confirmQuando è true (o lo studio ha la conferma automatica attiva), crea la prenotazione già confermata: esegue la sincronizzazione del calendario e invia al cliente una conferma invece di una richiesta. Altrimenti è pending.
falseidempotency_keyStesso ruolo dell'header Idempotency-Key, per i client che non possono inviare header personalizzati. Lettere, cifre, _, -, : o ., al massimo 128 caratteri.
^[A-Za-z0-9_\-:.]{1,128}$"b8f1c2e0-6f7a-4d2e-9c1b-2a3d4e5f6a7b"Risposte
201
Creato.
dataobbligatorioCampi di data
id4321booking_numberNumero di prenotazione leggibile, ad es. "#B-0001".
statuspending = in attesa della conferma dell'avvocato; confirmed = approvata; cancelled/completed; awaiting_payment/expired appartengono al flusso paga-prima-della-conferma.
"pending" "confirmed" "cancelled" "completed" "awaiting_payment" "expired" sourceDa dove proviene la prenotazione. Una prenotazione creata tramite API è "manual".
"flowyer" "website" "embed_widget" "manual" lawyerL'avvocato (user_id da colleagues.list) con cui è fissato l'appuntamento.
Campi di lawyer
user_idnamedateData di calendario nel fuso orario della prenotazione (YYYY-MM-DD), memorizzata letteralmente.
start_timeOra di inizio HH:MM nel fuso orario della prenotazione.
end_timeOra di fine HH:MM nel fuso orario della prenotazione.
startIstante ISO 8601 non ambiguo dell'inizio, composto con il fuso orario della prenotazione. Lo usi per confrontare istanti tra fusi diversi.
endIstante ISO 8601 non ambiguo della fine.
timezoneIl fuso orario della prenotazione (booking_settings.timezone), ad es. "Europe/Budapest". Governa date, start_time e end_time.
location_preferenceSe la consulenza è in studio o online.
"office" "online" meeting_linkURL della riunione online, quando impostato.
clientIl cliente esterno che ha prenotato: nome, e-mail, telefono e l'oggetto/note. Dati personali, solo per il personale dello studio.
Campi di client
nameemailphonedescriptiongdpr_consentSe è registrato il consenso del cliente al trattamento dei dati.
gdpr_consent_atQuando è stato registrato il consenso.
cancel_reasonMotivo registrato all'annullamento.
paymentStato di pagamento di sola lettura. L'API non modifica mai il pagamento; le commissioni di prenotazione sono gestite in Flowyer.
Campi di payment
status"none" "awaiting" "partial" "paid" "refunded" method"card" "transfer" amountcurrencyinvoice_numberconfirmed_atcancelled_atcreated_atupdated_atPassi questo a bookings.update / bookings.confirm / bookings.cancel come expected_updated_at.
created_via_apiPresente quando un agente esterno ha creato la prenotazione tramite questa API.
Campi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduseratcreatedtrue
200
Replay idempotente: questo Idempotency-Key (o, senza chiave, una richiesta identica entro 120 secondi) ha già creato il record; viene restituito di nuovo, nulla di nuovo è stato creato.
dataobbligatorioCampi di data
id4321booking_numberNumero di prenotazione leggibile, ad es. "#B-0001".
statuspending = in attesa della conferma dell'avvocato; confirmed = approvata; cancelled/completed; awaiting_payment/expired appartengono al flusso paga-prima-della-conferma.
"pending" "confirmed" "cancelled" "completed" "awaiting_payment" "expired" sourceDa dove proviene la prenotazione. Una prenotazione creata tramite API è "manual".
"flowyer" "website" "embed_widget" "manual" lawyerL'avvocato (user_id da colleagues.list) con cui è fissato l'appuntamento.
Campi di lawyer
user_idnamedateData di calendario nel fuso orario della prenotazione (YYYY-MM-DD), memorizzata letteralmente.
start_timeOra di inizio HH:MM nel fuso orario della prenotazione.
end_timeOra di fine HH:MM nel fuso orario della prenotazione.
startIstante ISO 8601 non ambiguo dell'inizio, composto con il fuso orario della prenotazione. Lo usi per confrontare istanti tra fusi diversi.
endIstante ISO 8601 non ambiguo della fine.
timezoneIl fuso orario della prenotazione (booking_settings.timezone), ad es. "Europe/Budapest". Governa date, start_time e end_time.
location_preferenceSe la consulenza è in studio o online.
"office" "online" meeting_linkURL della riunione online, quando impostato.
clientIl cliente esterno che ha prenotato: nome, e-mail, telefono e l'oggetto/note. Dati personali, solo per il personale dello studio.
Campi di client
nameemailphonedescriptiongdpr_consentSe è registrato il consenso del cliente al trattamento dei dati.
gdpr_consent_atQuando è stato registrato il consenso.
cancel_reasonMotivo registrato all'annullamento.
paymentStato di pagamento di sola lettura. L'API non modifica mai il pagamento; le commissioni di prenotazione sono gestite in Flowyer.
Campi di payment
status"none" "awaiting" "partial" "paid" "refunded" method"card" "transfer" amountcurrencyinvoice_numberconfirmed_atcancelled_atcreated_atupdated_atPassi questo a bookings.update / bookings.confirm / bookings.cancel come expected_updated_at.
created_via_apiPresente quando un agente esterno ha creato la prenotazione tramite questa API.
Campi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduseratcreatedfalseidempotent_replaytrue
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente. replay_not_visible: questo Idempotency-Key (o, senza chiave, una richiesta identica) ha già creato il record (details.record_id), ma da allora è stato eliminato o non è visibile all'utente; nulla di nuovo è stato creato, non lo ricrei.
replay_not_visible: questo Idempotency-Key (o, senza chiave, una richiesta identica) ha già creato il record (details.record_id), ma da allora è stato eliminato o non è visibile all'utente; nulla di nuovo è stato creato, non lo ricrei.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
409
L'Idempotency-Key è stato usato per un altro tipo di risorsa (idempotency_key_reused), oppure, senza chiave, una richiesta identica è in fase di elaborazione in questo momento (duplicate_in_progress; riprovi a breve).
idempotency_key_reused), oppure, senza chiave, una richiesta identica è in fase di elaborazione in questo momento (duplicate_in_progress; riprovi a breve).
413
Il corpo della richiesta è troppo grande (request_too_large).
request_too_large).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl -X POST 'https://www.flowyer.it/api/agent/bookings' \
-H 'Authorization: Bearer flw_...' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: 7f3a9c21-1b2c-4d5e-8f90-0a1b2c3d4e5f' \
-d '{
"user_id": 42,
"date": "2026-03-02",
"time": "09:00",
"client_name": "Kovács Anna",
"client_email": "anna@example.com"
}'
const response = await fetch("https://www.flowyer.it/api/agent/bookings", {
method: "POST",
headers: {
"Authorization": "Bearer flw_...",
"Content-Type": "application/json",
"Idempotency-Key": crypto.randomUUID(),
},
body: JSON.stringify({
"user_id": 42,
"date": "2026-03-02",
"time": "09:00",
"client_name": "Kovács Anna",
"client_email": "anna@example.com"
}),
});
const result = await response.json();
import uuid
import requests
response = requests.post(
"https://www.flowyer.it/api/agent/bookings",
headers={
"Authorization": "Bearer flw_...",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"user_id": 42,
"date": "2026-03-02",
"time": "09:00",
"client_name": "Kovács Anna",
"client_email": "anna@example.com",
},
timeout=30,
)
print(response.status_code, response.json())
{
"user_id": 42,
"date": "2026-03-02",
"time": "09:00",
"client_name": "Kovács Anna",
"client_email": "anna@example.com"
}
Esempi di risposta
{
"data": {
"id": 4321,
"booking_number": "string",
"status": "pending",
"source": "flowyer",
"lawyer": {
"user_id": 1234,
"name": "string"
},
"date": "2026-10-30",
"start_time": "string",
"end_time": "string",
"start": "2026-10-30T09:15:00+01:00",
"end": "2026-10-30T09:15:00+01:00",
"timezone": "string",
"location_preference": "office",
"meeting_link": "string",
"client": {
"name": "string",
"email": "info@example.hu",
"phone": "string",
"description": "string"
},
"gdpr_consent": true,
"gdpr_consent_at": "2026-10-30T09:15:00+01:00",
"cancel_reason": "string",
"payment": {
"status": "none",
"method": "card",
"amount": 0,
"currency": "string",
"invoice_number": "string"
},
"confirmed_at": "2026-10-30T09:15:00+01:00",
"cancelled_at": "2026-10-30T09:15:00+01:00",
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
}
},
"created": true
}
{
"data": {
"id": 4321,
"booking_number": "string",
"status": "pending",
"source": "flowyer",
"lawyer": {
"user_id": 1234,
"name": "string"
},
"date": "2026-10-30",
"start_time": "string",
"end_time": "string",
"start": "2026-10-30T09:15:00+01:00",
"end": "2026-10-30T09:15:00+01:00",
"timezone": "string",
"location_preference": "office",
"meeting_link": "string",
"client": {
"name": "string",
"email": "info@example.hu",
"phone": "string",
"description": "string"
},
"gdpr_consent": true,
"gdpr_consent_at": "2026-10-30T09:15:00+01:00",
"cancel_reason": "string",
"payment": {
"status": "none",
"method": "card",
"amount": 0,
"currency": "string",
"invoice_number": "string"
},
"confirmed_at": "2026-10-30T09:15:00+01:00",
"cancelled_at": "2026-10-30T09:15:00+01:00",
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
}
},
"created": false,
"idempotent_replay": true
}
{
"error": "validation_failed",
"message": "The request is invalid. See \"details.fields\" for the field-level errors.",
"message_localized": "La richiesta non è valida. Gli errori per campo sono in \"details.fields\".",
"locale": "it",
"details": {
"fields": {
"user_id": [
"Il campo user id è obbligatorio."
]
}
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Aggiorna la prenotazione
/api/agent/bookings/{id}
Riprogramma (data + ora insieme, con nuova verifica di uno slot libero) o modifica una prenotazione (telefono, note, link della riunione, luogo). Scrive solo i campi che invia. Notifica all'avvocato una riprogrammazione, mai al cliente. Passi expected_updated_at dalla sua ultima lettura; una scrittura obsoleta risponde 409.
Parametri di percorso
idobbligatorioId del record da modificare.
Corpo della richiesta application/json
expected_updated_atIl valore updated_at dalla sua lettura più recente di questo record (obbligatorio ogni volta che il record ne ha uno). Se il record è cambiato da allora (un collega lo ha modificato), l'API risponde 409 e deve rileggere prima di riprovare. Un record legacy il cui updated_at è null accetta null.
dateNuovo giorno (YYYY-MM-DD) nel fuso orario della prenotazione. Invii data E ora insieme per riprogrammare.
"2026-03-05"timeNuova ora di inizio HH:MM. L'ora di fine viene ricalcolata dalla durata dello slot dello studio. Invii data E ora insieme.
^([01]\d|2[0-3]):[0-5]\d$"11:00"client_phoneIl telefono del cliente. Testo semplice. "" lo cancella.
^[^<>]*$client_descriptionOggetto / note. Testo semplice. "" lo cancella.
^[^<>]*$meeting_linkURL della riunione online (http/https). "" lo cancella.
location_preferenceConsulenza in studio o online.
"office" "online" Risposte
200
Aggiornato.
dataobbligatorioCampi di data
id4321booking_numberNumero di prenotazione leggibile, ad es. "#B-0001".
statuspending = in attesa della conferma dell'avvocato; confirmed = approvata; cancelled/completed; awaiting_payment/expired appartengono al flusso paga-prima-della-conferma.
"pending" "confirmed" "cancelled" "completed" "awaiting_payment" "expired" sourceDa dove proviene la prenotazione. Una prenotazione creata tramite API è "manual".
"flowyer" "website" "embed_widget" "manual" lawyerL'avvocato (user_id da colleagues.list) con cui è fissato l'appuntamento.
Campi di lawyer
user_idnamedateData di calendario nel fuso orario della prenotazione (YYYY-MM-DD), memorizzata letteralmente.
start_timeOra di inizio HH:MM nel fuso orario della prenotazione.
end_timeOra di fine HH:MM nel fuso orario della prenotazione.
startIstante ISO 8601 non ambiguo dell'inizio, composto con il fuso orario della prenotazione. Lo usi per confrontare istanti tra fusi diversi.
endIstante ISO 8601 non ambiguo della fine.
timezoneIl fuso orario della prenotazione (booking_settings.timezone), ad es. "Europe/Budapest". Governa date, start_time e end_time.
location_preferenceSe la consulenza è in studio o online.
"office" "online" meeting_linkURL della riunione online, quando impostato.
clientIl cliente esterno che ha prenotato: nome, e-mail, telefono e l'oggetto/note. Dati personali, solo per il personale dello studio.
Campi di client
nameemailphonedescriptiongdpr_consentSe è registrato il consenso del cliente al trattamento dei dati.
gdpr_consent_atQuando è stato registrato il consenso.
cancel_reasonMotivo registrato all'annullamento.
paymentStato di pagamento di sola lettura. L'API non modifica mai il pagamento; le commissioni di prenotazione sono gestite in Flowyer.
Campi di payment
status"none" "awaiting" "partial" "paid" "refunded" method"card" "transfer" amountcurrencyinvoice_numberconfirmed_atcancelled_atcreated_atupdated_atPassi questo a bookings.update / bookings.confirm / bookings.cancel come expected_updated_at.
created_via_apiPresente quando un agente esterno ha creato la prenotazione tramite questa API.
Campi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduseratupdatedtrue
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
409
Il record è cambiato da quando lo ha letto (record_conflict: expected_updated_at non corrisponde più; lo rilegga e riprovi con il nuovo updated_at).
record_conflict: expected_updated_at non corrisponde più; lo rilegga e riprovi con il nuovo updated_at).
413
Il corpo della richiesta è troppo grande (request_too_large).
request_too_large).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl -X PATCH 'https://www.flowyer.it/api/agent/bookings/1234' \
-H 'Authorization: Bearer flw_...' \
-H 'Content-Type: application/json' \
-d '{
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"date": "2026-03-05",
"time": "11:00"
}'
const response = await fetch("https://www.flowyer.it/api/agent/bookings/1234", {
method: "PATCH",
headers: {
"Authorization": "Bearer flw_...",
"Content-Type": "application/json",
},
body: JSON.stringify({
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"date": "2026-03-05",
"time": "11:00"
}),
});
const result = await response.json();
import requests
response = requests.patch(
"https://www.flowyer.it/api/agent/bookings/1234",
headers={
"Authorization": "Bearer flw_...",
},
json={
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"date": "2026-03-05",
"time": "11:00",
},
timeout=30,
)
print(response.status_code, response.json())
{
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"date": "2026-03-05",
"time": "11:00"
}
Esempi di risposta
{
"data": {
"id": 4321,
"booking_number": "string",
"status": "pending",
"source": "flowyer",
"lawyer": {
"user_id": 1234,
"name": "string"
},
"date": "2026-10-30",
"start_time": "string",
"end_time": "string",
"start": "2026-10-30T09:15:00+01:00",
"end": "2026-10-30T09:15:00+01:00",
"timezone": "string",
"location_preference": "office",
"meeting_link": "string",
"client": {
"name": "string",
"email": "info@example.hu",
"phone": "string",
"description": "string"
},
"gdpr_consent": true,
"gdpr_consent_at": "2026-10-30T09:15:00+01:00",
"cancel_reason": "string",
"payment": {
"status": "none",
"method": "card",
"amount": 0,
"currency": "string",
"invoice_number": "string"
},
"confirmed_at": "2026-10-30T09:15:00+01:00",
"cancelled_at": "2026-10-30T09:15:00+01:00",
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
}
},
"updated": true
}
{
"error": "record_conflict",
"message": "The record changed since you read it (someone edited it). Read it again and retry with the new updated_at.",
"message_localized": "Il record è cambiato dall'ultima lettura (qualcuno lo ha modificato). Rileggerlo e riprovare con il nuovo updated_at.",
"locale": "it",
"details": {
"current_updated_at": "2026-10-30T10:42:05+01:00",
"reason": "modified_since_read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Conferma la prenotazione
/api/agent/bookings/{id}/confirm
Conferma una prenotazione pending e INVIA UN'EMAIL AL CLIENTE con la conferma (con il link della riunione per una online). Solo una prenotazione pending può essere confermata; qualsiasi altro stato risponde 409, quindi un nuovo tentativo non invia mai di nuovo l'email. Facoltativamente passi expected_updated_at come token di blocco.
Parametri di percorso
idobbligatorioId della prenotazione.
4321Corpo della richiesta application/json
expected_updated_atToken opzionale di blocco ottimistico: l'updated_at dalla sua ultima lettura. Se la prenotazione è cambiata da allora, l'API risponde 409 e Lei rilegge prima di riprovare.
meeting_linkURL della riunione online (http/https) da impostare sulla prenotazione prima che l'e-mail di conferma venga inviata.
Risposte
200
OK.
dataobbligatorioCampi di data
id4321booking_numberNumero di prenotazione leggibile, ad es. "#B-0001".
statuspending = in attesa della conferma dell'avvocato; confirmed = approvata; cancelled/completed; awaiting_payment/expired appartengono al flusso paga-prima-della-conferma.
"pending" "confirmed" "cancelled" "completed" "awaiting_payment" "expired" sourceDa dove proviene la prenotazione. Una prenotazione creata tramite API è "manual".
"flowyer" "website" "embed_widget" "manual" lawyerL'avvocato (user_id da colleagues.list) con cui è fissato l'appuntamento.
Campi di lawyer
user_idnamedateData di calendario nel fuso orario della prenotazione (YYYY-MM-DD), memorizzata letteralmente.
start_timeOra di inizio HH:MM nel fuso orario della prenotazione.
end_timeOra di fine HH:MM nel fuso orario della prenotazione.
startIstante ISO 8601 non ambiguo dell'inizio, composto con il fuso orario della prenotazione. Lo usi per confrontare istanti tra fusi diversi.
endIstante ISO 8601 non ambiguo della fine.
timezoneIl fuso orario della prenotazione (booking_settings.timezone), ad es. "Europe/Budapest". Governa date, start_time e end_time.
location_preferenceSe la consulenza è in studio o online.
"office" "online" meeting_linkURL della riunione online, quando impostato.
clientIl cliente esterno che ha prenotato: nome, e-mail, telefono e l'oggetto/note. Dati personali, solo per il personale dello studio.
Campi di client
nameemailphonedescriptiongdpr_consentSe è registrato il consenso del cliente al trattamento dei dati.
gdpr_consent_atQuando è stato registrato il consenso.
cancel_reasonMotivo registrato all'annullamento.
paymentStato di pagamento di sola lettura. L'API non modifica mai il pagamento; le commissioni di prenotazione sono gestite in Flowyer.
Campi di payment
status"none" "awaiting" "partial" "paid" "refunded" method"card" "transfer" amountcurrencyinvoice_numberconfirmed_atcancelled_atcreated_atupdated_atPassi questo a bookings.update / bookings.confirm / bookings.cancel come expected_updated_at.
created_via_apiPresente quando un agente esterno ha creato la prenotazione tramite questa API.
Campi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduserat
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
413
Il corpo della richiesta è troppo grande (request_too_large).
request_too_large).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl -X POST 'https://www.flowyer.it/api/agent/bookings/4321/confirm' \
-H 'Authorization: Bearer flw_...' \
-H 'Content-Type: application/json' \
-d '{
"expected_updated_at": "2026-10-30T09:15:00+01:00"
}'
const response = await fetch("https://www.flowyer.it/api/agent/bookings/4321/confirm", {
method: "POST",
headers: {
"Authorization": "Bearer flw_...",
"Content-Type": "application/json",
},
body: JSON.stringify({
"expected_updated_at": "2026-10-30T09:15:00+01:00"
}),
});
const result = await response.json();
import requests
response = requests.post(
"https://www.flowyer.it/api/agent/bookings/4321/confirm",
headers={
"Authorization": "Bearer flw_...",
},
json={
"expected_updated_at": "2026-10-30T09:15:00+01:00",
},
timeout=30,
)
print(response.status_code, response.json())
{
"expected_updated_at": "2026-10-30T09:15:00+01:00"
}
Esempi di risposta
{
"data": {
"id": 4321,
"booking_number": "string",
"status": "pending",
"source": "flowyer",
"lawyer": {
"user_id": 1234,
"name": "string"
},
"date": "2026-10-30",
"start_time": "string",
"end_time": "string",
"start": "2026-10-30T09:15:00+01:00",
"end": "2026-10-30T09:15:00+01:00",
"timezone": "string",
"location_preference": "office",
"meeting_link": "string",
"client": {
"name": "string",
"email": "info@example.hu",
"phone": "string",
"description": "string"
},
"gdpr_consent": true,
"gdpr_consent_at": "2026-10-30T09:15:00+01:00",
"cancel_reason": "string",
"payment": {
"status": "none",
"method": "card",
"amount": 0,
"currency": "string",
"invoice_number": "string"
},
"confirmed_at": "2026-10-30T09:15:00+01:00",
"cancelled_at": "2026-10-30T09:15:00+01:00",
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
}
}
}
{
"error": "not_found",
"message": "The record was not found, or it is not visible to the user who owns this API key.",
"message_localized": "Il record non è stato trovato oppure non è visibile al titolare di questa chiave API.",
"locale": "it",
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Annulla la prenotazione
/api/agent/bookings/{id}/cancel
Annulla una prenotazione e INVIA UN'EMAIL AL CLIENTE (e all'avvocato) con l'annullamento. Una prenotazione già annullata o completata risponde 409, quindi un nuovo tentativo non invia mai di nuovo l'email. Una prenotazione pagata viene annullata ma mai rimborsata (se ne occupa lo studio). Facoltativamente passi expected_updated_at.
Parametri di percorso
idobbligatorioId della prenotazione.
4321Corpo della richiesta application/json
expected_updated_atToken opzionale di blocco ottimistico: l'updated_at dalla sua ultima lettura. Se la prenotazione è cambiata da allora, l'API risponde 409.
reasonMotivo registrato come cancel_reason e mostrato nell'e-mail di annullamento. Testo semplice; "<" e ">" non sono consentiti.
^[^<>]*$Risposte
200
OK.
dataobbligatorioCampi di data
id4321booking_numberNumero di prenotazione leggibile, ad es. "#B-0001".
statuspending = in attesa della conferma dell'avvocato; confirmed = approvata; cancelled/completed; awaiting_payment/expired appartengono al flusso paga-prima-della-conferma.
"pending" "confirmed" "cancelled" "completed" "awaiting_payment" "expired" sourceDa dove proviene la prenotazione. Una prenotazione creata tramite API è "manual".
"flowyer" "website" "embed_widget" "manual" lawyerL'avvocato (user_id da colleagues.list) con cui è fissato l'appuntamento.
Campi di lawyer
user_idnamedateData di calendario nel fuso orario della prenotazione (YYYY-MM-DD), memorizzata letteralmente.
start_timeOra di inizio HH:MM nel fuso orario della prenotazione.
end_timeOra di fine HH:MM nel fuso orario della prenotazione.
startIstante ISO 8601 non ambiguo dell'inizio, composto con il fuso orario della prenotazione. Lo usi per confrontare istanti tra fusi diversi.
endIstante ISO 8601 non ambiguo della fine.
timezoneIl fuso orario della prenotazione (booking_settings.timezone), ad es. "Europe/Budapest". Governa date, start_time e end_time.
location_preferenceSe la consulenza è in studio o online.
"office" "online" meeting_linkURL della riunione online, quando impostato.
clientIl cliente esterno che ha prenotato: nome, e-mail, telefono e l'oggetto/note. Dati personali, solo per il personale dello studio.
Campi di client
nameemailphonedescriptiongdpr_consentSe è registrato il consenso del cliente al trattamento dei dati.
gdpr_consent_atQuando è stato registrato il consenso.
cancel_reasonMotivo registrato all'annullamento.
paymentStato di pagamento di sola lettura. L'API non modifica mai il pagamento; le commissioni di prenotazione sono gestite in Flowyer.
Campi di payment
status"none" "awaiting" "partial" "paid" "refunded" method"card" "transfer" amountcurrencyinvoice_numberconfirmed_atcancelled_atcreated_atupdated_atPassi questo a bookings.update / bookings.confirm / bookings.cancel come expected_updated_at.
created_via_apiPresente quando un agente esterno ha creato la prenotazione tramite questa API.
Campi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduserat
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
413
Il corpo della richiesta è troppo grande (request_too_large).
request_too_large).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl -X POST 'https://www.flowyer.it/api/agent/bookings/4321/cancel' \
-H 'Authorization: Bearer flw_...' \
-H 'Content-Type: application/json' \
-d '{
"expected_updated_at": "2026-10-30T09:15:00+01:00"
}'
const response = await fetch("https://www.flowyer.it/api/agent/bookings/4321/cancel", {
method: "POST",
headers: {
"Authorization": "Bearer flw_...",
"Content-Type": "application/json",
},
body: JSON.stringify({
"expected_updated_at": "2026-10-30T09:15:00+01:00"
}),
});
const result = await response.json();
import requests
response = requests.post(
"https://www.flowyer.it/api/agent/bookings/4321/cancel",
headers={
"Authorization": "Bearer flw_...",
},
json={
"expected_updated_at": "2026-10-30T09:15:00+01:00",
},
timeout=30,
)
print(response.status_code, response.json())
{
"expected_updated_at": "2026-10-30T09:15:00+01:00"
}
Esempi di risposta
{
"data": {
"id": 4321,
"booking_number": "string",
"status": "pending",
"source": "flowyer",
"lawyer": {
"user_id": 1234,
"name": "string"
},
"date": "2026-10-30",
"start_time": "string",
"end_time": "string",
"start": "2026-10-30T09:15:00+01:00",
"end": "2026-10-30T09:15:00+01:00",
"timezone": "string",
"location_preference": "office",
"meeting_link": "string",
"client": {
"name": "string",
"email": "info@example.hu",
"phone": "string",
"description": "string"
},
"gdpr_consent": true,
"gdpr_consent_at": "2026-10-30T09:15:00+01:00",
"cancel_reason": "string",
"payment": {
"status": "none",
"method": "card",
"amount": 0,
"currency": "string",
"invoice_number": "string"
},
"confirmed_at": "2026-10-30T09:15:00+01:00",
"cancelled_at": "2026-10-30T09:15:00+01:00",
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
}
}
}
{
"error": "not_found",
"message": "The record was not found, or it is not visible to the user who owns this API key.",
"message_localized": "Il record non è stato trovato oppure non è visibile al titolare di questa chiave API.",
"locale": "it",
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Ticket di assistenza
Elenca i ticket
/api/agent/tickets
Elenca i ticket di assistenza che l'utente può vedere (visibilità per casella di posta), prima l'attività più recente. Filtra per stato (predefinito open_states = new+open+pending; "all" include closed), casella di posta, assegnatario, email del richiedente, o testo libero su oggetto/richiedente/numero di ticket.
Parametri di query
statusopen_states (predefinito) = new+open+pending (la vista predefinita del web); "all" include closed; oppure uno stato esatto.
"new" "open" "pending" "closed" "open_states" "all" "open_states"mailbox_idSolo i ticket di questa casella di posta. Una casella di posta che l'utente non può vedere produce un elenco vuoto (mai una fuga di dati).
7assigned_to_user_idSolo i ticket assegnati a questo collega (id da colleagues.list); 0 = solo i ticket non assegnati. Ometta per qualsiasi assegnatario.
requester_emailSolo i ticket la cui email del richiedente esterno corrisponde esattamente (ignorando maiuscole/minuscole).
"ugyfel@example.com"qRicerca a testo libero su oggetto, nome/email del richiedente e numero di ticket (maiuscole/minuscole ignorate).
"számla"limitDimensione della pagina, 1-100. Valore predefinito 25.
2525offsetNumero di record da saltare. Usi offset + limit della pagina precedente per ottenere quella successiva; pagination.total è il conteggio totale.
00Risposte
200
OK.
dataobbligatorioCampi di data
idId del ticket (da usare con tickets.get / tickets.update).
4321ticket_numberNumero di ticket leggibile, ad es. FLW-000123.
subjectstatus"new" "open" "pending" "closed" priority"low" "normal" "high" mailboxLa casella di posta attraverso cui è arrivato il ticket (registro centrale).
Campi di mailbox
idemaildisplay_namerequesterLa persona esterna che ha scritto.
Campi di requester
emailnameassigned_toIl collega a cui è assegnato il ticket, oppure null quando non assegnato.
Campi di assigned_to
user_idnamematterLa pratica collegata al ticket, oppure null.
Campi di matter
idcase_numberclientIl cliente collegato al ticket, oppure null.
Campi di client
idnamelast_message_atOra dell'attività più recente del thread; l'elenco è ordinato in base ad essa, prima i più recenti.
created_atupdated_atPassi questo a tickets.update come expected_updated_at.
created_via_apiPresente quando il ticket è stato creato tramite questa API.
Campi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduseratpaginationobbligatorioCampi di pagination
limitobbligatoriooffsetobbligatoriototalobbligatorioNumero totale di record corrispondenti.
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl 'https://www.flowyer.it/api/agent/tickets?mailbox_id=7&requester_email=ugyfel%40example.com&q=sz%C3%A1mla' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.it/api/agent/tickets?mailbox_id=7&requester_email=ugyfel%40example.com&q=sz%C3%A1mla", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.it/api/agent/tickets?mailbox_id=7&requester_email=ugyfel%40example.com&q=sz%C3%A1mla",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Esempi di risposta
{
"data": [
{
"id": 4321,
"ticket_number": "string",
"subject": "string",
"status": "new",
"priority": "low",
"mailbox": {
"id": 1234,
"email": "info@example.hu",
"display_name": "string"
},
"requester": {
"email": "info@example.hu",
"name": "string"
},
"assigned_to": {
"user_id": 1234,
"name": "string"
},
"matter": {
"id": 1234,
"case_number": "string"
},
"client": {
"id": 1234,
"name": "string"
},
"last_message_at": "2026-10-30T09:15:00+01:00",
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
}
}
],
"pagination": {
"limit": 25,
"offset": 0,
"total": 1
}
}
{
"error": "scope_missing",
"message": "This API key does not have the \"tickets:read\" permission. The permissions of an existing key cannot be changed, so the key owner needs to create a new key with this permission in Flowyer under Settings > API keys and use it in place of the old one.",
"message_localized": "Questa chiave API non ha il permesso \"tickets:read\". I permessi di una chiave esistente non possono essere modificati, quindi il titolare della chiave deve creare in Flowyer, in Impostazioni > Chiavi API, una nuova chiave con questo permesso e usarla al posto di quella vecchia.",
"locale": "it",
"details": {
"required_scope": "tickets:read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Ottieni il ticket
/api/agent/tickets/{id}
Restituisce un ticket di assistenza con il suo thread di messaggi (prima i più vecchi) e la pratica/il cliente collegati. Risponde 404 quando il ticket non esiste o si trova in una casella di posta che l'utente non può vedere. La lettura non modifica mai il ticket (un ticket NEW non viene portato a OPEN).
Parametri di percorso
idobbligatorioId del ticket.
4321Parametri di query
messages_limitRestituisce solo gli N messaggi più recenti del thread (comunque presentati prima i più vecchi). Ometta per l'intero thread.
Risposte
200
OK.
dataobbligatorioCampi di data
idId del ticket (da usare con tickets.get / tickets.update).
4321ticket_numberNumero di ticket leggibile, ad es. FLW-000123.
subjectstatus"new" "open" "pending" "closed" priority"low" "normal" "high" mailboxLa casella di posta attraverso cui è arrivato il ticket (registro centrale).
Campi di mailbox
idemaildisplay_namerequesterLa persona esterna che ha scritto.
Campi di requester
emailnameassigned_toIl collega a cui è assegnato il ticket, oppure null quando non assegnato.
Campi di assigned_to
user_idnamematterLa pratica collegata al ticket, oppure null.
Campi di matter
idcase_numberclientIl cliente collegato al ticket, oppure null.
Campi di client
idnamelast_message_atOra dell'attività più recente del thread; l'elenco è ordinato in base ad essa, prima i più recenti.
created_atupdated_atPassi questo a tickets.update come expected_updated_at.
created_via_apiPresente quando il ticket è stato creato tramite questa API.
Campi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduseratmessagesIl thread di messaggi, prima i più vecchi.
Campi di messages
iddirectionin = dal richiedente, out = risposta/conferma automatica inviata dalla casella di posta, note = interno.
"in" "out" "note" fromCampi di from
emailnametoCampi di to
emailnameccCampi di cc
emailnamesent_statusStato di consegna di un messaggio in uscita; null per in/note.
"pending" "sent" "failed" "scheduled" body_textCorpo del messaggio in testo semplice. Il corpo HTML è volutamente omesso per mantenere compatta la conversazione; se il testo memorizzato è vuoto, viene ricavato dall'HTML.
has_attachmentsauthorIl collega che ha scritto un messaggio out/note; null per un messaggio in entrata.
Campi di author
user_idnamecreated_atlinked_matterLa pratica collegata al ticket (come matter).
Campi di linked_matter
idcase_numberlinked_clientIl cliente collegato al ticket (come client).
Campi di linked_client
idname
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl 'https://www.flowyer.it/api/agent/tickets/4321' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.it/api/agent/tickets/4321", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.it/api/agent/tickets/4321",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Esempi di risposta
{
"data": {
"id": 4321,
"ticket_number": "string",
"subject": "string",
"status": "new",
"priority": "low",
"mailbox": {
"id": 1234,
"email": "info@example.hu",
"display_name": "string"
},
"requester": {
"email": "info@example.hu",
"name": "string"
},
"assigned_to": {
"user_id": 1234,
"name": "string"
},
"matter": {
"id": 1234,
"case_number": "string"
},
"client": {
"id": 1234,
"name": "string"
},
"last_message_at": "2026-10-30T09:15:00+01:00",
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
},
"messages": [
{
"id": 1234,
"direction": "in",
"from": {
"email": "info@example.hu",
"name": "string"
},
"to": [
{
"email": "info@example.hu",
"name": "string"
}
],
"cc": [
{
"email": "info@example.hu",
"name": "string"
}
],
"sent_status": "pending",
"body_text": "string",
"has_attachments": true,
"author": {
"user_id": 1234,
"name": "string"
},
"created_at": "2026-10-30T09:15:00+01:00"
}
],
"linked_matter": {
"id": 1234,
"case_number": "string"
},
"linked_client": {
"id": 1234,
"name": "string"
}
}
}
{
"error": "not_found",
"message": "The record was not found, or it is not visible to the user who owns this API key.",
"message_localized": "Il record non è stato trovato oppure non è visibile al titolare di questa chiave API.",
"locale": "it",
"details": {
"record_type": "ticket",
"record_id": 4321
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Rispondi al ticket
/api/agent/tickets/{id}/reply
Risponde a un ticket di assistenza e INVIA la risposta via email al richiedente esterno (attraverso la casella di posta del ticket). Il corpo è HTML formattato, sanificato lato server prima della memorizzazione. Un nuovo tentativo con lo stesso Idempotency-Key non invia mai una seconda email.
Parametri di percorso
idobbligatorioId del ticket (deve essere visibile tramite l'ACL della casella di posta).
4321Parametri di intestazione
Idempotency-KeyConsigliato a ogni creazione. Un valore univoco per operazione logica (ad es. un UUID). Lo stesso valore restituisce lo stesso record: riprovare con esso restituisce il record creato la prima volta invece di crearne un secondo. Valori diversi creano sempre record diversi. I client che non possono inviare header possono passare lo stesso valore nel campo del corpo idempotency_key. Lettere, cifre, _, -, : o ., al massimo 128 caratteri.
^[A-Za-z0-9_\-:.]{1,128}$Corpo della richiesta application/json
body_htmlobbligatorioLa risposta, HTML formattato (come lo produce TinyMCE). Ripulito lato server con HTMLPurifier prima della memorizzazione e prima dell'invio. Al massimo 100000 caratteri; rifiutato se la sanificazione non lascia nulla.
"<p>Köszönjük megkeresését, csatoltan küldjük a választ.</p>"ccDestinatari aggiuntivi in Cc (al massimo 10). Il richiedente e la casella di posta sono esclusi automaticamente; un indirizzo non valido risponde 422.
statusStato del ticket da impostare dopo aver risposto (predefinito "pending" = in attesa del richiedente). Registra un evento di cambio stato.
"new" "open" "pending" "closed" "pending"append_signatureAggiunge la firma del ticket salvata dall'utente della chiave solo alla posta in USCITA (mai memorizzata nel thread).
falseidempotency_keyStesso ruolo dell'header Idempotency-Key, per i client che non possono inviare header personalizzati. Lettere, cifre, _, -, : o ., al massimo 128 caratteri.
^[A-Za-z0-9_\-:.]{1,128}$"b8f1c2e0-6f7a-4d2e-9c1b-2a3d4e5f6a7b"Risposte
201
Creato.
dataobbligatorioCampi di data
ticket_id4321message_idId della riga ticket_messages in uscita creata.
98765directionSempre "out".
sent_status"pending" al momento della creazione; l'invio asincrono lo porta in seguito a sent/failed.
"pending" "sent" "failed" "scheduled" statusLo stato del ticket dopo la risposta.
"new" "open" "pending" "closed" created_atcreated_via_apiPresente quando la risposta è stata creata tramite questa API.
Campi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduseratcreatedtrue
200
Replay idempotente: questo Idempotency-Key (o, senza chiave, una richiesta identica entro 120 secondi) ha già creato il record; viene restituito di nuovo, nulla di nuovo è stato creato.
dataobbligatorioCampi di data
ticket_id4321message_idId della riga ticket_messages in uscita creata.
98765directionSempre "out".
sent_status"pending" al momento della creazione; l'invio asincrono lo porta in seguito a sent/failed.
"pending" "sent" "failed" "scheduled" statusLo stato del ticket dopo la risposta.
"new" "open" "pending" "closed" created_atcreated_via_apiPresente quando la risposta è stata creata tramite questa API.
Campi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduseratcreatedfalseidempotent_replaytrue
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente. replay_not_visible: questo Idempotency-Key (o, senza chiave, una richiesta identica) ha già creato il record (details.record_id), ma da allora è stato eliminato o non è visibile all'utente; nulla di nuovo è stato creato, non lo ricrei.
replay_not_visible: questo Idempotency-Key (o, senza chiave, una richiesta identica) ha già creato il record (details.record_id), ma da allora è stato eliminato o non è visibile all'utente; nulla di nuovo è stato creato, non lo ricrei.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
409
L'Idempotency-Key è stato usato per un altro tipo di risorsa (idempotency_key_reused), oppure, senza chiave, una richiesta identica è in fase di elaborazione in questo momento (duplicate_in_progress; riprovi a breve).
idempotency_key_reused), oppure, senza chiave, una richiesta identica è in fase di elaborazione in questo momento (duplicate_in_progress; riprovi a breve).
413
Il corpo della richiesta è troppo grande (request_too_large).
request_too_large).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl -X POST 'https://www.flowyer.it/api/agent/tickets/4321/reply' \
-H 'Authorization: Bearer flw_...' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: 7f3a9c21-1b2c-4d5e-8f90-0a1b2c3d4e5f' \
-d '{
"body_html": "<p>Köszönjük megkeresését, csatoltan küldjük a választ.</p>"
}'
const response = await fetch("https://www.flowyer.it/api/agent/tickets/4321/reply", {
method: "POST",
headers: {
"Authorization": "Bearer flw_...",
"Content-Type": "application/json",
"Idempotency-Key": crypto.randomUUID(),
},
body: JSON.stringify({
"body_html": "<p>Köszönjük megkeresését, csatoltan küldjük a választ.</p>"
}),
});
const result = await response.json();
import uuid
import requests
response = requests.post(
"https://www.flowyer.it/api/agent/tickets/4321/reply",
headers={
"Authorization": "Bearer flw_...",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"body_html": "<p>Köszönjük megkeresését, csatoltan küldjük a választ.</p>",
},
timeout=30,
)
print(response.status_code, response.json())
{
"body_html": "<p>Köszönjük megkeresését, csatoltan küldjük a választ.</p>"
}
Esempi di risposta
{
"data": {
"ticket_id": 4321,
"message_id": 98765,
"direction": "string",
"sent_status": "pending",
"status": "new",
"created_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
}
},
"created": true
}
{
"data": {
"ticket_id": 4321,
"message_id": 98765,
"direction": "string",
"sent_status": "pending",
"status": "new",
"created_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
}
},
"created": false,
"idempotent_replay": true
}
{
"error": "validation_failed",
"message": "The request is invalid. See \"details.fields\" for the field-level errors.",
"message_localized": "La richiesta non è valida. Gli errori per campo sono in \"details.fields\".",
"locale": "it",
"details": {
"fields": {
"body_html": [
"Il campo body html è obbligatorio."
]
}
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Cambia lo stato del ticket
/api/agent/tickets/{id}
Cambia lo stato di un ticket (new, open, pending o closed). "closed" imposta closed_at; qualsiasi altro stato lo cancella. Passi expected_updated_at dalla sua ultima lettura; una modifica in conflitto risponde 409. Risponde 404 quando il ticket non è visibile.
Parametri di percorso
idobbligatorioId del record da modificare.
Corpo della richiesta application/json
expected_updated_atIl valore updated_at dalla sua lettura più recente di questo record (obbligatorio ogni volta che il record ne ha uno). Se il record è cambiato da allora (un collega lo ha modificato), l'API risponde 409 e deve rileggere prima di riprovare. Un record legacy il cui updated_at è null accetta null.
statusobbligatorioIl nuovo stato. "closed" imposta closed_at; qualsiasi altro stato lo cancella.
"new" "open" "pending" "closed" "open"Risposte
200
Aggiornato.
dataobbligatorioCampi di data
idId del ticket (da usare con tickets.get / tickets.update).
4321ticket_numberNumero di ticket leggibile, ad es. FLW-000123.
subjectstatus"new" "open" "pending" "closed" priority"low" "normal" "high" mailboxLa casella di posta attraverso cui è arrivato il ticket (registro centrale).
Campi di mailbox
idemaildisplay_namerequesterLa persona esterna che ha scritto.
Campi di requester
emailnameassigned_toIl collega a cui è assegnato il ticket, oppure null quando non assegnato.
Campi di assigned_to
user_idnamematterLa pratica collegata al ticket, oppure null.
Campi di matter
idcase_numberclientIl cliente collegato al ticket, oppure null.
Campi di client
idnamelast_message_atOra dell'attività più recente del thread; l'elenco è ordinato in base ad essa, prima i più recenti.
created_atupdated_atPassi questo a tickets.update come expected_updated_at.
created_via_apiPresente quando il ticket è stato creato tramite questa API.
Campi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduseratupdatedtrue
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
409
Il record è cambiato da quando lo ha letto (record_conflict: expected_updated_at non corrisponde più; lo rilegga e riprovi con il nuovo updated_at).
record_conflict: expected_updated_at non corrisponde più; lo rilegga e riprovi con il nuovo updated_at).
413
Il corpo della richiesta è troppo grande (request_too_large).
request_too_large).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl -X PATCH 'https://www.flowyer.it/api/agent/tickets/1234' \
-H 'Authorization: Bearer flw_...' \
-H 'Content-Type: application/json' \
-d '{
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"status": "open"
}'
const response = await fetch("https://www.flowyer.it/api/agent/tickets/1234", {
method: "PATCH",
headers: {
"Authorization": "Bearer flw_...",
"Content-Type": "application/json",
},
body: JSON.stringify({
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"status": "open"
}),
});
const result = await response.json();
import requests
response = requests.patch(
"https://www.flowyer.it/api/agent/tickets/1234",
headers={
"Authorization": "Bearer flw_...",
},
json={
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"status": "open",
},
timeout=30,
)
print(response.status_code, response.json())
{
"expected_updated_at": "2026-10-30T09:15:00+01:00",
"status": "open"
}
Esempi di risposta
{
"data": {
"id": 4321,
"ticket_number": "string",
"subject": "string",
"status": "new",
"priority": "low",
"mailbox": {
"id": 1234,
"email": "info@example.hu",
"display_name": "string"
},
"requester": {
"email": "info@example.hu",
"name": "string"
},
"assigned_to": {
"user_id": 1234,
"name": "string"
},
"matter": {
"id": 1234,
"case_number": "string"
},
"client": {
"id": 1234,
"name": "string"
},
"last_message_at": "2026-10-30T09:15:00+01:00",
"created_at": "2026-10-30T09:15:00+01:00",
"updated_at": "2026-10-30T09:15:00+01:00",
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
}
},
"updated": true
}
{
"error": "record_conflict",
"message": "The record changed since you read it (someone edited it). Read it again and retry with the new updated_at.",
"message_localized": "Il record è cambiato dall'ultima lettura (qualcuno lo ha modificato). Rileggerlo e riprovare con il nuovo updated_at.",
"locale": "it",
"details": {
"current_updated_at": "2026-10-30T10:42:05+01:00",
"reason": "modified_since_read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Portale clienti
Elenca i portali clienti
/api/agent/portals
Elenca i portali clienti (thread) a cui l'utente può accedere: la pratica, i partecipanti lato cliente, i conteggi dei messaggi e dei partecipanti e l'ora dell'ultimo messaggio, prima i più recenti. Facoltativamente filtrati su una sola pratica (matter_id). Una pratica ha al massimo un portale.
Parametri di query
matter_idSolo il portale di questa pratica (404 matter_not_visible quando la pratica non è visibile). Una pratica ha al massimo un portale.
1234limitDimensione della pagina, 1-100. Valore predefinito 25.
2525offsetNumero di record da saltare. Usi offset + limit della pagina precedente per ottenere quella successiva; pagination.total è il conteggio totale.
00Risposte
200
OK.
dataobbligatorioCampi di data
idId del portale (thread) - l'identificatore per portal.messages.list e portal.reply.
57matterLa pratica (causa) a cui appartiene il portale.
Campi di matter
idcase_numberclient_participantsI partecipanti esterni lato cliente con cui lo studio sta comunicando.
Campi di client_participants
namekindclient = un mandante, contact = un contatto del cliente, email = una concessione legacy solo e-mail.
"client" "contact" "email" participant_countNumero di partecipanti attivi (personale e cliente).
message_countNumero di messaggi non eliminati nel thread.
last_message_atQuando è stato pubblicato il messaggio non eliminato più recente, ISO 8601 nel fuso dello studio; null per un thread vuoto.
unread_for_meMessaggi non letti per la riga partecipante dell'utente che agisce; null quando l'utente che agisce non è un partecipante di questo portale.
created_atpaginationobbligatorioCampi di pagination
limitobbligatoriooffsetobbligatoriototalobbligatorioNumero totale di record corrispondenti.
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl 'https://www.flowyer.it/api/agent/portals?matter_id=1234&limit=25' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.it/api/agent/portals?matter_id=1234&limit=25", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.it/api/agent/portals?matter_id=1234&limit=25",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Esempi di risposta
{
"data": [
{
"id": 57,
"matter": {
"id": 1234,
"case_number": "string"
},
"client_participants": [
{
"name": "string",
"kind": "client"
}
],
"participant_count": 0,
"message_count": 0,
"last_message_at": "2026-10-30T09:15:00+01:00",
"unread_for_me": 0,
"created_at": "2026-10-30T09:15:00+01:00"
}
],
"pagination": {
"limit": 25,
"offset": 0,
"total": 1
}
}
{
"error": "scope_missing",
"message": "This API key does not have the \"portal:read\" permission. The permissions of an existing key cannot be changed, so the key owner needs to create a new key with this permission in Flowyer under Settings > API keys and use it in place of the old one.",
"message_localized": "Questa chiave API non ha il permesso \"portal:read\". I permessi di una chiave esistente non possono essere modificati, quindi il titolare della chiave deve creare in Flowyer, in Impostazioni > Chiavi API, una nuova chiave con questo permesso e usarla al posto di quella vecchia.",
"locale": "it",
"details": {
"required_scope": "portal:read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Elenca i messaggi del portale
/api/agent/portals/{id}/messages
Elenca i messaggi di un thread del portale clienti, prima i più vecchi, con l'autore (personale o cliente), il corpo in testo semplice ed eventuali metadati degli allegati. Risponde 404 quando il portale non esiste o non è accessibile. Non contrassegna i messaggi come letti.
Parametri di percorso
idobbligatorioId del portale (deve essere accessibile).
57Parametri di query
include_deletedIncludi i messaggi eliminati (il loro corpo è vuoto). Predefinito false.
falselimitDimensione della pagina, 1-100. Valore predefinito 25.
2525offsetNumero di record da saltare. Usi offset + limit della pagina precedente per ottenere quella successiva; pagination.total è il conteggio totale.
00Risposte
200
OK.
dataobbligatorioCampi di data
idportal_messages.id.
8012authorChi ha scritto il messaggio.
Campi di author
participant_idnamekindstaff = un collega dello studio, client = il cliente esterno.
"staff" "client" directionfrom_firm = un autore del personale, from_client = il cliente esterno.
"from_firm" "from_client" bodyIl messaggio in testo semplice (<br> decodificato in interruzioni di riga). Stringa vuota per un messaggio eliminato.
attachmentMetadati dell'allegato quando il messaggio ha un documento; il suo download è fuori ambito. Null quando non ce n'è nessuno.
Campi di attachment
portal_document_idfile_nameis_deleteddeleted_atcreated_atQuando il messaggio è stato pubblicato, ISO 8601 nel fuso dello studio.
paginationobbligatorioCampi di pagination
limitobbligatoriooffsetobbligatoriototalobbligatorioNumero totale di record corrispondenti.
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl 'https://www.flowyer.it/api/agent/portals/57/messages?limit=25' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.it/api/agent/portals/57/messages?limit=25", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.it/api/agent/portals/57/messages?limit=25",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Esempi di risposta
{
"data": [
{
"id": 8012,
"author": {
"participant_id": 1234,
"name": "string",
"kind": "staff"
},
"direction": "from_firm",
"body": "string",
"attachment": {
"portal_document_id": 1234,
"file_name": "string"
},
"is_deleted": true,
"deleted_at": "2026-10-30T09:15:00+01:00",
"created_at": "2026-10-30T09:15:00+01:00"
}
],
"pagination": {
"limit": 25,
"offset": 0,
"total": 1
}
}
{
"error": "portal_not_visible",
"message": "The client portal :id does not exist, or is not accessible to the user who owns this API key.",
"message_localized": "Il portale clienti :id non esiste o non è accessibile all'utente proprietario di questa chiave API.",
"locale": "it",
"details": {
"portal_id": 57
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Rispondi nel portale clienti
/api/agent/portals/{id}/messages
Pubblica una risposta del personale in un thread del portale clienti. Il cliente la vede nel portale e viene notificato via e-mail (un avviso con magic-link firmato, non il testo); i colleghi ricevono una notifica in-app. Testo semplice, sottoposto a escape alla memorizzazione. 404 quando il portale non è accessibile.
Parametri di percorso
idobbligatorioId del portale in cui rispondere (deve essere accessibile).
57Parametri di intestazione
Idempotency-KeyConsigliato a ogni creazione. Un valore univoco per operazione logica (ad es. un UUID). Lo stesso valore restituisce lo stesso record: riprovare con esso restituisce il record creato la prima volta invece di crearne un secondo. Valori diversi creano sempre record diversi. I client che non possono inviare header possono passare lo stesso valore nel campo del corpo idempotency_key. Lettere, cifre, _, -, : o ., al massimo 128 caratteri.
^[A-Za-z0-9_\-:.]{1,128}$Corpo della richiesta application/json
bodyobbligatorioLa risposta, testo semplice. Le parentesi angolari sono accettate e sottoposte a escape alla memorizzazione. Al massimo 20000 caratteri.
"Tisztelt Ügyfelünk! A beadványt ma benyújtottuk."idempotency_keyStesso ruolo dell'header Idempotency-Key, per i client che non possono inviare header personalizzati. Lettere, cifre, _, -, : o ., al massimo 128 caratteri.
^[A-Za-z0-9_\-:.]{1,128}$"b8f1c2e0-6f7a-4d2e-9c1b-2a3d4e5f6a7b"Risposte
201
Creato.
dataobbligatorioCampi di data
messageLa risposta pubblicata.
Campi di message
id8012authorL'utente del personale che ha pubblicato la risposta.
Campi di author
participant_idnamekindstaff = un collega dello studio, client = il cliente esterno.
"staff" "client" directionSempre "from_firm" per una risposta pubblicata tramite questa API.
"from_firm" "from_client" bodyIl messaggio pubblicato in testo semplice.
created_atportalIl portale (thread) e la sua pratica in cui è stata pubblicata la risposta.
Campi di portal
idmatterCampi di matter
idcase_numbercreated_via_apiProvenienza del messaggio creato tramite questa API.
Campi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduseratcreatedtrue
200
Replay idempotente: questo Idempotency-Key (o, senza chiave, una richiesta identica entro 120 secondi) ha già creato il record; viene restituito di nuovo, nulla di nuovo è stato creato.
dataobbligatorioCampi di data
messageLa risposta pubblicata.
Campi di message
id8012authorL'utente del personale che ha pubblicato la risposta.
Campi di author
participant_idnamekindstaff = un collega dello studio, client = il cliente esterno.
"staff" "client" directionSempre "from_firm" per una risposta pubblicata tramite questa API.
"from_firm" "from_client" bodyIl messaggio pubblicato in testo semplice.
created_atportalIl portale (thread) e la sua pratica in cui è stata pubblicata la risposta.
Campi di portal
idmatterCampi di matter
idcase_numbercreated_via_apiProvenienza del messaggio creato tramite questa API.
Campi di created_via_api
kind"key": creato con una chiave API statica; "oauth": creato da un'app connessa tramite OAuth.
"key" "oauth" key_idId della chiave API (tipo "key") o dell'app connessa (tipo "oauth"); i due sono numerati separatamente.
key_nameNome che l'utente ha assegnato alla chiave API, ad es. "Grok integration", oppure il nome dell'app connessa per il tipo "oauth", ad es. "Claude".
user_iduseratcreatedfalseidempotent_replaytrue
400
Richiesta malformata: corpo JSON non valido, host errato (usi l'host www.) o richiesta illeggibile.
401
La chiave è mancante, non valida, revocata o scaduta, oppure il suo utente non è più attivo.
403
Scope mancante (scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
scope_missing), permesso di modulo Flowyer mancante (module_forbidden), API disabilitata per lo studio, licenza scaduta o studio archiviato.
404
Endpoint sconosciuto, oppure il record non esiste / non è visibile all'utente. replay_not_visible: questo Idempotency-Key (o, senza chiave, una richiesta identica) ha già creato il record (details.record_id), ma da allora è stato eliminato o non è visibile all'utente; nulla di nuovo è stato creato, non lo ricrei.
replay_not_visible: questo Idempotency-Key (o, senza chiave, una richiesta identica) ha già creato il record (details.record_id), ma da allora è stato eliminato o non è visibile all'utente; nulla di nuovo è stato creato, non lo ricrei.
405
Metodo non offerto su questo percorso (DELETE e PUT non lo sono mai; PATCH solo dove è offerto un aggiornamento).
409
L'Idempotency-Key è stato usato per un altro tipo di risorsa (idempotency_key_reused), oppure, senza chiave, una richiesta identica è in fase di elaborazione in questo momento (duplicate_in_progress; riprovi a breve).
idempotency_key_reused), oppure, senza chiave, una richiesta identica è in fase di elaborazione in questo momento (duplicate_in_progress; riprovi a breve).
413
Il corpo della richiesta è troppo grande (request_too_large).
request_too_large).
422
Validazione non riuscita o campo sconosciuto; details.fields elenca gli errori dei campi.
details.fields elenca gli errori dei campi.
429
Limite di frequenza superato; Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
503
Lo studio è temporaneamente non disponibile (manutenzione o configurazione in corso); Retry-After indica quando riprovare.
Retry-After indica quando riprovare.
default
Qualsiasi altro errore, nello stesso envelope.
Esempi di richiesta
curl -X POST 'https://www.flowyer.it/api/agent/portals/57/messages' \
-H 'Authorization: Bearer flw_...' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: 7f3a9c21-1b2c-4d5e-8f90-0a1b2c3d4e5f' \
-d '{
"body": "Tisztelt Ügyfelünk! A beadványt ma benyújtottuk."
}'
const response = await fetch("https://www.flowyer.it/api/agent/portals/57/messages", {
method: "POST",
headers: {
"Authorization": "Bearer flw_...",
"Content-Type": "application/json",
"Idempotency-Key": crypto.randomUUID(),
},
body: JSON.stringify({
"body": "Tisztelt Ügyfelünk! A beadványt ma benyújtottuk."
}),
});
const result = await response.json();
import uuid
import requests
response = requests.post(
"https://www.flowyer.it/api/agent/portals/57/messages",
headers={
"Authorization": "Bearer flw_...",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"body": "Tisztelt Ügyfelünk! A beadványt ma benyújtottuk.",
},
timeout=30,
)
print(response.status_code, response.json())
{
"body": "Tisztelt Ügyfelünk! A beadványt ma benyújtottuk."
}
Esempi di risposta
{
"data": {
"message": {
"id": 8012,
"author": {
"participant_id": 1234,
"name": "string",
"kind": "staff"
},
"direction": "from_firm",
"body": "string",
"created_at": "2026-10-30T09:15:00+01:00",
"portal": {
"id": 1234,
"matter": {
"id": 1234,
"case_number": "string"
}
},
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
}
}
},
"created": true
}
{
"data": {
"message": {
"id": 8012,
"author": {
"participant_id": 1234,
"name": "string",
"kind": "staff"
},
"direction": "from_firm",
"body": "string",
"created_at": "2026-10-30T09:15:00+01:00",
"portal": {
"id": 1234,
"matter": {
"id": 1234,
"case_number": "string"
}
},
"created_via_api": {
"kind": "key",
"key_id": 1234,
"key_name": "string",
"user_id": 1234,
"user": "string",
"at": "2026-10-30T09:15:00+01:00"
}
}
},
"created": false,
"idempotent_replay": true
}
{
"error": "validation_failed",
"message": "The request is invalid. See \"details.fields\" for the field-level errors.",
"message_localized": "La richiesta non è valida. Gli errori per campo sono in \"details.fields\".",
"locale": "it",
"details": {
"fields": {
"body": [
"Il campo body è obbligatorio."
]
}
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}