Referința API Flowyer
Versiunea API: 90bdda12e80e
Descrierea completă a REST API Flowyer pentru dezvoltatori: endpointuri, parametri, răspunsuri și exemple de cod.
Cu API-ul Flowyer, propriul dumneavoastră software sau un asistent IA poate citi, crea și modifica înregistrări (dosare, clienți, sarcini, ore de lucru, costuri și documente) în numele unui utilizator Flowyer. Fiecare cerere rulează exact cu permisiunile acelui utilizator, restrânse suplimentar de domeniile cheii sau ale autorizării. Prin API nu se poate șterge nimic.
Descrierile endpointurilor și ale câmpurilor sunt în engleză, deoarece asistenții IA citesc exact acest text.
URL de bază
Toate endpointurile se află la adresele de mai jos. Folosiți întotdeauna exact gazda https care începe cu www., deoarece o redirecționare ar elimina antetul Authorization.
URL de bază
https://www.flowyer.ro/api/agent
https://www.flowyer.hu/api/agent
https://www.flowyer.com/api/agent
https://www.flowyer.de/api/agent
https://www.flowyer.it/api/agent
Autentificare
Fiecare cerere necesită un token Bearer în antetul Authorization. Există două tipuri de token; endpointurile le tratează la fel.
Cheie API personală
Utilizatorul o creează în Flowyer la Setări > Chei API, după ce un administrator al biroului a activat API-ul. O cheie începe cu flw_, este afișată o singură dată și poate fi revocată oricând, cu efect imediat.
OAuth 2.1 pentru aplicațiile conectate
O integrare destinată altor utilizatori solicită acces prin fluxul OAuth 2.1 Authorization Code + PKCE (S256) în locul unei chei; clienții se pot înregistra dinamic. Un token de acces este valabil 60 minute, un token de reîmprospătare 60 zile, iar perechea este înlocuită la fiecare utilizare. Codul code_verifier PKCE are între 43 și 128 de caractere din A-Z, a-z, 0-9 și - . _ ~ (RFC 7636 4.1), adică base64url fără caractere de umplere: un "=" final este respins.
- Metadatele serverului
https://www.flowyer.com/.well-known/oauth-authorization-server- Autorizare
https://www.flowyer.com/authorize- Token
https://www.flowyer.com/api/agent/oauth/token- Înregistrarea clientului
https://www.flowyer.com/api/agent/oauth/register- Revocare
https://www.flowyer.com/api/agent/oauth/revoke
Exemple de cerere
curl 'https://www.flowyer.ro/api/agent/me' \
-H 'Authorization: Bearer flw_...'
Domenii
Fiecare endpoint, cu excepția GET /me, necesită un domeniu (scope). Dacă cheia sau autorizarea nu îl include, răspunsul este 403 scope_missing. GET /me nu necesită niciun domeniu: cu el vedeți ce poate face cheia sau autorizarea.
| Domeniu | Semnificație | Endpointuri |
|---|---|---|
matters:read |
Citire dosare | GETListați dosarele GETGăsiți un dosar după nume GETObțineți un dosar GETListare responsabili ai dosarului |
matters:create |
Creare dosare | POSTCreați un dosar |
matters:update |
Modificare dosare | PATCHActualizați un dosar POSTAdăugare responsabil de dosar |
clients:read |
Citire clienți | GETListare clienți GETRezolvare client după nume GETObținere client |
clients:create |
Creare clienți | POSTCreare client |
clients:update |
Modificare clienți | PATCHActualizare client |
tasks:read |
Citire sarcini | GETListare sarcini GETObținere sarcină |
tasks:create |
Creare sarcini | POSTCreare sarcină |
tasks:update |
Modificare sarcini | PATCHActualizare sarcină POSTÎnchidere sarcină |
workhours:read |
Citire ore | GETListare intrări de timp GETObținere intrare de timp |
workhours:create |
Înregistrare ore | POSTÎnregistrare intrare de timp |
workhours:update |
Modificare ore | PATCHActualizare intrare de timp |
costs:read |
Citire costuri | GETListare costuri GETObținere cost |
costs:create |
Înregistrare costuri | POSTÎnregistrare cost |
costs:update |
Modificare costuri | PATCHActualizare cost |
invoices:read |
Citire facturi | GETListare facturi GETObținere factură |
documents:read |
Listare documente (doar metadate, fără descărcare) | GETListați documentele unui dosar GETListați folderele unui dosar |
documents:download |
Descărcare documente (conținut complet) | GETDescărcare document |
documents:create |
Încărcare documente | POSTCreare folder de dosar POSTÎncepeți încărcarea unui document POSTFinalizați încărcarea unui document |
documents:update |
Redenumire documente | PATCHRedenumire document PATCHRedenumire folder de dosar |
colleagues:read |
Listarea colegilor (doar nume) | GETListare colegi |
knowledge:read |
Citirea bazei de cunoștințe | GETListare articole din baza de cunoștințe GETObținere articol din baza de cunoștințe GETListare categorii din baza de cunoștințe GETObținere categorie din baza de cunoștințe |
knowledge:create |
Crearea intrărilor în baza de cunoștințe | POSTCreare articol în baza de cunoștințe POSTCreare categorie în baza de cunoștințe |
knowledge:update |
Modificarea intrărilor în baza de cunoștințe | PATCHActualizare articol din baza de cunoștințe PATCHActualizare categorie din baza de cunoștințe |
emails:read |
Citire e-mailuri dosare | GETListare e-mailuri de dosar GETObținere e-mail |
litigation:read |
Listare istoric litigiu | GETListare istoric litigiu al dosarului |
litigation:create |
Creare înregistrare istoric litigiu | POSTCreare intrare în istoricul litigiului |
litigation:update |
Modificare înregistrare istoric litigiu | PATCHActualizare intrare din istoricul litigiului |
mail_register:read |
Citire corespondență | GETListare registru de corespondență GETObținere intrare din registrul de corespondență |
mail_register:create |
Creare înregistrări corespondență | POSTCreare intrare în registrul de corespondență |
mail_register:update |
Modificare înregistrări corespondență | PATCHActualizare intrare din registrul de corespondență |
comments:read |
Citirea comentariilor dosarului | GETListare comentarii de dosar |
comments:create |
Adăugarea de comentarii la dosar | POSTPostare comentariu de dosar |
comments:update |
Editarea propriilor comentarii | PATCHEditare comentariu propriu de dosar |
trials:read |
Citire termene de judecată | GETListare termene de judecată ale dosarului GETObținere termen de judecată |
trials:create |
Creare termene de judecată | POSTCreare termen de judecată |
trials:update |
Modificare termene de judecată | PATCHActualizare termen de judecată |
courts:read |
Listarea instanțelor | GETListare instanțe |
hr:read |
Citirea concediilor (doar date) | GETListare concedii ale personalului |
calendar:read |
Citirea evenimentelor din calendar | GETListare evenimente de calendar GETObținere eveniment de calendar |
calendar:create |
Crearea evenimentelor în calendar | POSTCreare eveniment de calendar |
calendar:update |
Modificarea evenimentelor din calendar | PATCHActualizare eveniment de calendar |
bookings:read |
Vizualizarea programărilor | GETListare programări GETObținere programare |
bookings:create |
Crearea de programări (trimite un e-mail clientului) | POSTCreare programare |
bookings:update |
Reprogramarea și editarea programărilor | PATCHActualizare programare |
bookings:send |
Confirmarea sau anularea programărilor (trimite un e-mail clientului) | POSTConfirmare programare POSTAnulare programare |
tickets:read |
Citirea tichetelor de asistență | GETListare tichete de asistență GETObținere tichet de asistență |
tickets:reply |
Răspuns la tichete (trimite un e-mail clientului) | POSTRăspuns la tichet |
tickets:update |
Modificarea stării tichetului | PATCHSchimbare status tichet |
portal:read |
Portal client: citirea conversațiilor și a mesajelor | GETListare portaluri client GETListare mesaje de portal |
portal:reply |
Portal client: răspuns către client (trimite un mesaj și un e-mail de notificare) | POSTRăspuns în portalul client |
Erori
Fiecare eroare are aceeași formă: un cod (error), un mesaj în engleză (message), mesajul în limba biroului (message_localized) și detalii opționale (details). La 401, 403, 404 și 422 nu are sens să repetați cererea neschimbată, cu două excepții: la 404 upload_not_finished finalizați mai întâi încărcarea la upload_url, apoi apelați din nou complete; la un token de acces OAuth expirat (401 expired_key) reînnoiți mai întâi tokenul.
| HTTP | error | Semnificație |
|---|---|---|
| 400 | invalid_json use_www_host bad_request |
Cerere invalidă: corp JSON invalid, gazdă greșită (folosiți gazda www.) sau o cerere ilizibilă. |
| 401 | missing_key invalid_key revoked_key expired_key user_inactive office_not_found |
Cheia lipsește, este invalidă, revocată sau expirată, titularul ei nu mai este activ, ori biroul cheii nu a fost găsit. |
| 403 | scope_missing module_forbidden forbidden office_api_disabled licence_expired office_archived |
Lipsește o permisiune pe cheie sau pe utilizator, ori biroul nu a activat API-ul. |
| 404 | not_found matter_not_visible unknown_endpoint upload_not_finished replay_not_visible |
Înregistrarea nu există sau utilizatorul nu o poate vedea; endpoint necunoscut; fișierul încărcat nu a ajuns încă în stocare (upload_not_finished: încărcați-l la upload_url, apoi apelați din nou complete); ori o creare repetată a cărei înregistrare a fost creată anterior, dar între timp a fost ștearsă sau ascunsă (replay_not_visible: nu s-a creat nimic nou, nu o creați din nou). |
| 405 | delete_not_allowed update_not_allowed method_not_allowed |
Ștergerea nu este posibilă prin API; modificarea doar acolo unde descrierea oferă o operație PATCH. |
| 409 | client_exists client_exists_generic idempotency_key_reused duplicate_in_progress record_conflict record_locked duplicate_name |
Există deja un client cu acel nume; în folder există deja un document cu acel nume (duplicate_name); înregistrarea s-a modificat de când ați citit-o (record_conflict: citiți-o din nou și retrimiteți modificarea cu noul updated_at); înregistrarea a fost facturată sau blocată (record_locked: faceți modificarea în Flowyer); Idempotency-Key a fost folosit pe altă resursă; ori o cerere identică este în curs de procesare. |
| 413 | request_too_large file_too_large |
Corpul cererii este prea mare (request_too_large) sau fișierul de încărcat depășește limita (file_too_large; details.max indică limita în octeți). |
| 422 | validation_failed unknown_client unknown_colleague blocked_file_type upload_token_invalid folder_not_in_matter document_name_too_long |
Un câmp invalid sau lipsă (details.fields arată care); un token de încărcare invalid, deja folosit sau expirat (upload_token_invalid: reluați încărcarea); ori un folder care nu aparține dosarului (folder_not_in_matter). |
| 429 | rate_limited auth_rate_limited |
Prea multe cereri (300 pe minut per cheie); antetul Retry-After spune când să reîncercați. |
| 500 | server_error |
Eroare neașteptată. Cererea a fost înregistrată sub request_id; reîncercați mai târziu și, dacă se repetă, comunicați acest ID asistenței Flowyer. |
| 503 | office_maintenance office_setup_incomplete temporarily_unavailable |
Biroul este temporar indisponibil (întreținere sau configurare în curs); antetul Retry-After spune când să reîncercați. |
Exemple de răspuns · 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": "Această cheie API nu are permisiunea \"clients:create\". Permisiunile unei chei existente nu pot fi modificate, așa că titularul cheii trebuie să creeze în Flowyer, la Setări > Chei API, o cheie nouă cu această permisiune și să o folosească în locul celei vechi.",
"locale": "ro",
"details": {
"required_scope": "clients:create"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Paginare
Listele de înregistrări se paginează cu parametrii limit și offset (implicit 25, cel mult 100 elemente pe pagină). pagination.total este numărul total de rezultate; offset-ul paginii următoare este offset-ul anterior plus limit. GET /colleagues, GET /clients/resolve și GET /matters/resolve nu se paginează: acceptă doar limit (cu valoare implicită și maximă proprii, vedeți endpointul respectiv) și returnează total și truncated în data, în loc de un obiect pagination, așadar nu le trimiteți offset.
Exemple de răspuns · 200
{
"data": [
{
"id": 1234,
"...": "..."
}
],
"pagination": {
"limit": 25,
"offset": 0,
"total": 134
}
}
Reîncercări sigure
Fiecare creare acceptă un antet Idempotency-Key (sau un câmp idempotency_key). O cerere repetată cu aceeași valoare returnează înregistrarea creată prima dată (200, idempotent_replay), în loc să creeze alta. Chei diferite creează întotdeauna înregistrări separate. Fără cheie, o creare identică în decurs de 120 secunde returnează prima înregistrare.
Exemple de cerere
curl -X POST 'https://www.flowyer.ro/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."}'
Modificări și conflicte
O modificare este o cerere PATCH pe calea proprie a înregistrării: se schimbă doar câmpurile trimise, iar un null explicit golește un câmp numai dacă descrierea câmpului permite acest lucru; la unele câmpuri, null păstrează valoarea memorată, așadar citiți descrierea câmpului. Trimiteți în expected_updated_at valoarea updated_at de la ultima citire. Dacă între timp altcineva a modificat înregistrarea, răspunsul este 409 record_conflict; în acest caz citiți din nou înregistrarea.
Exemple de cerere
curl -X PATCH 'https://www.flowyer.ro/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 și fus orar
Datele au formatul AAAA-LL-ZZ, momentele urmează ISO 8601 cu decalajul fusului orar al biroului. Fusul orar al biroului se află în câmpul office.timezone al răspunsului GET /me.
Limite
Cel mult 300 cereri pe minut per cheie sau token; peste această limită răspunsul este 429, iar antetul Retry-After spune când să reîncercați. Corpul unei cereri JSON poate avea cel mult 64 KB, un document încărcat cel mult 100 MB.
Versiuni
Versiunea descrierii OpenAPI se schimbă la fiecare modificare și este trimisă și ca antet ETag, astfel încât clienții pot verifica cu If-None-Match dacă s-a schimbat.
Identitate
Cine sunt
/api/agent/me
Returnează utilizatorul și biroul pentru care acționează această cheie API, scope-urile cheii (ce poate face) și limitele de rată. Apelați-o prima dată pentru a afla ce operații sunt disponibile; nu necesită niciun scope.
Acest endpoint nu are date de intrare.
Răspunsuri
200
OK.
dataobligatoriuCâmpurile data
userCâmpurile user
idnamelanguageofficeCâmpurile office
idnametimezoneZona IANA în care API-ul citește și scrie marcajele temporale, de exemplu Europe/Budapest.
currency_idMoneda biroului (id-ul de monedă Flowyer): costs.create înregistrează în ea atunci când currency_id este omis.
currencyCodul ISO al monedei biroului, de exemplu HUF, EUR, RON.
keyCâmpurile key
idnameNumele pe care utilizatorul l-a dat acestei chei sau aplicația conectată pentru un token OAuth.
kind"key" = o cheie API statică, "oauth" = un token de acces OAuth 2.1.
"key" "oauth" prefixPrimele caractere ale unei chei statice, doar pentru identificare; null pentru OAuth.
expires_atlast_used_atscopesScope-urile acestei credențiale, de exemplu "matters:read". O operație al cărei scope lipsește răspunde cu 403.
available_scopesToate scope-urile pe care proprietarul cheii le-ar putea activa în Flowyer.
limitsCâmpurile limits
requests_per_minutelist_max_limitchannelCum a ajuns cererea la Flowyer.
"rest" "mcp"
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
API dezactivat pentru birou, licență expirată sau birou arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
422
Parametru de interogare necunoscut (această operație nu acceptă niciunul); details.fields îl numește.
details.fields îl numește.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl 'https://www.flowyer.ro/api/agent/me' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.ro/api/agent/me", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.ro/api/agent/me",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Exemple de răspuns
{
"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": "Cheia API nu este validă.",
"locale": "ro",
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Colegi
Listare colegi
/api/agent/colleagues
Listează colegii activi ai biroului (id, nume) pentru assigned_to_user_id / responsible_user_id. Cu q (un nume așa cum a fost auzit; diacriticele, majusculele/minusculele și micile greșeli de tastare sunt tolerate) răspunde cu statusul exact/similar/none ca instrumentele de rezolvare: doar "exact" este sigur de folosit direct.
Parametri de interogare
qNumele unui coleg de căutat, așa cum a fost auzit sau dictat, în orice ordine a cuvintelor. Omiteți-l pentru a lista fiecare coleg activ.
"Nagy Péter"limitNumărul maxim de colegi de returnat (implicit 200).
200Răspunsuri
200
OK.
dataobligatoriuCâmpurile data
statusDoar cu q: exact = o singură potrivire sigură (id-ul ei se poate folosi în siguranță), similar = potrivire aproximativă sau mai multe potriviri (confirmați mai întâi cu utilizatorul), none = nicio potrivire (întrebați utilizatorul). Null fără q.
"exact" "similar" "none" colleaguesColegi activi, cea mai bună potrivire prima cu q, altfel după nume.
Câmpurile colleagues
idId-ul utilizatorului: transmiteți-l ca assigned_to_user_id / responsible_user_id.
nameNumele afișat așa cum îl arată Flowyer (cu titlul, dacă există).
titlePrefixul numelui, precum "Dr.", sau null.
totalCâți colegi au corespuns (toți colegii activi fără q) înainte ca lista să fie redusă la limit.
truncatedTrue când au corespuns mai mulți colegi decât au fost returnați: restrângeți q sau măriți limit.
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Scope lipsă (scope_missing), API dezactivat pentru birou, licență expirată sau birou arhivat.
scope_missing), API dezactivat pentru birou, licență expirată sau birou arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl 'https://www.flowyer.ro/api/agent/colleagues?q=Nagy%20P%C3%A9ter' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.ro/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.ro/api/agent/colleagues?q=Nagy%20P%C3%A9ter",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Exemple de răspuns
{
"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": "Această cheie API nu are permisiunea \"colleagues:read\". Permisiunile unei chei existente nu pot fi modificate, așa că titularul cheii trebuie să creeze în Flowyer, la Setări > Chei API, o cheie nouă cu această permisiune și să o folosească în locul celei vechi.",
"locale": "ro",
"details": {
"required_scope": "colleagues:read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Dosare
Listați dosarele
/api/agent/matters
Listează dosarele (cazurile) pe care utilizatorul le poate vedea, cele mai noi primele. Folosiți această operație pentru a găsi un dosar după numărul de caz, obiect sau client înainte de a-l referi în altă parte. Dosarele arhivate sunt ascunse, cu excepția cazului în care include_archived este true.
Parametri de interogare
qCăutare text liber în obiect și în numele clienților (ignorând diacriticele și majusculele) și în celelalte numere de caz ale biroului; sau un număr de caz, fie exact așa cum este returnat în case_number (schema de numerotare a biroului), fie sub forma an/secvență, precum "2026/0025".
"2026/0025"client_idDoar dosarele acestui client.
512responsible_user_idDoar dosarele de care răspunde acest utilizator (id-urile din colleagues.list): ca responsabil principal, ca responsabil suplimentar sau ca membru al unui grup de lucru responsabil (la fel ca filtrul de colegi din interfața web).
updated_sinceDoar dosarele modificate la acest moment sau după el (ISO 8601).
"2026-10-01T00:00:00+02:00"include_archivedInclude dosarele arhivate.
falselimitDimensiunea paginii, 1-100. Valoarea implicită este 25.
2525offsetNumărul de înregistrări de omis. Folosiți offset + limit ale paginii anterioare pentru a o obține pe următoarea; pagination.total este numărul total.
00Răspunsuri
200
OK.
dataobligatoriuCâmpurile data
idId-ul dosarului. Folosiți-l ca matter_id în altă parte.
1234case_numberNumărul de caz așa cum este afișat în Flowyer, în schema de numerotare a biroului.
"2026/0025"subject"Kovács Kft. v. Nagy Bt. - contract dispute"status"active" "archived" case_type_idcase_typeDenumirea localizată a tipului de caz.
responsible_user_idresponsibleNumele afișat al avocatului responsabil.
clientsClienții (mandanții) dosarului.
Câmpurile clients
idnamestarted_onrestrictedTrue atunci când doar avocații responsabili pot vedea dosarul (zid chinezesc).
created_atupdated_atcreated_via_apiPrezent atunci când un agent extern a creat înregistrarea prin acest API.
Câmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduseratpaginationobligatoriuCâmpurile pagination
limitobligatoriuoffsetobligatoriutotalobligatoriuNumărul total de înregistrări care se potrivesc.
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl 'https://www.flowyer.ro/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.ro/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.ro/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())
Exemple de răspuns
{
"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": "Această cheie API nu are permisiunea \"matters:read\". Permisiunile unei chei existente nu pot fi modificate, așa că titularul cheii trebuie să creeze în Flowyer, la Setări > Chei API, o cheie nouă cu această permisiune și să o folosească în locul celei vechi.",
"locale": "ro",
"details": {
"required_scope": "matters:read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Găsiți un dosar după nume
/api/agent/matters/resolve
Găsește un dosar după un obiect sau un nume de client rostit sau scris greșit (tolerând diacriticele, majusculele și micile greșeli de scriere). Returnează status-ul exact/similar/none și candidații. Doar "exact" este sigur de folosit direct; altfel confirmați cu utilizatorul. Multe potriviri aparente nu sunt niciodată "exact": restrângeți cu client_id sau cu un nume mai complet.
Parametri de interogare
nameobligatoriuObiectul dosarului sau numele clientului de căutat, așa cum a fost auzit sau dictat.
"ingatlan adásvétel"client_idDoar dosarele acestui client (folosiți după ce clients.resolve a returnat un client exact).
limitNumărul maxim de candidați de returnat (implicit 5).
5Răspunsuri
200
OK.
dataobligatoriuCâmpurile data
statusexact = o singură potrivire sigură (id-ul ei poate fi folosit în siguranță). similar = una sau mai multe potriviri aproximative, confirmați mai întâi cu utilizatorul. none = nicio potrivire, întrebați utilizatorul.
"exact" "similar" "none" mattersDosarele candidate, cea mai bună potrivire prima.
Câmpurile matters
idId-ul dosarului. Folosiți-l ca matter_id în altă parte.
1234case_numberNumărul de caz așa cum este afișat în Flowyer, în schema de numerotare a biroului.
"2026/0025"subject"Kovács Kft. v. Nagy Bt. - contract dispute"status"active" "archived" case_type_idcase_typeDenumirea localizată a tipului de caz.
responsible_user_idresponsibleNumele afișat al avocatului responsabil.
clientsClienții (mandanții) dosarului.
Câmpurile clients
idnamestarted_onrestrictedTrue atunci când doar avocații responsabili pot vedea dosarul (zid chinezesc).
created_atupdated_atcreated_via_apiPrezent atunci când un agent extern a creat înregistrarea prin acest API.
Câmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduserattotalCâte dosare s-au potrivit înainte ca lista să fie restrânsă la limit.
truncatedTrue atunci când s-au potrivit mai multe dosare decât au fost returnate sau au existat prea multe potriviri aparente pentru a le verifica pe toate; restrângeți cu client_id sau cu un nume mai complet, ori măriți limit, în loc să alegeți dintr-o listă incompletă.
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl 'https://www.flowyer.ro/api/agent/matters/resolve?name=ingatlan%20ad%C3%A1sv%C3%A9tel' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.ro/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.ro/api/agent/matters/resolve?name=ingatlan%20ad%C3%A1sv%C3%A9tel",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Exemple de răspuns
{
"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": "Această cheie API nu are permisiunea \"matters:read\". Permisiunile unei chei existente nu pot fi modificate, așa că titularul cheii trebuie să creeze în Flowyer, la Setări > Chei API, o cheie nouă cu această permisiune și să o folosească în locul celei vechi.",
"locale": "ro",
"details": {
"required_scope": "matters:read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Obțineți un dosar
/api/agent/matters/{id}
Returnează un dosar (caz) împreună cu clienții și detaliile lui. Răspunde cu 404 atunci când dosarul nu există sau utilizatorul nu îl poate vedea.
Parametri de cale
idobligatoriuId-ul dosarului.
1234Răspunsuri
200
OK.
dataobligatoriuCâmpurile data
idId-ul dosarului. Folosiți-l ca matter_id în altă parte.
1234case_numberNumărul de caz așa cum este afișat în Flowyer, în schema de numerotare a biroului.
"2026/0025"subject"Kovács Kft. v. Nagy Bt. - contract dispute"status"active" "archived" case_type_idcase_typeDenumirea localizată a tipului de caz.
responsible_user_idresponsibleNumele afișat al avocatului responsabil.
clientsClienții (mandanții) dosarului.
Câmpurile clients
idnamestarted_onrestrictedTrue atunci când doar avocații responsabili pot vedea dosarul (zid chinezesc).
created_atupdated_atcreated_via_apiPrezent atunci când un agent extern a creat înregistrarea prin acest API.
Câmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduseratdescriptionlitigiousarchived_atZiua în care dosarul a fost arhivat, YYYY-MM-DD. Flowyer înregistrează doar data, fără ora din zi.
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl 'https://www.flowyer.ro/api/agent/matters/1234' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.ro/api/agent/matters/1234", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.ro/api/agent/matters/1234",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Exemple de răspuns
{
"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": "Dosarul 1234 nu există, este arhivat sau nu este vizibil pentru titularul acestei chei API.",
"locale": "ro",
"details": {
"matter_id": 1234
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Creați un dosar
/api/agent/matters
Deschide un dosar (caz) cu următorul număr de caz al anului. Necesită cel puțin un client existent (găsiți-l sau creați-l mai întâi). Avocatul responsabil este implicit utilizatorul cheii și este notificat în caz contrar. Părțile, persoanele de contact și onorariile se stabilesc în Flowyer.
Parametri de antet
Idempotency-KeyRecomandat la fiecare creare. O valoare unică per operație logică (de exemplu un UUID). Aceeași valoare returnează aceeași înregistrare: reîncercarea cu ea returnează înregistrarea creată prima dată, în loc să creeze o a doua. Valori diferite creează întotdeauna înregistrări diferite. Clienții care nu pot trimite anteturi pot transmite aceeași valoare în câmpul de corp idempotency_key. Litere, cifre, _, -, : sau ., cel mult 128 de caractere.
^[A-Za-z0-9_\-:.]{1,128}$Corpul cererii application/json
subjectobligatoriuTitlu scurt al dosarului, așa cum apare în liste. Text simplu; "<" și ">" nu sunt permise.
^[^<>]*$"Kovács Kft. v. Nagy Bt. - contract dispute"case_type_idobligatoriuId-ul tipului de caz (domeniu de drept) din lista globală de tipuri de caz Flowyer: alegeți-l pe cel al cărui nume corespunde cuvintelor utilizatorului sau cereți utilizatorului să aleagă după nume. Un id necunoscut răspunde cu 422 și details.known_case_types (id + denumire localizată); un dosar existent își arată tipul în matters.get, în case_type_id / case_type.
client_idsobligatoriuId-urile clienților (mandanților). Cel puțin unul, cel mult 20.
[
512
]responsible_user_idAvocat responsabil: un id de utilizator din colleagues.list (căutați acolo un nume dictat). Implicit: utilizatorul din spatele cheii.
started_onData de început, YYYY-MM-DD. Implicit: astăzi.
"2026-10-29"descriptionDescriere mai amplă, text simplu.
main_case_numberNumărul de referință principal propriu al biroului pentru dosar. Obligatoriu atunci când schema de numerotare a biroului îl folosește (altfel API-ul răspunde cu 422).
restrictedtrue = doar avocații responsabili pot vedea dosarul (zid chinezesc).
falseidempotency_keyAcelași rol ca antetul Idempotency-Key, pentru clienții care nu pot trimite anteturi personalizate. Litere, cifre, _, -, : sau ., cel mult 128 de caractere.
^[A-Za-z0-9_\-:.]{1,128}$"b8f1c2e0-6f7a-4d2e-9c1b-2a3d4e5f6a7b"Răspunsuri
201
Creat.
dataobligatoriuCâmpurile data
idId-ul dosarului. Folosiți-l ca matter_id în altă parte.
1234case_numberNumărul de caz așa cum este afișat în Flowyer, în schema de numerotare a biroului.
"2026/0025"subject"Kovács Kft. v. Nagy Bt. - contract dispute"status"active" "archived" case_type_idcase_typeDenumirea localizată a tipului de caz.
responsible_user_idresponsibleNumele afișat al avocatului responsabil.
clientsClienții (mandanții) dosarului.
Câmpurile clients
idnamestarted_onrestrictedTrue atunci când doar avocații responsabili pot vedea dosarul (zid chinezesc).
created_atupdated_atcreated_via_apiPrezent atunci când un agent extern a creat înregistrarea prin acest API.
Câmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduseratdescriptionlitigiousarchived_atZiua în care dosarul a fost arhivat, YYYY-MM-DD. Flowyer înregistrează doar data, fără ora din zi.
createdtrue
200
Reluare idempotentă: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică în interval de 120 de secunde) a creat deja înregistrarea; aceasta este returnată din nou, nu s-a creat nimic nou.
dataobligatoriuCâmpurile data
idId-ul dosarului. Folosiți-l ca matter_id în altă parte.
1234case_numberNumărul de caz așa cum este afișat în Flowyer, în schema de numerotare a biroului.
"2026/0025"subject"Kovács Kft. v. Nagy Bt. - contract dispute"status"active" "archived" case_type_idcase_typeDenumirea localizată a tipului de caz.
responsible_user_idresponsibleNumele afișat al avocatului responsabil.
clientsClienții (mandanții) dosarului.
Câmpurile clients
idnamestarted_onrestrictedTrue atunci când doar avocații responsabili pot vedea dosarul (zid chinezesc).
created_atupdated_atcreated_via_apiPrezent atunci când un agent extern a creat înregistrarea prin acest API.
Câmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduseratdescriptionlitigiousarchived_atZiua în care dosarul a fost arhivat, YYYY-MM-DD. Flowyer înregistrează doar data, fără ora din zi.
createdfalseidempotent_replaytrue
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator. replay_not_visible: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică) a creat deja înregistrarea (details.record_id), dar aceasta a fost între timp ștearsă sau nu este vizibilă pentru utilizator; nu s-a creat nimic nou, nu o creați din nou.
replay_not_visible: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică) a creat deja înregistrarea (details.record_id), dar aceasta a fost între timp ștearsă sau nu este vizibilă pentru utilizator; nu s-a creat nimic nou, nu o creați din nou.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
409
Idempotency-Key a fost folosit pentru alt tip de resursă (idempotency_key_reused) sau, în lipsa unei chei, o cerere identică este procesată chiar acum (duplicate_in_progress; reîncercați în scurt timp).
idempotency_key_reused) sau, în lipsa unei chei, o cerere identică este procesată chiar acum (duplicate_in_progress; reîncercați în scurt timp).
413
Corpul cererii este prea mare (request_too_large).
request_too_large).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl -X POST 'https://www.flowyer.ro/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.ro/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.ro/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"
}
Exemple de răspuns
{
"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": "Cererea nu este validă. Erorile pe câmpuri se găsesc în \"details.fields\".",
"locale": "ro",
"details": {
"fields": {
"subject": [
"Câmpul subject este obligatoriu."
]
}
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Actualizați un dosar
/api/agent/matters/{id}
Modifică obiectul, descrierea, data de început, indicatorul de litigiu sau avocatul responsabil al unui dosar. Numărul de caz, zidul chinezesc, starea de arhivare, onorariile și legăturile cu clienții nu pot fi editate aici. Transmiteți expected_updated_at din ultima citire; o modificare conflictuală răspunde cu 409.
Parametri de cale
idobligatoriuId-ul înregistrării de modificat.
Corpul cererii application/json
expected_updated_atValoarea updated_at din cea mai recentă citire a acestei înregistrări (obligatorie ori de câte ori înregistrarea are una). Dacă înregistrarea s-a schimbat între timp (un coleg a editat-o), API-ul răspunde cu 409 și trebuie să o recitiți înainte de a reîncerca. O înregistrare veche al cărei updated_at este null acceptă null.
subjectTitlu scurt al dosarului. Text simplu, cel mult 255 de caractere ca valoare NOUĂ; nici "<" și ">" nu pot fi introduse, însă un obiect stocat care este mai lung sau le conține poate fi returnat neschimbat. null păstrează obiectul curent.
descriptionDescriere mai amplă, text simplu, cel mult 10000 de caractere ca valoare NOUĂ; o descriere stocată mai lungă poate fi returnată neschimbată.
started_onData de început, YYYY-MM-DD. null păstrează valoarea curentă (o dată de început nu poate fi eliminată).
litigiousDacă dosarul este litigios sau nu.
responsible_user_idNou avocat responsabil: id-ul de utilizator al unui coleg activ din colleagues.list. Acesta este notificat atunci când nu sunteți dumneavoastră. Trimiterea celui curent - sau null / 0, valoare sub care este citit un dosar fără responsabil - nu schimbă nimic.
Răspunsuri
200
Actualizat.
dataobligatoriuCâmpurile data
idId-ul dosarului. Folosiți-l ca matter_id în altă parte.
1234case_numberNumărul de caz așa cum este afișat în Flowyer, în schema de numerotare a biroului.
"2026/0025"subject"Kovács Kft. v. Nagy Bt. - contract dispute"status"active" "archived" case_type_idcase_typeDenumirea localizată a tipului de caz.
responsible_user_idresponsibleNumele afișat al avocatului responsabil.
clientsClienții (mandanții) dosarului.
Câmpurile clients
idnamestarted_onrestrictedTrue atunci când doar avocații responsabili pot vedea dosarul (zid chinezesc).
created_atupdated_atcreated_via_apiPrezent atunci când un agent extern a creat înregistrarea prin acest API.
Câmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduseratdescriptionlitigiousarchived_atZiua în care dosarul a fost arhivat, YYYY-MM-DD. Flowyer înregistrează doar data, fără ora din zi.
updatedtrue
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
409
Înregistrarea s-a schimbat de când ați citit-o (record_conflict: expected_updated_at nu mai corespunde; citiți-o din nou și reîncercați cu noul updated_at).
record_conflict: expected_updated_at nu mai corespunde; citiți-o din nou și reîncercați cu noul updated_at).
413
Corpul cererii este prea mare (request_too_large).
request_too_large).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl -X PATCH 'https://www.flowyer.ro/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.ro/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.ro/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"
}
Exemple de răspuns
{
"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": "Înregistrarea s-a modificat de când ați citit-o (cineva a editat-o). Citiți-o din nou și reîncercați cu noua valoare updated_at.",
"locale": "ro",
"details": {
"current_updated_at": "2026-10-30T10:42:05+01:00",
"reason": "modified_since_read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Listare responsabili ai dosarului
/api/agent/matters/{id}/responsibles
Listează responsabilii SUPLIMENTARI ai unui dosar (responsabilul principal se află în matters.get): fiecare este un coleg (type "user", user_id setat) sau un grup de lucru (type "workgroup", workgroup_id setat), toți putând vedea dosarul. Răspunde cu 404 când dosarul nu este vizibil.
Parametri de cale
idobligatoriuId-ul dosarului.
1234Parametri de interogare
limitDimensiunea paginii, 1-100. Valoarea implicită este 25.
2525offsetNumărul de înregistrări de omis. Folosiți offset + limit ale paginii anterioare pentru a o obține pe următoarea; pagination.total este numărul total.
00Răspunsuri
200
OK.
dataobligatoriuCâmpurile data
type"user" = un singur coleg; "workgroup" = fiecare membru al unui grup de lucru.
"user" "workgroup" user_idId-ul de utilizator al colegului pentru o intrare "user" (transmiteți-l ca user_id către matters.responsibles.add); null pentru un grup de lucru.
workgroup_idId-ul grupului de lucru pentru o intrare "workgroup"; null pentru un singur coleg. Responsabilii de tip grup de lucru sunt gestionați în Flowyer.
nameNumele afișat al colegului sau al grupului de lucru.
paginationobligatoriuCâmpurile pagination
limitobligatoriuoffsetobligatoriutotalobligatoriuNumărul total de înregistrări care se potrivesc.
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl 'https://www.flowyer.ro/api/agent/matters/1234/responsibles?limit=25' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.ro/api/agent/matters/1234/responsibles?limit=25", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.ro/api/agent/matters/1234/responsibles?limit=25",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Exemple de răspuns
{
"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": "Dosarul 1234 nu există, este arhivat sau nu este vizibil pentru titularul acestei chei API.",
"locale": "ro",
"details": {
"matter_id": 1234
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Adăugare responsabil de dosar
/api/agent/matters/{id}/responsibles
Adaugă un coleg (user_id din colleagues.list) ca responsabil suplimentar al unui dosar. Acest lucru ÎI ACORDĂ acelui coleg acces la dosar, așa că adăugați doar pe cineva care ar trebui să îl vadă; acesta este notificat. Idempotent: readăugarea unui responsabil existent nu face nicio modificare.
Parametri de cale
idobligatoriuDosarul de care colegul devine responsabil (trebuie să fie vizibil).
1234Corpul cererii application/json
user_idobligatoriuColegul de adăugat: un id de utilizator din colleagues.list. Adăugarea lui îi acordă acces la dosar.
42Răspunsuri
200
OK.
dataobligatoriuCâmpurile data
user_idColegul acum responsabil de dosar.
nameNumele afișat al colegului.
already_responsibleTrue când colegul era deja responsabil al dosarului (nimic nu s-a schimbat).
notifiedTrue când colegul a fost notificat că a fost adăugat. Niciodată true când colegul sunteți dumneavoastră sau când era deja responsabil.
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
413
Corpul cererii este prea mare (request_too_large).
request_too_large).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl -X POST 'https://www.flowyer.ro/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.ro/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.ro/api/agent/matters/1234/responsibles",
headers={
"Authorization": "Bearer flw_...",
},
json={
"user_id": 42,
},
timeout=30,
)
print(response.status_code, response.json())
{
"user_id": 42
}
Exemple de răspuns
{
"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": "Cererea nu este validă. Erorile pe câmpuri se găsesc în \"details.fields\".",
"locale": "ro",
"details": {
"fields": {
"user_id": [
"Câmpul user id este obligatoriu."
]
}
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Clienți
Listare clienți
/api/agent/clients
Listează clienții biroului (persoane și companii), în ordine alfabetică; q caută în nume (ignorând diacriticele și majusculele/minusculele), e-mail și codul fiscal. Înainte de a crea un client, verificați numele cu clients.resolve (tolerează și greșelile de tastare). Clienții arhivați sunt ascunși, cu excepția cazului în care include_archived este true.
Parametri de interogare
qCaută în nume (ignorând diacriticele și majusculele/minusculele), e-mail și codul fiscal.
"Kovács"is_persontrue = doar persoane fizice, false = doar companii.
include_archivedfalselimitDimensiunea paginii, 1-100. Valoarea implicită este 25.
2525offsetNumărul de înregistrări de omis. Folosiți offset + limit ale paginii anterioare pentru a o obține pe următoarea; pagination.total este numărul total.
00Răspunsuri
200
OK.
dataobligatoriuCâmpurile data
idId-ul clientului. Folosiți-l ca client_id în altă parte.
512name"Kovács Kft."is_personTrue pentru o persoană fizică, false pentru o companie.
emailphonearchivedrecorded_by_user_idrecorded_bycreated_atupdated_atcreated_via_apiCâmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduseratpaginationobligatoriuCâmpurile pagination
limitobligatoriuoffsetobligatoriutotalobligatoriuNumărul total de înregistrări care se potrivesc.
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl 'https://www.flowyer.ro/api/agent/clients?q=Kov%C3%A1cs&limit=25' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.ro/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.ro/api/agent/clients?q=Kov%C3%A1cs&limit=25",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Exemple de răspuns
{
"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": "Această cheie API nu are permisiunea \"clients:read\". Permisiunile unei chei existente nu pot fi modificate, așa că titularul cheii trebuie să creeze în Flowyer, la Setări > Chei API, o cheie nouă cu această permisiune și să o folosească în locul celei vechi.",
"locale": "ro",
"details": {
"required_scope": "clients:read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Rezolvare client după nume
/api/agent/clients/resolve
Găsește un client după un nume rostit sau scris greșit (diacriticele, majusculele/minusculele și micile greșeli de tastare sunt tolerate). Returnează statusul exact/similar/none și clienții candidați. Doar "exact" este sigur de folosit direct; la "similar" sau "none" întrebați utilizatorul. Un nume cu multe asemănări nu este niciodată "exact": cereți un nume mai complet.
Parametri de interogare
nameobligatoriuNumele clientului de căutat, așa cum a fost auzit sau dictat.
"Józsi ingatlan"limitNumărul maxim de candidați de returnat (implicit 5).
5Răspunsuri
200
OK.
dataobligatoriuCâmpurile data
statusexact = o singură potrivire sigură (id-ul ei poate fi folosit în siguranță). similar = una sau mai multe potriviri aproximative, confirmați mai întâi cu utilizatorul. none = nicio potrivire, întrebați utilizatorul.
"exact" "similar" "none" matchesClienți candidați, cea mai bună potrivire prima.
Câmpurile matches
idId-ul clientului. Folosiți-l ca client_id în altă parte.
512name"Kovács Kft."is_personTrue pentru o persoană fizică, false pentru o companie.
emailphonearchivedrecorded_by_user_idrecorded_bycreated_atupdated_atcreated_via_apiCâmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduserattotalCâți clienți au corespuns înainte ca lista să fie redusă la limit.
truncatedTrue când au corespuns mai mulți clienți decât au fost returnați, sau au existat prea multe asemănări pentru a le verifica pe toate; cereți utilizatorului un nume mai complet sau măriți limit în loc să alegeți dintr-o listă incompletă.
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl 'https://www.flowyer.ro/api/agent/clients/resolve?name=J%C3%B3zsi%20ingatlan' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.ro/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.ro/api/agent/clients/resolve?name=J%C3%B3zsi%20ingatlan",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Exemple de răspuns
{
"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": "Această cheie API nu are permisiunea \"clients:read\". Permisiunile unei chei existente nu pot fi modificate, așa că titularul cheii trebuie să creeze în Flowyer, la Setări > Chei API, o cheie nouă cu această permisiune și să o folosească în locul celei vechi.",
"locale": "ro",
"details": {
"required_scope": "clients:read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Obținere client
/api/agent/clients/{id}
Returnează un client cu detaliile de adresă și de înregistrare. Numerele actelor de identitate și setările de onorariu nu sunt returnate niciodată.
Parametri de cale
idobligatoriuId-ul clientului.
512Răspunsuri
200
OK.
dataobligatoriuCâmpurile data
idId-ul clientului. Folosiți-l ca client_id în altă parte.
512name"Kovács Kft."is_personTrue pentru o persoană fizică, false pentru o companie.
emailphonearchivedrecorded_by_user_idrecorded_bycreated_atupdated_atcreated_via_apiCâmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduserataddressCâmpurile address
zipcitystreetmailing_addressCâmpurile mailing_address
zipcitystreettax_numberDoar pentru companii; null pentru o persoană fizică.
company_registration_numberDoar pentru companii; null pentru o persoană fizică.
representative_nameDoar pentru companii; null pentru o persoană fizică.
representative_positionDoar pentru companii; null pentru o persoană fizică.
main_activityObiectul principal de activitate. Doar pentru companii; null pentru o persoană fizică.
nationality_countrynote
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl 'https://www.flowyer.ro/api/agent/clients/512' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.ro/api/agent/clients/512", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.ro/api/agent/clients/512",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Exemple de răspuns
{
"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": "Înregistrarea nu a fost găsită sau nu este vizibilă pentru titularul acestei chei API.",
"locale": "ro",
"details": {
"client_id": 512
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Creare client
/api/agent/clients
Creează un client (persoană sau companie), înregistrat ca fiind creat de utilizatorul cheii. Verificați mai întâi numele cu clients.resolve (tolerează lipsa diacriticelor și greșelile de tastare): un 409 surprinde doar un client activ cu exact același nume, cu excepția cazului în care allow_duplicate_name este true. Numerele de act de identitate și onorariile nu pot fi setate.
Parametri de antet
Idempotency-KeyRecomandat la fiecare creare. O valoare unică per operație logică (de exemplu un UUID). Aceeași valoare returnează aceeași înregistrare: reîncercarea cu ea returnează înregistrarea creată prima dată, în loc să creeze o a doua. Valori diferite creează întotdeauna înregistrări diferite. Clienții care nu pot trimite anteturi pot transmite aceeași valoare în câmpul de corp idempotency_key. Litere, cifre, _, -, : sau ., cel mult 128 de caractere.
^[A-Za-z0-9_\-:.]{1,128}$Corpul cererii application/json
nameobligatoriuNumele complet al persoanei sau denumirea companiei. Text simplu; "<" și ">" nu sunt permise.
^[^<>]*$"Kovács Kft."is_persontrue pentru o persoană fizică, false (implicit) pentru o companie.
falseemail"info@kovacskft.hu"phone"+36 1 234 5678"addressAdresa înregistrată / de domiciliu.
Câmpurile address
zipcitystreetmailing_addressCâmpurile mailing_address
zipcitystreettax_numberCodul fiscal al companiei (doar pentru companii).
"12345678-2-41"company_registration_numberNumărul de înregistrare al companiei (doar pentru companii).
"01-09-123456"representative_nameDoar pentru companii.
representative_positionDoar pentru companii.
main_activityObiectul principal de activitate (doar pentru companii).
nationality_countrynoteallow_duplicate_nameCreează chiar dacă există un client activ cu același nume.
falseidempotency_keyAcelași rol ca antetul Idempotency-Key, pentru clienții care nu pot trimite anteturi personalizate. Litere, cifre, _, -, : sau ., cel mult 128 de caractere.
^[A-Za-z0-9_\-:.]{1,128}$"b8f1c2e0-6f7a-4d2e-9c1b-2a3d4e5f6a7b"Răspunsuri
201
Creat.
dataobligatoriuCâmpurile data
idId-ul clientului. Folosiți-l ca client_id în altă parte.
512name"Kovács Kft."is_personTrue pentru o persoană fizică, false pentru o companie.
emailphonearchivedrecorded_by_user_idrecorded_bycreated_atupdated_atcreated_via_apiCâmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduserataddressCâmpurile address
zipcitystreetmailing_addressCâmpurile mailing_address
zipcitystreettax_numberDoar pentru companii; null pentru o persoană fizică.
company_registration_numberDoar pentru companii; null pentru o persoană fizică.
representative_nameDoar pentru companii; null pentru o persoană fizică.
representative_positionDoar pentru companii; null pentru o persoană fizică.
main_activityObiectul principal de activitate. Doar pentru companii; null pentru o persoană fizică.
nationality_countrynotecreatedtrue
200
Reluare idempotentă: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică în interval de 120 de secunde) a creat deja înregistrarea; aceasta este returnată din nou, nu s-a creat nimic nou.
dataobligatoriuCâmpurile data
idId-ul clientului. Folosiți-l ca client_id în altă parte.
512name"Kovács Kft."is_personTrue pentru o persoană fizică, false pentru o companie.
emailphonearchivedrecorded_by_user_idrecorded_bycreated_atupdated_atcreated_via_apiCâmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduserataddressCâmpurile address
zipcitystreetmailing_addressCâmpurile mailing_address
zipcitystreettax_numberDoar pentru companii; null pentru o persoană fizică.
company_registration_numberDoar pentru companii; null pentru o persoană fizică.
representative_nameDoar pentru companii; null pentru o persoană fizică.
representative_positionDoar pentru companii; null pentru o persoană fizică.
main_activityObiectul principal de activitate. Doar pentru companii; null pentru o persoană fizică.
nationality_countrynotecreatedfalseidempotent_replaytrue
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator. replay_not_visible: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică) a creat deja înregistrarea (details.record_id), dar aceasta a fost între timp ștearsă sau nu este vizibilă pentru utilizator; nu s-a creat nimic nou, nu o creați din nou.
replay_not_visible: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică) a creat deja înregistrarea (details.record_id), dar aceasta a fost între timp ștearsă sau nu este vizibilă pentru utilizator; nu s-a creat nimic nou, nu o creați din nou.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
409
Există un client activ cu același nume (client_exists, sau client_exists_generic fără scope-ul clients:read, când clientul existent nu poate fi numit; transmiteți allow_duplicate_name pentru a suprascrie), Idempotency-Key a fost folosită pentru alt tip de resursă (idempotency_key_reused), sau, fără o cheie, o cerere identică este în curs de procesare (duplicate_in_progress).
client_exists, sau client_exists_generic fără scope-ul clients:read, când clientul existent nu poate fi numit; transmiteți allow_duplicate_name pentru a suprascrie), Idempotency-Key a fost folosită pentru alt tip de resursă (idempotency_key_reused), sau, fără o cheie, o cerere identică este în curs de procesare (duplicate_in_progress).
413
Corpul cererii este prea mare (request_too_large).
request_too_large).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl -X POST 'https://www.flowyer.ro/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.ro/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.ro/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"
}
Exemple de răspuns
{
"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": "Cererea nu este validă. Erorile pe câmpuri se găsesc în \"details.fields\".",
"locale": "ro",
"details": {
"fields": {
"name": [
"Câmpul name este obligatoriu."
]
}
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Actualizare client
/api/agent/clients/{id}
Modifică câmpurile de contact ale unui client (nume, e-mail, telefon, adresă, notă, naționalitate și reprezentantul/activitatea companiei). Numerele de act de identitate, codurile fiscale, onorariile și tipul persoană/companie nu pot fi editate aici. Transmiteți expected_updated_at; o modificare conflictuală răspunde cu 409.
Parametri de cale
idobligatoriuId-ul înregistrării de modificat.
Corpul cererii application/json
expected_updated_atValoarea updated_at din cea mai recentă citire a acestei înregistrări (obligatorie ori de câte ori înregistrarea are una). Dacă înregistrarea s-a schimbat între timp (un coleg a editat-o), API-ul răspunde cu 409 și trebuie să o recitiți înainte de a reîncerca. O înregistrare veche al cărei updated_at este null acceptă null.
nameNumele complet sau denumirea companiei. Text simplu, cel mult 255 de caractere ca valoare NOUĂ; "<" și ">" nu pot fi introduse nici ele, dar un nume stocat care este mai lung sau le conține poate fi trimis înapoi nemodificat. null păstrează numele curent.
emailphoneaddressAdresa înregistrată / de domiciliu.
Câmpurile address
zipcitystreetmailing_addressCâmpurile mailing_address
zipcitystreetrepresentative_nameDoar pentru companii.
representative_positionDoar pentru companii.
main_activityObiectul principal de activitate (doar pentru companii).
nationality_countrynoteNotă cu text liber, cel mult 4000 de caractere ca valoare NOUĂ; o notă stocată mai lungă poate fi trimisă înapoi nemodificată. null șterge nota.
Răspunsuri
200
Actualizat.
dataobligatoriuCâmpurile data
idId-ul clientului. Folosiți-l ca client_id în altă parte.
512name"Kovács Kft."is_personTrue pentru o persoană fizică, false pentru o companie.
emailphonearchivedrecorded_by_user_idrecorded_bycreated_atupdated_atcreated_via_apiCâmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduserataddressCâmpurile address
zipcitystreetmailing_addressCâmpurile mailing_address
zipcitystreettax_numberDoar pentru companii; null pentru o persoană fizică.
company_registration_numberDoar pentru companii; null pentru o persoană fizică.
representative_nameDoar pentru companii; null pentru o persoană fizică.
representative_positionDoar pentru companii; null pentru o persoană fizică.
main_activityObiectul principal de activitate. Doar pentru companii; null pentru o persoană fizică.
nationality_countrynoteupdatedtrue
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
409
Înregistrarea s-a schimbat de când ați citit-o (record_conflict: expected_updated_at nu mai corespunde; citiți-o din nou și reîncercați cu noul updated_at).
record_conflict: expected_updated_at nu mai corespunde; citiți-o din nou și reîncercați cu noul updated_at).
413
Corpul cererii este prea mare (request_too_large).
request_too_large).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl -X PATCH 'https://www.flowyer.ro/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.ro/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.ro/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"
}
Exemple de răspuns
{
"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": "Înregistrarea s-a modificat de când ați citit-o (cineva a editat-o). Citiți-o din nou și reîncercați cu noua valoare updated_at.",
"locale": "ro",
"details": {
"current_updated_at": "2026-10-30T10:42:05+01:00",
"reason": "modified_since_read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Sarcini
Listare sarcini
/api/agent/tasks
Listează sarcinile (lucruri de făcut cu termen limită) pe care utilizatorul le poate vedea, cel mai apropiat termen limită primul. Sarcinile deschise în mod implicit; filtrați după responsabil, dosar, client sau interval de termene.
Parametri de interogare
statusopen (implicit), closed sau all.
"open" "closed" "all" "open"assigned_to_user_idDoar sarcinile atribuite acestui utilizator (un id de utilizator din colleagues.list).
matter_idDoar sarcinile acestui dosar.
client_idDoar sarcinile fără dosar ale acestui client.
deadline_fromTermen limită la această dată sau ulterior.
"2026-11-01"deadline_toTermen limită la această dată sau anterior.
"2026-11-30"limitDimensiunea paginii, 1-100. Valoarea implicită este 25.
2525offsetNumărul de înregistrări de omis. Folosiți offset + limit ale paginii anterioare pentru a o obține pe următoarea; pagination.total este numărul total.
00Răspunsuri
200
OK.
dataobligatoriuCâmpurile data
id9876subject"Submit the statement of defence"descriptiondeadlineData scadentă, YYYY-MM-DD.
"2026-11-15"priority1 = scăzută, 2 = medie, 3 = ridicată; null = nesetată (o sarcină mai veche fără prioritate).
2status"open" "closed" closed_atZiua în care a fost închisă sarcina, YYYY-MM-DD. Flowyer înregistrează doar data, fără ora din zi.
matterDosarul de care aparține sarcina, dacă există.
Câmpurile matter
idcase_numberclientClientul: primul client al dosarului, sau clientul propriu al sarcinii când aceasta nu are dosar.
Câmpurile client
idnameassigned_to_user_idassigned_tocreated_by_user_idcreated_byflag_idcreated_atupdated_atcreated_via_apiCâmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduseratpaginationobligatoriuCâmpurile pagination
limitobligatoriuoffsetobligatoriutotalobligatoriuNumărul total de înregistrări care se potrivesc.
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl 'https://www.flowyer.ro/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.ro/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.ro/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())
Exemple de răspuns
{
"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": "Această cheie API nu are permisiunea \"tasks:read\". Permisiunile unei chei existente nu pot fi modificate, așa că titularul cheii trebuie să creeze în Flowyer, la Setări > Chei API, o cheie nouă cu această permisiune și să o folosească în locul celei vechi.",
"locale": "ro",
"details": {
"required_scope": "tasks:read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Obținere sarcină
/api/agent/tasks/{id}
Returnează o sarcină. Răspunde cu 404 când sarcina nu există sau utilizatorul nu o poate vedea.
Parametri de cale
idobligatoriuId-ul sarcinii.
9876Răspunsuri
200
OK.
dataobligatoriuCâmpurile data
id9876subject"Submit the statement of defence"descriptiondeadlineData scadentă, YYYY-MM-DD.
"2026-11-15"priority1 = scăzută, 2 = medie, 3 = ridicată; null = nesetată (o sarcină mai veche fără prioritate).
2status"open" "closed" closed_atZiua în care a fost închisă sarcina, YYYY-MM-DD. Flowyer înregistrează doar data, fără ora din zi.
matterDosarul de care aparține sarcina, dacă există.
Câmpurile matter
idcase_numberclientClientul: primul client al dosarului, sau clientul propriu al sarcinii când aceasta nu are dosar.
Câmpurile client
idnameassigned_to_user_idassigned_tocreated_by_user_idcreated_byflag_idcreated_atupdated_atcreated_via_apiCâmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduserat
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl 'https://www.flowyer.ro/api/agent/tasks/9876' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.ro/api/agent/tasks/9876", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.ro/api/agent/tasks/9876",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Exemple de răspuns
{
"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": "Înregistrarea nu a fost găsită sau nu este vizibilă pentru titularul acestei chei API.",
"locale": "ro",
"details": {
"task_id": 9876
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Creare sarcină
/api/agent/tasks
Creează o sarcină (ceva de făcut cu termen limită), fie pe un dosar (matter_id, vizibil și nearhivat), fie fără dosar, opțional pentru un client (client_id). Responsabilul este implicit utilizatorul cheii și este notificat când este altcineva.
Parametri de antet
Idempotency-KeyRecomandat la fiecare creare. O valoare unică per operație logică (de exemplu un UUID). Aceeași valoare returnează aceeași înregistrare: reîncercarea cu ea returnează înregistrarea creată prima dată, în loc să creeze o a doua. Valori diferite creează întotdeauna înregistrări diferite. Clienții care nu pot trimite anteturi pot transmite aceeași valoare în câmpul de corp idempotency_key. Litere, cifre, _, -, : sau ., cel mult 128 de caractere.
^[A-Za-z0-9_\-:.]{1,128}$Corpul cererii application/json
subjectobligatoriuCe trebuie făcut. Text simplu.
"Submit the statement of defence"deadlineobligatoriuData scadentă, YYYY-MM-DD.
"2026-11-15"matter_idDosarul de care aparține sarcina. Omiteți pentru o sarcină fără dosar.
1234client_idClientul unei sarcini fără dosar. Nu este permis împreună cu matter_id (o sarcină de pe un dosar preia clientul dosarului).
assigned_to_user_idColegul responsabil de sarcină: un id de utilizator din colleagues.list (căutați acolo un nume dictat). Implicit: utilizatorul din spatele cheii.
priority1 = scăzută, 2 = medie (implicit), 3 = ridicată.
2descriptionDetalii mai ample, text simplu.
flag_idId-ul unui indicator (etichetă) de sarcină al biroului.
idempotency_keyAcelași rol ca antetul Idempotency-Key, pentru clienții care nu pot trimite anteturi personalizate. Litere, cifre, _, -, : sau ., cel mult 128 de caractere.
^[A-Za-z0-9_\-:.]{1,128}$"b8f1c2e0-6f7a-4d2e-9c1b-2a3d4e5f6a7b"Răspunsuri
201
Creat.
dataobligatoriuCâmpurile data
id9876subject"Submit the statement of defence"descriptiondeadlineData scadentă, YYYY-MM-DD.
"2026-11-15"priority1 = scăzută, 2 = medie, 3 = ridicată; null = nesetată (o sarcină mai veche fără prioritate).
2status"open" "closed" closed_atZiua în care a fost închisă sarcina, YYYY-MM-DD. Flowyer înregistrează doar data, fără ora din zi.
matterDosarul de care aparține sarcina, dacă există.
Câmpurile matter
idcase_numberclientClientul: primul client al dosarului, sau clientul propriu al sarcinii când aceasta nu are dosar.
Câmpurile client
idnameassigned_to_user_idassigned_tocreated_by_user_idcreated_byflag_idcreated_atupdated_atcreated_via_apiCâmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduseratcreatedtrue
200
Reluare idempotentă: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică în interval de 120 de secunde) a creat deja înregistrarea; aceasta este returnată din nou, nu s-a creat nimic nou.
dataobligatoriuCâmpurile data
id9876subject"Submit the statement of defence"descriptiondeadlineData scadentă, YYYY-MM-DD.
"2026-11-15"priority1 = scăzută, 2 = medie, 3 = ridicată; null = nesetată (o sarcină mai veche fără prioritate).
2status"open" "closed" closed_atZiua în care a fost închisă sarcina, YYYY-MM-DD. Flowyer înregistrează doar data, fără ora din zi.
matterDosarul de care aparține sarcina, dacă există.
Câmpurile matter
idcase_numberclientClientul: primul client al dosarului, sau clientul propriu al sarcinii când aceasta nu are dosar.
Câmpurile client
idnameassigned_to_user_idassigned_tocreated_by_user_idcreated_byflag_idcreated_atupdated_atcreated_via_apiCâmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduseratcreatedfalseidempotent_replaytrue
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator. replay_not_visible: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică) a creat deja înregistrarea (details.record_id), dar aceasta a fost între timp ștearsă sau nu este vizibilă pentru utilizator; nu s-a creat nimic nou, nu o creați din nou.
replay_not_visible: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică) a creat deja înregistrarea (details.record_id), dar aceasta a fost între timp ștearsă sau nu este vizibilă pentru utilizator; nu s-a creat nimic nou, nu o creați din nou.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
409
Idempotency-Key a fost folosit pentru alt tip de resursă (idempotency_key_reused) sau, în lipsa unei chei, o cerere identică este procesată chiar acum (duplicate_in_progress; reîncercați în scurt timp).
idempotency_key_reused) sau, în lipsa unei chei, o cerere identică este procesată chiar acum (duplicate_in_progress; reîncercați în scurt timp).
413
Corpul cererii este prea mare (request_too_large).
request_too_large).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl -X POST 'https://www.flowyer.ro/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.ro/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.ro/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
}
Exemple de răspuns
{
"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": "Cererea nu este validă. Erorile pe câmpuri se găsesc în \"details.fields\".",
"locale": "ro",
"details": {
"fields": {
"subject": [
"Câmpul subject este obligatoriu."
]
}
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Actualizare sarcină
/api/agent/tasks/{id}
Modifică o sarcină: subiectul, termenul limită, descrierea, prioritatea, indicatorul, responsabilul sau dosarul de care aparține. Mutarea ei pe un dosar re-derivă legătura cu instanța și elimină un client direct; client_id este doar pentru o sarcină fără dosar. Transmiteți expected_updated_at; o modificare conflictuală răspunde cu 409.
Parametri de cale
idobligatoriuId-ul înregistrării de modificat.
Corpul cererii application/json
expected_updated_atValoarea updated_at din cea mai recentă citire a acestei înregistrări (obligatorie ori de câte ori înregistrarea are una). Dacă înregistrarea s-a schimbat între timp (un coleg a editat-o), API-ul răspunde cu 409 și trebuie să o recitiți înainte de a reîncerca. O înregistrare veche al cărei updated_at este null acceptă null.
subjectCe trebuie făcut. Text simplu, cel mult 1000 de caractere ca valoare NOUĂ; un subiect stocat mai lung poate fi trimis înapoi nemodificat. null păstrează subiectul curent.
deadlineData scadentă, YYYY-MM-DD. null păstrează termenul limită curent (un termen limită nu poate fi șters).
matter_idMută sarcina pe acest dosar (trebuie să fie vizibil și nearhivat), sau null pentru a o detașa. Trimiterea dosarului curent al sarcinii nu schimbă nimic.
client_idClientul unei sarcini fără dosar. Permis doar când sarcina nu are dosar.
assigned_to_user_idNoul responsabil: id-ul de utilizator al unui coleg activ din colleagues.list. Notificat când nu sunteți dumneavoastră. Trimiterea celui curent, sau null / 0, cu care o sarcină fără responsabil este citită înapoi, nu schimbă nimic.
priority1 = scăzută, 2 = medie, 3 = ridicată. Omiteți pentru a păstra prioritatea curentă (inclusiv când sarcina este citită înapoi cu priority null); null este respins.
descriptionDetalii mai ample, text simplu, cel mult 10000 de caractere ca valoare NOUĂ; o descriere stocată mai lungă poate fi trimisă înapoi nemodificată.
flag_idId-ul unui indicator (etichetă) de sarcină al biroului, sau null pentru a-l șterge.
Răspunsuri
200
Actualizat.
dataobligatoriuCâmpurile data
id9876subject"Submit the statement of defence"descriptiondeadlineData scadentă, YYYY-MM-DD.
"2026-11-15"priority1 = scăzută, 2 = medie, 3 = ridicată; null = nesetată (o sarcină mai veche fără prioritate).
2status"open" "closed" closed_atZiua în care a fost închisă sarcina, YYYY-MM-DD. Flowyer înregistrează doar data, fără ora din zi.
matterDosarul de care aparține sarcina, dacă există.
Câmpurile matter
idcase_numberclientClientul: primul client al dosarului, sau clientul propriu al sarcinii când aceasta nu are dosar.
Câmpurile client
idnameassigned_to_user_idassigned_tocreated_by_user_idcreated_byflag_idcreated_atupdated_atcreated_via_apiCâmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduseratupdatedtrue
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
409
Înregistrarea s-a schimbat de când ați citit-o (record_conflict: expected_updated_at nu mai corespunde; citiți-o din nou și reîncercați cu noul updated_at).
record_conflict: expected_updated_at nu mai corespunde; citiți-o din nou și reîncercați cu noul updated_at).
413
Corpul cererii este prea mare (request_too_large).
request_too_large).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl -X PATCH 'https://www.flowyer.ro/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.ro/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.ro/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"
}
Exemple de răspuns
{
"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": "Înregistrarea s-a modificat de când ați citit-o (cineva a editat-o). Citiți-o din nou și reîncercați cu noua valoare updated_at.",
"locale": "ro",
"details": {
"current_updated_at": "2026-10-30T10:42:05+01:00",
"reason": "modified_since_read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Închidere sarcină
/api/agent/tasks/{id}/close
Închide o sarcină. Dacă sunt furnizate minute, înregistrează și o intrare de timp (necesită workhours:create și un dosar: cel propriu al sarcinii, sau matter_id pe o sarcină fără dosar); minutele facturabile sunt limitate la plafonul orar al biroului. O a doua închidere răspunde cu 409, astfel încât o reîncercare nu înregistrează niciodată o a doua intrare.
Parametri de cale
idobligatoriuId-ul sarcinii.
9876Corpul cererii application/json
minutes_spentTimpul petrecut, în minute. Înregistrarea oricărui timp necesită scope-ul workhours:create și un dosar.
minutes_invoiceableMinute facturabile; limitate la plafonul orar al biroului.
minutes_normativeMinute normative; stocate brut, niciodată plafonate.
matter_idAtribuie acest dosar unei sarcini FĂRĂ DOSAR la închidere (și astfel face posibilă înregistrarea timpului). Nu este permis când sarcina are deja un dosar.
client_idClientul direct (Megbízó) pentru o sarcină fără dosar, închisă fără un dosar.
Răspunsuri
200
OK.
dataobligatoriuCâmpurile data
id9876subject"Submit the statement of defence"descriptiondeadlineData scadentă, YYYY-MM-DD.
"2026-11-15"priority1 = scăzută, 2 = medie, 3 = ridicată; null = nesetată (o sarcină mai veche fără prioritate).
2status"open" "closed" closed_atZiua în care a fost închisă sarcina, YYYY-MM-DD. Flowyer înregistrează doar data, fără ora din zi.
matterDosarul de care aparține sarcina, dacă există.
Câmpurile matter
idcase_numberclientClientul: primul client al dosarului, sau clientul propriu al sarcinii când aceasta nu are dosar.
Câmpurile client
idnameassigned_to_user_idassigned_tocreated_by_user_idcreated_byflag_idcreated_atupdated_atcreated_via_apiCâmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduseratbooked_workhourIntrarea de timp efectuată la închidere, sau null când nu a fost introdus timp.
Câmpurile booked_workhour
idminutesminutes_invoiceableminutes_normative
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
413
Corpul cererii este prea mare (request_too_large).
request_too_large).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl -X POST 'https://www.flowyer.ro/api/agent/tasks/9876/close' \
-H 'Authorization: Bearer flw_...' \
-H 'Content-Type: application/json' \
-d '{}'
const response = await fetch("https://www.flowyer.ro/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.ro/api/agent/tasks/9876/close",
headers={
"Authorization": "Bearer flw_...",
},
json={},
timeout=30,
)
print(response.status_code, response.json())
{}
Exemple de răspuns
{
"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": "Înregistrarea nu a fost găsită sau nu este vizibilă pentru titularul acestei chei API.",
"locale": "ro",
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Ore lucrate
Listare intrări de timp
/api/agent/workhours
Listează intrările de timp curente (încă nefacturate) de pe dosarele pe care utilizatorul le poate vedea, cele mai noi primele. Filtrați după dosar, coleg responsabil sau interval de date. Intrările excluse din rezumat sunt și ele listate, marcate cu excluded: true; lăsați-le în afara totalurilor facturabile.
Parametri de interogare
matter_idDoar intrările de pe acest dosar.
1234responsible_user_idDoar intrările atribuite acestui coleg (un id de utilizator din colleagues.list).
date_fromDoar intrările de la această dată sau ulterioare (YYYY-MM-DD).
date_toDoar intrările de la această dată sau anterioare (YYYY-MM-DD).
limitDimensiunea paginii, 1-100. Valoarea implicită este 25.
2525offsetNumărul de înregistrări de omis. Folosiți offset + limit ale paginii anterioare pentru a o obține pe următoarea; pagination.total este numărul total.
00Răspunsuri
200
OK.
dataobligatoriuCâmpurile data
idId-ul intrării de timp.
matter_idDosarul pe care este înregistrată intrarea.
dateactivityCe s-a făcut (text simplu).
minutesMinute petrecute.
minutes_invoiceableMinute facturabile după aplicarea plafonului orar al biroului (pot fi mai mici decât cele solicitate). Contează la facturare doar cât timp excluded este false.
minutes_normativeMinute normative (informative; niciodată plafonate).
responsible_user_idColegul pe care este înregistrat timpul.
responsiblerecorded_by_user_idCine a înregistrat intrarea.
lockedTrue când intrarea este blocată (doar pentru citire prin API).
excludedTrue când un coleg a exclus intrarea din rezumatul dosarului: nu este facturată și minutele ei sunt lăsate în afara totalurilor facturabile.
created_atupdated_atTrimiteți această valoare înapoi ca expected_updated_at la actualizare.
paginationobligatoriuCâmpurile pagination
limitobligatoriuoffsetobligatoriutotalobligatoriuNumărul total de înregistrări care se potrivesc.
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl 'https://www.flowyer.ro/api/agent/workhours?matter_id=1234&limit=25' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.ro/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.ro/api/agent/workhours?matter_id=1234&limit=25",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Exemple de răspuns
{
"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": "Această cheie API nu are permisiunea \"workhours:read\". Permisiunile unei chei existente nu pot fi modificate, așa că titularul cheii trebuie să creeze în Flowyer, la Setări > Chei API, o cheie nouă cu această permisiune și să o folosească în locul celei vechi.",
"locale": "ro",
"details": {
"required_scope": "workhours:read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Obținere intrare de timp
/api/agent/workhours/{id}
Returnează o intrare de timp curentă după id, dacă dosarul său este vizibil pentru utilizator.
Parametri de cale
idobligatoriuId-ul intrării de timp.
Răspunsuri
200
OK.
dataobligatoriuCâmpurile data
idId-ul intrării de timp.
matter_idDosarul pe care este înregistrată intrarea.
dateactivityCe s-a făcut (text simplu).
minutesMinute petrecute.
minutes_invoiceableMinute facturabile după aplicarea plafonului orar al biroului (pot fi mai mici decât cele solicitate). Contează la facturare doar cât timp excluded este false.
minutes_normativeMinute normative (informative; niciodată plafonate).
responsible_user_idColegul pe care este înregistrat timpul.
responsiblerecorded_by_user_idCine a înregistrat intrarea.
lockedTrue când intrarea este blocată (doar pentru citire prin API).
excludedTrue când un coleg a exclus intrarea din rezumatul dosarului: nu este facturată și minutele ei sunt lăsate în afara totalurilor facturabile.
created_atupdated_atTrimiteți această valoare înapoi ca expected_updated_at la actualizare.
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl 'https://www.flowyer.ro/api/agent/workhours/1234' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.ro/api/agent/workhours/1234", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.ro/api/agent/workhours/1234",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Exemple de răspuns
{
"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": "Înregistrarea nu a fost găsită sau nu este vizibilă pentru titularul acestei chei API.",
"locale": "ro",
"details": {
"record_type": "workhour",
"record_id": 1234
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Înregistrare intrare de timp
/api/agent/workhours
Înregistrează o intrare de timp pe un dosar: dată, activitate, minute petrecute și minute facturabile. Minutele facturabile omise înseamnă nefacturabil: trimiteți minutes_invoiceable pentru munca facturabilă. Ele sunt limitate la plafonul orar al biroului. Colegul responsabil este implicit utilizatorul cheii și este notificat în caz contrar.
Parametri de antet
Idempotency-KeyRecomandat la fiecare creare. O valoare unică per operație logică (de exemplu un UUID). Aceeași valoare returnează aceeași înregistrare: reîncercarea cu ea returnează înregistrarea creată prima dată, în loc să creeze o a doua. Valori diferite creează întotdeauna înregistrări diferite. Clienții care nu pot trimite anteturi pot transmite aceeași valoare în câmpul de corp idempotency_key. Litere, cifre, _, -, : sau ., cel mult 128 de caractere.
^[A-Za-z0-9_\-:.]{1,128}$Corpul cererii application/json
matter_idobligatoriuDosarul pe care este înregistrat timpul (trebuie să fie vizibil).
1234dateobligatoriuData lucrării, YYYY-MM-DD.
"2026-10-30"subjectCe s-a făcut; partea de citire o returnează ca activity și oricare dintre denumiri este acceptată aici (una dintre cele două este obligatorie). Text simplu; "<" și ">" nu sunt permise.
^[^<>]*$"Drafting the statement of claim"activityAcelași câmp ca subject, sub denumirea folosită de partea de citire. Trimiteți una dintre cele două.
^[^<>]*$minutesMinute efectiv petrecute.
90minutes_invoiceableMinute facturabile solicitate. Omise sau null = nefacturabil (intrarea nu facturează nimic; nu sunt derivate din minute): pentru munca facturabilă trimiteți-le explicit, de obicei egale cu minutele. Plafonul orar al biroului poate reduce valoarea stocată. Contează la facturare doar cât timp intrarea nu este exclusă din rezumat.
60minutes_normativeMinute normative (informative; niciodată plafonate).
responsible_user_idColegul pe care este înregistrat timpul: un id de utilizator din colleagues.list (căutați acolo un nume dictat). Implicit: utilizatorul din spatele cheii.
idempotency_keyAcelași rol ca antetul Idempotency-Key, pentru clienții care nu pot trimite anteturi personalizate. Litere, cifre, _, -, : sau ., cel mult 128 de caractere.
^[A-Za-z0-9_\-:.]{1,128}$"b8f1c2e0-6f7a-4d2e-9c1b-2a3d4e5f6a7b"Răspunsuri
201
Creat.
dataobligatoriuCâmpurile data
idId-ul intrării de timp.
matter_idDosarul pe care este înregistrată intrarea.
dateactivityCe s-a făcut (text simplu).
minutesMinute petrecute.
minutes_invoiceableMinute facturabile după aplicarea plafonului orar al biroului (pot fi mai mici decât cele solicitate). Contează la facturare doar cât timp excluded este false.
minutes_normativeMinute normative (informative; niciodată plafonate).
responsible_user_idColegul pe care este înregistrat timpul.
responsiblerecorded_by_user_idCine a înregistrat intrarea.
lockedTrue când intrarea este blocată (doar pentru citire prin API).
excludedTrue când un coleg a exclus intrarea din rezumatul dosarului: nu este facturată și minutele ei sunt lăsate în afara totalurilor facturabile.
created_atupdated_atTrimiteți această valoare înapoi ca expected_updated_at la actualizare.
createdtrue
200
Reluare idempotentă: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică în interval de 120 de secunde) a creat deja înregistrarea; aceasta este returnată din nou, nu s-a creat nimic nou.
dataobligatoriuCâmpurile data
idId-ul intrării de timp.
matter_idDosarul pe care este înregistrată intrarea.
dateactivityCe s-a făcut (text simplu).
minutesMinute petrecute.
minutes_invoiceableMinute facturabile după aplicarea plafonului orar al biroului (pot fi mai mici decât cele solicitate). Contează la facturare doar cât timp excluded este false.
minutes_normativeMinute normative (informative; niciodată plafonate).
responsible_user_idColegul pe care este înregistrat timpul.
responsiblerecorded_by_user_idCine a înregistrat intrarea.
lockedTrue când intrarea este blocată (doar pentru citire prin API).
excludedTrue când un coleg a exclus intrarea din rezumatul dosarului: nu este facturată și minutele ei sunt lăsate în afara totalurilor facturabile.
created_atupdated_atTrimiteți această valoare înapoi ca expected_updated_at la actualizare.
createdfalseidempotent_replaytrue
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator. replay_not_visible: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică) a creat deja înregistrarea (details.record_id), dar aceasta a fost între timp ștearsă sau nu este vizibilă pentru utilizator; nu s-a creat nimic nou, nu o creați din nou.
replay_not_visible: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică) a creat deja înregistrarea (details.record_id), dar aceasta a fost între timp ștearsă sau nu este vizibilă pentru utilizator; nu s-a creat nimic nou, nu o creați din nou.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
409
Idempotency-Key a fost folosit pentru alt tip de resursă (idempotency_key_reused) sau, în lipsa unei chei, o cerere identică este procesată chiar acum (duplicate_in_progress; reîncercați în scurt timp).
idempotency_key_reused) sau, în lipsa unei chei, o cerere identică este procesată chiar acum (duplicate_in_progress; reîncercați în scurt timp).
413
Corpul cererii este prea mare (request_too_large).
request_too_large).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl -X POST 'https://www.flowyer.ro/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.ro/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.ro/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
}
Exemple de răspuns
{
"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": "Cererea nu este validă. Erorile pe câmpuri se găsesc în \"details.fields\".",
"locale": "ro",
"details": {
"fields": {
"matter_id": [
"Câmpul matter id este obligatoriu."
]
}
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Actualizare intrare de timp
/api/agent/workhours/{id}
Modifică o intrare de timp curentă: dată, activitate (subject sau activity), minute, minute facturabile (un număr modificat este limitat la plafonul orar, unul retrimis identic este păstrat) și colegul responsabil. O intrare blocată sau facturată nu poate fi modificată (409). Transmiteți expected_updated_at; un conflict răspunde cu 409.
Parametri de cale
idobligatoriuId-ul înregistrării de modificat.
Corpul cererii application/json
expected_updated_atValoarea updated_at din cea mai recentă citire a acestei înregistrări (obligatorie ori de câte ori înregistrarea are una). Dacă înregistrarea s-a schimbat între timp (un coleg a editat-o), API-ul răspunde cu 409 și trebuie să o recitiți înainte de a reîncerca. O înregistrare veche al cărei updated_at este null acceptă null.
dateData lucrării, YYYY-MM-DD. null păstrează data curentă.
subjectCe s-a făcut, valoarea pe care partea de citire o returnează ca activity (oricare dintre denumiri este acceptată; null sub una dintre ele înseamnă "neprecizat", doar două texte diferite sunt respinse). Text simplu, cel mult 1000 de caractere ca valoare NOUĂ; "<" și ">" nu pot fi introduse nici ele, dar un text stocat care este mai lung sau le conține poate fi trimis înapoi nemodificat. null păstrează textul curent.
activityAcelași câmp ca subject, sub denumirea folosită de partea de citire. Trimiteți una dintre cele două (null sub cealaltă este acceptabil).
minutesMinute efectiv petrecute; null le șterge.
minutes_invoiceableMinute facturabile solicitate. Un număr diferit de cel stocat este limitat la cât a mai rămas din plafonul orar; retrimiterea valorii returnate de citire o păstrează așa cum a fost înregistrată (nu este limitată din nou). null le șterge. Contează la facturare doar cât timp intrarea nu este exclusă din rezumat (excluded este false).
minutes_normativeMinute normative (niciodată plafonate); null le șterge.
responsible_user_idNoul coleg responsabil: id-ul de utilizator al unui coleg activ din colleagues.list; notificat când nu sunteți dumneavoastră. Trimiterea celui curent, sau null / 0, cu care o intrare fără responsabil este citită înapoi, nu schimbă nimic.
Răspunsuri
200
Actualizat.
dataobligatoriuCâmpurile data
idId-ul intrării de timp.
matter_idDosarul pe care este înregistrată intrarea.
dateactivityCe s-a făcut (text simplu).
minutesMinute petrecute.
minutes_invoiceableMinute facturabile după aplicarea plafonului orar al biroului (pot fi mai mici decât cele solicitate). Contează la facturare doar cât timp excluded este false.
minutes_normativeMinute normative (informative; niciodată plafonate).
responsible_user_idColegul pe care este înregistrat timpul.
responsiblerecorded_by_user_idCine a înregistrat intrarea.
lockedTrue când intrarea este blocată (doar pentru citire prin API).
excludedTrue când un coleg a exclus intrarea din rezumatul dosarului: nu este facturată și minutele ei sunt lăsate în afara totalurilor facturabile.
created_atupdated_atTrimiteți această valoare înapoi ca expected_updated_at la actualizare.
updatedtrue
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
409
Înregistrarea s-a modificat de când ați citit-o (record_conflict: expected_updated_at nu mai corespunde; citiți-o din nou și reîncercați cu noul updated_at), sau a fost facturată / blocată și nu mai poate fi modificată prin API (record_locked; efectuați modificarea în Flowyer).
record_conflict: expected_updated_at nu mai corespunde; citiți-o din nou și reîncercați cu noul updated_at), sau a fost facturată / blocată și nu mai poate fi modificată prin API (record_locked; efectuați modificarea în Flowyer).
413
Corpul cererii este prea mare (request_too_large).
request_too_large).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl -X PATCH 'https://www.flowyer.ro/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.ro/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.ro/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"
}
Exemple de răspuns
{
"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": "Înregistrarea s-a modificat de când ați citit-o (cineva a editat-o). Citiți-o din nou și reîncercați cu noua valoare updated_at.",
"locale": "ro",
"details": {
"current_updated_at": "2026-10-30T10:42:05+01:00",
"reason": "modified_since_read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Costuri
Listare costuri
/api/agent/costs
Listează costurile curente ale dosarelor pe care utilizatorul le poate vedea, cele mai noi primele (un cost facturat nu mai apare aici). Filtrați după dosar, coleg responsabil sau interval de date. Sumele sunt nete. Rândurile marcate cu excluded: true sunt în afara rezumatului, iar rândurile marcate cu locked: true sunt gestionate de Flowyer.
Parametri de interogare
matter_idDoar costurile de pe acest dosar.
1234responsible_user_idDoar costurile înregistrate pentru acest coleg (un id de utilizator din colleagues.list).
date_fromDoar costurile de la această dată sau ulterioare (YYYY-MM-DD).
date_toDoar costurile de la această dată sau anterioare (YYYY-MM-DD).
limitDimensiunea paginii, 1-100. Valoarea implicită este 25.
2525offsetNumărul de înregistrări de omis. Folosiți offset + limit ale paginii anterioare pentru a o obține pe următoarea; pagination.total este numărul total.
00Răspunsuri
200
OK.
dataobligatoriuCâmpurile data
idId-ul costului.
matter_idDosarul de care aparține costul.
dateactivityDescrierea costului (text simplu).
costSuma netă a costului (fără TVA).
cost_invoiceableSuma netă de facturat mai departe către client. Contează la facturare doar cât timp excluded este false.
currency_idId-ul monedei (lista de monede Flowyer).
currencyCodul ISO al monedei, de ex. HUF, EUR.
responsible_user_idresponsibleexcludedTrue când un coleg a exclus costul din rezumatul dosarului: nu este facturat și este lăsat în afara totalurilor facturabile.
lockedTrue când costul este gestionat de Flowyer, preluat dintr-o factură primită sau un supliment de debursare, și nu poate fi modificat prin API (costs.update răspunde cu 409 record_locked, details.reason indică motivul).
approved_for_billingTrue când un coleg a aprobat costul pentru facturare în rezumatul dosarului. Rămâne editabil prin API (ca în interfața web), iar aprobarea NU este solicitată din nou ulterior: menționați acest lucru înainte de a modifica suma unui cost aprobat.
created_atupdated_atTrimiteți această valoare înapoi ca expected_updated_at la actualizare.
paginationobligatoriuCâmpurile pagination
limitobligatoriuoffsetobligatoriutotalobligatoriuNumărul total de înregistrări care se potrivesc.
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl 'https://www.flowyer.ro/api/agent/costs?matter_id=1234&limit=25' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.ro/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.ro/api/agent/costs?matter_id=1234&limit=25",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Exemple de răspuns
{
"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": "Această cheie API nu are permisiunea \"costs:read\". Permisiunile unei chei existente nu pot fi modificate, așa că titularul cheii trebuie să creeze în Flowyer, la Setări > Chei API, o cheie nouă cu această permisiune și să o folosească în locul celei vechi.",
"locale": "ro",
"details": {
"required_scope": "costs:read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Obținere cost
/api/agent/costs/{id}
Returnează un cost curent după id, dacă dosarul său este vizibil pentru utilizator. Sumele sunt nete.
Parametri de cale
idobligatoriuId-ul costului.
Răspunsuri
200
OK.
dataobligatoriuCâmpurile data
idId-ul costului.
matter_idDosarul de care aparține costul.
dateactivityDescrierea costului (text simplu).
costSuma netă a costului (fără TVA).
cost_invoiceableSuma netă de facturat mai departe către client. Contează la facturare doar cât timp excluded este false.
currency_idId-ul monedei (lista de monede Flowyer).
currencyCodul ISO al monedei, de ex. HUF, EUR.
responsible_user_idresponsibleexcludedTrue când un coleg a exclus costul din rezumatul dosarului: nu este facturat și este lăsat în afara totalurilor facturabile.
lockedTrue când costul este gestionat de Flowyer, preluat dintr-o factură primită sau un supliment de debursare, și nu poate fi modificat prin API (costs.update răspunde cu 409 record_locked, details.reason indică motivul).
approved_for_billingTrue când un coleg a aprobat costul pentru facturare în rezumatul dosarului. Rămâne editabil prin API (ca în interfața web), iar aprobarea NU este solicitată din nou ulterior: menționați acest lucru înainte de a modifica suma unui cost aprobat.
created_atupdated_atTrimiteți această valoare înapoi ca expected_updated_at la actualizare.
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl 'https://www.flowyer.ro/api/agent/costs/1234' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.ro/api/agent/costs/1234", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.ro/api/agent/costs/1234",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Exemple de răspuns
{
"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": "Înregistrarea nu a fost găsită sau nu este vizibilă pentru titularul acestei chei API.",
"locale": "ro",
"details": {
"record_type": "cost",
"record_id": 1234
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Înregistrare cost
/api/agent/costs
Înregistrează un cost (debursare) pe un dosar: dată, text (subject, citit înapoi ca activity), suma netă, suma netă facturată clientului și moneda (implicit: moneda biroului). Sumele sunt nete (fără TVA). Colegul responsabil este implicit utilizatorul cheii și este notificat în caz contrar.
Parametri de antet
Idempotency-KeyRecomandat la fiecare creare. O valoare unică per operație logică (de exemplu un UUID). Aceeași valoare returnează aceeași înregistrare: reîncercarea cu ea returnează înregistrarea creată prima dată, în loc să creeze o a doua. Valori diferite creează întotdeauna înregistrări diferite. Clienții care nu pot trimite anteturi pot transmite aceeași valoare în câmpul de corp idempotency_key. Litere, cifre, _, -, : sau ., cel mult 128 de caractere.
^[A-Za-z0-9_\-:.]{1,128}$Corpul cererii application/json
matter_idobligatoriuDosarul de care aparține costul (trebuie să fie vizibil).
1234dateobligatoriuData costului, YYYY-MM-DD.
"2026-10-30"subjectDescrierea costului; partea de citire o returnează ca activity și oricare dintre denumiri este acceptată aici (una dintre cele două este obligatorie). Text simplu; "<" și ">" nu sunt permise.
^[^<>]*$"Court filing fee"activityAcelași câmp ca subject, sub denumirea folosită de partea de citire. Trimiteți una dintre cele două.
^[^<>]*$costobligatoriuSuma netă a costului (fără TVA), un număr întreg în unitatea principală a monedei (subunitățile nu sunt stocate).
15000cost_invoiceableSuma netă de facturat mai departe către client, un număr întreg (omiteți dacă nu se facturează). Contează la facturare doar cât timp costul nu este exclus din rezumat.
15000currency_idId-ul monedei din lista de monede Flowyer (nu un cod ISO). Omiteți-l pentru a folosi moneda biroului (GET /me office.currency_id / office.currency); un id necunoscut răspunde cu 422, cu id-urile și codurile acceptate în details.allowed.
responsible_user_idColegul responsabil: un id de utilizator din colleagues.list (căutați acolo un nume dictat). Implicit: utilizatorul din spatele cheii.
idempotency_keyAcelași rol ca antetul Idempotency-Key, pentru clienții care nu pot trimite anteturi personalizate. Litere, cifre, _, -, : sau ., cel mult 128 de caractere.
^[A-Za-z0-9_\-:.]{1,128}$"b8f1c2e0-6f7a-4d2e-9c1b-2a3d4e5f6a7b"Răspunsuri
201
Creat.
dataobligatoriuCâmpurile data
idId-ul costului.
matter_idDosarul de care aparține costul.
dateactivityDescrierea costului (text simplu).
costSuma netă a costului (fără TVA).
cost_invoiceableSuma netă de facturat mai departe către client. Contează la facturare doar cât timp excluded este false.
currency_idId-ul monedei (lista de monede Flowyer).
currencyCodul ISO al monedei, de ex. HUF, EUR.
responsible_user_idresponsibleexcludedTrue când un coleg a exclus costul din rezumatul dosarului: nu este facturat și este lăsat în afara totalurilor facturabile.
lockedTrue când costul este gestionat de Flowyer, preluat dintr-o factură primită sau un supliment de debursare, și nu poate fi modificat prin API (costs.update răspunde cu 409 record_locked, details.reason indică motivul).
approved_for_billingTrue când un coleg a aprobat costul pentru facturare în rezumatul dosarului. Rămâne editabil prin API (ca în interfața web), iar aprobarea NU este solicitată din nou ulterior: menționați acest lucru înainte de a modifica suma unui cost aprobat.
created_atupdated_atTrimiteți această valoare înapoi ca expected_updated_at la actualizare.
createdtrue
200
Reluare idempotentă: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică în interval de 120 de secunde) a creat deja înregistrarea; aceasta este returnată din nou, nu s-a creat nimic nou.
dataobligatoriuCâmpurile data
idId-ul costului.
matter_idDosarul de care aparține costul.
dateactivityDescrierea costului (text simplu).
costSuma netă a costului (fără TVA).
cost_invoiceableSuma netă de facturat mai departe către client. Contează la facturare doar cât timp excluded este false.
currency_idId-ul monedei (lista de monede Flowyer).
currencyCodul ISO al monedei, de ex. HUF, EUR.
responsible_user_idresponsibleexcludedTrue când un coleg a exclus costul din rezumatul dosarului: nu este facturat și este lăsat în afara totalurilor facturabile.
lockedTrue când costul este gestionat de Flowyer, preluat dintr-o factură primită sau un supliment de debursare, și nu poate fi modificat prin API (costs.update răspunde cu 409 record_locked, details.reason indică motivul).
approved_for_billingTrue când un coleg a aprobat costul pentru facturare în rezumatul dosarului. Rămâne editabil prin API (ca în interfața web), iar aprobarea NU este solicitată din nou ulterior: menționați acest lucru înainte de a modifica suma unui cost aprobat.
created_atupdated_atTrimiteți această valoare înapoi ca expected_updated_at la actualizare.
createdfalseidempotent_replaytrue
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator. replay_not_visible: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică) a creat deja înregistrarea (details.record_id), dar aceasta a fost între timp ștearsă sau nu este vizibilă pentru utilizator; nu s-a creat nimic nou, nu o creați din nou.
replay_not_visible: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică) a creat deja înregistrarea (details.record_id), dar aceasta a fost între timp ștearsă sau nu este vizibilă pentru utilizator; nu s-a creat nimic nou, nu o creați din nou.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
409
Idempotency-Key a fost folosit pentru alt tip de resursă (idempotency_key_reused) sau, în lipsa unei chei, o cerere identică este procesată chiar acum (duplicate_in_progress; reîncercați în scurt timp).
idempotency_key_reused) sau, în lipsa unei chei, o cerere identică este procesată chiar acum (duplicate_in_progress; reîncercați în scurt timp).
413
Corpul cererii este prea mare (request_too_large).
request_too_large).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl -X POST 'https://www.flowyer.ro/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.ro/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.ro/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
}
Exemple de răspuns
{
"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": "Cererea nu este validă. Erorile pe câmpuri se găsesc în \"details.fields\".",
"locale": "ro",
"details": {
"fields": {
"matter_id": [
"Câmpul matter id este obligatoriu."
]
}
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Actualizare cost
/api/agent/costs/{id}
Modifică un cost curent: text (subject, citit înapoi ca activity), dată, sume nete, moneda și colegul responsabil. Un cost marcat cu locked: true nu poate fi modificat (409 record_locked, details.reason). Transmiteți expected_updated_at; o modificare conflictuală răspunde cu 409.
Parametri de cale
idobligatoriuId-ul înregistrării de modificat.
Corpul cererii application/json
expected_updated_atValoarea updated_at din cea mai recentă citire a acestei înregistrări (obligatorie ori de câte ori înregistrarea are una). Dacă înregistrarea s-a schimbat între timp (un coleg a editat-o), API-ul răspunde cu 409 și trebuie să o recitiți înainte de a reîncerca. O înregistrare veche al cărei updated_at este null acceptă null.
dateData costului, YYYY-MM-DD. null păstrează data curentă.
subjectDescrierea costului, valoarea pe care partea de citire o returnează ca activity (oricare dintre denumiri este acceptată; null sub una dintre ele înseamnă "neprecizat", doar două texte diferite sunt respinse). Text simplu, cel mult 1000 de caractere ca valoare NOUĂ; "<" și ">" nu pot fi introduse nici ele, dar un text stocat care este mai lung sau le conține poate fi trimis înapoi nemodificat. null păstrează textul curent.
activityAcelași câmp ca subject, sub denumirea folosită de partea de citire. Trimiteți una dintre cele două (null sub cealaltă este acceptabil).
costSuma netă a costului (fără TVA), un număr întreg în unitatea principală a monedei (subunitățile nu sunt stocate). null șterge suma.
cost_invoiceableSuma netă de facturat mai departe către client, un număr întreg; null o șterge. Contează la facturare doar cât timp costul nu este exclus din rezumat (excluded este false).
currency_idId-ul monedei din lista de monede Flowyer (nu un cod ISO; moneda biroului este GET /me office.currency_id). Un id necunoscut răspunde cu 422, cu id-urile și codurile acceptate în details.allowed. null, sau 0-ul cu care un cost mai vechi nesetat este citit înapoi, păstrează moneda curentă.
responsible_user_idNoul coleg responsabil: id-ul de utilizator al unui coleg activ din colleagues.list. Trimiterea celui curent, sau null / 0, cu care un cost fără responsabil este citit înapoi, nu schimbă nimic.
Răspunsuri
200
Actualizat.
dataobligatoriuCâmpurile data
idId-ul costului.
matter_idDosarul de care aparține costul.
dateactivityDescrierea costului (text simplu).
costSuma netă a costului (fără TVA).
cost_invoiceableSuma netă de facturat mai departe către client. Contează la facturare doar cât timp excluded este false.
currency_idId-ul monedei (lista de monede Flowyer).
currencyCodul ISO al monedei, de ex. HUF, EUR.
responsible_user_idresponsibleexcludedTrue când un coleg a exclus costul din rezumatul dosarului: nu este facturat și este lăsat în afara totalurilor facturabile.
lockedTrue când costul este gestionat de Flowyer, preluat dintr-o factură primită sau un supliment de debursare, și nu poate fi modificat prin API (costs.update răspunde cu 409 record_locked, details.reason indică motivul).
approved_for_billingTrue când un coleg a aprobat costul pentru facturare în rezumatul dosarului. Rămâne editabil prin API (ca în interfața web), iar aprobarea NU este solicitată din nou ulterior: menționați acest lucru înainte de a modifica suma unui cost aprobat.
created_atupdated_atTrimiteți această valoare înapoi ca expected_updated_at la actualizare.
updatedtrue
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
409
Înregistrarea s-a modificat de când ați citit-o (record_conflict: expected_updated_at nu mai corespunde; citiți-o din nou și reîncercați cu noul updated_at), sau a fost facturată / blocată și nu mai poate fi modificată prin API (record_locked; efectuați modificarea în Flowyer).
record_conflict: expected_updated_at nu mai corespunde; citiți-o din nou și reîncercați cu noul updated_at), sau a fost facturată / blocată și nu mai poate fi modificată prin API (record_locked; efectuați modificarea în Flowyer).
413
Corpul cererii este prea mare (request_too_large).
request_too_large).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl -X PATCH 'https://www.flowyer.ro/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.ro/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.ro/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"
}
Exemple de răspuns
{
"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": "Înregistrarea s-a modificat de când ați citit-o (cineva a editat-o). Citiți-o din nou și reîncercați cu noua valoare updated_at.",
"locale": "ro",
"details": {
"current_updated_at": "2026-10-30T10:42:05+01:00",
"reason": "modified_since_read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Facturi
Listare facturi
/api/agent/invoices
Listează facturile (emise și primite), cea mai recentă dată de emitere prima. direction=outgoing este lista facturilor emise de birou și exclude proformele (direction=proforma le listează pe acelea). Doar pentru citire: facturile nu pot fi create sau modificate prin API. Facturile dosarelor pe care utilizatorul nu le poate vedea sunt ascunse.
Parametri de interogare
directionCele trei liste proprii ale biroului: outgoing = facturi emise de birou, proformele excluse (un rând mai vechi fără tip de document contează ca factură, ca în tabloul de bord al biroului); proforma = cereri de plată (díjbekérő) emise de birou; incoming = primite.
"incoming" "outgoing" "proforma" paid_status"unpaid" "paid" "partially_paid" "cancelled" client_idmatter_idissued_fromData de emitere la această dată sau ulterioară.
"2026-01-01"issued_toData de emitere la această dată sau anterioară.
"2026-12-31"limitDimensiunea paginii, 1-100. Valoarea implicită este 25.
2525offsetNumărul de înregistrări de omis. Folosiți offset + limit ale paginii anterioare pentru a o obține pe următoarea; pagination.total este numărul total.
00Răspunsuri
200
OK.
dataobligatoriuCâmpurile data
id301invoice_number"FLW-2026-0042"directionoutgoing = emise de birou, incoming = primite de birou.
"incoming" "outgoing" document_type"proforma" este o cerere de plată, nu o factură emisă: nu este venit și nu trebuie contabilizată împreună cu cele emise. invoices.list direction=outgoing exclude proformele, direction=proforma le listează. Null pe un rând mai vechi, care contează ca factură.
"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_methodDenumirea localizată a metodei de plată (de ex. transfer bancar); în engleză când limba biroului nu are o traducere pentru ea, null când metoda nu are deloc un nume. Identificați metoda după payment_method_id.
supplierEmitentul unei facturi primite.
clientCâmpurile client
idnamematter_idcreated_atupdated_atpaginationobligatoriuCâmpurile pagination
limitobligatoriuoffsetobligatoriutotalobligatoriuNumărul total de înregistrări care se potrivesc.
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl 'https://www.flowyer.ro/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.ro/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.ro/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())
Exemple de răspuns
{
"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": "Această cheie API nu are permisiunea \"invoices:read\". Permisiunile unei chei existente nu pot fi modificate, așa că titularul cheii trebuie să creeze în Flowyer, la Setări > Chei API, o cheie nouă cu această permisiune și să o folosească în locul celei vechi.",
"locale": "ro",
"details": {
"required_scope": "invoices:read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Obținere factură
/api/agent/invoices/{id}
Returnează o factură. Doar pentru citire. Răspunde cu 404 când nu există sau aparține unui dosar pe care utilizatorul nu îl poate vedea.
Parametri de cale
idobligatoriuId-ul facturii.
301Răspunsuri
200
OK.
dataobligatoriuCâmpurile data
id301invoice_number"FLW-2026-0042"directionoutgoing = emise de birou, incoming = primite de birou.
"incoming" "outgoing" document_type"proforma" este o cerere de plată, nu o factură emisă: nu este venit și nu trebuie contabilizată împreună cu cele emise. invoices.list direction=outgoing exclude proformele, direction=proforma le listează. Null pe un rând mai vechi, care contează ca factură.
"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_methodDenumirea localizată a metodei de plată (de ex. transfer bancar); în engleză când limba biroului nu are o traducere pentru ea, null când metoda nu are deloc un nume. Identificați metoda după payment_method_id.
supplierEmitentul unei facturi primite.
clientCâmpurile client
idnamematter_idcreated_atupdated_atnotesreceived_datesent_dateproforma_invoice_id
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl 'https://www.flowyer.ro/api/agent/invoices/301' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.ro/api/agent/invoices/301", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.ro/api/agent/invoices/301",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Exemple de răspuns
{
"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": "Înregistrarea nu a fost găsită sau nu este vizibilă pentru titularul acestei chei API.",
"locale": "ro",
"details": {
"invoice_id": 301
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Documente
Listați documentele unui dosar
/api/agent/matters/{id}/documents
Listează versiunile curente ale documentelor arhivate sub un dosar: nume, dimensiuni, foldere și cine le-a încărcat. Doar metadate; folosiți documents.download (scope documents:download) pentru un link semnat către conținut. Documentele cu nume apar primele, în ordine alfabetică, apoi cele importate care nu au nume.
Parametri de cale
idobligatoriuId-ul dosarului.
1234Parametri de interogare
qFiltrați după numele fișierului.
"contract"limitDimensiunea paginii, 1-100. Valoarea implicită este 25.
2525offsetNumărul de înregistrări de omis. Folosiți offset + limit ale paginii anterioare pentru a o obține pe următoarea; pagination.total este numărul total.
00Răspunsuri
200
OK.
dataobligatoriuCâmpurile data
idnameNumele fișierului așa cum este afișat în Flowyer: numele stocat împreună cu documentul sau numele de stocare al acestuia atunci când a fost importat dintr-un sistem mai vechi fără nume. documents.list este ordonat după numele stocat: documentele care au unul apar primele, în ordine alfabetică, apoi cele importate fără nume stocat, cele mai vechi primele (ordinea în care au fost arhivate în Flowyer), care, prin urmare, nu sunt sortate după numele afișat aici. Ordinea este aceeași pe fiecare pagină, astfel încât limit și offset parcurg lista fără repetări sau lacune.
"Contract_v2.docx"sizeOcteți.
versionNumărul versiunii curente a fișierului.
folderFolderul în care este arhivat documentul sau null la rădăcina dosarului. documents.upload.complete răspunde cu null atunci când folderul ales la documents.upload.init a fost șters în timp ce octeții se încărcau: documentul este atunci arhivat la rădăcina dosarului, unde îl afișează Flowyer. Dacă rădăcina conține deja un document cu acel nume, încărcarea este arhivată sub un nume cu sufix ("Contract_2.pdf") în loc să devină o versiune nouă a acelui document fără legătură; răspunsul 201 reia name stocat.
Câmpurile folder
idnamepathCalea folderului în interiorul dosarului, separată prin "/".
folder_deletedTrue atunci când documentul este arhivat într-un folder care nu mai există, lucru pe care lista de fișiere proprie a Flowyer nu îl afișează (folder este null pentru el, la fel ca pentru un document aflat la rădăcina dosarului). documents.upload.complete răspunde cu true doar dacă folderul a fost șters în timp ce octeții se încărcau ȘI mutarea fișierului stocat la rădăcina dosarului a eșuat: documentul este atunci păstrat în folderul șters, unde conținutul lui este încă accesibil. False pentru orice altceva, inclusiv o arhivare normală la rădăcină.
created_by_user_idcreated_bycreated_atupdated_atpaginationobligatoriuCâmpurile pagination
limitobligatoriuoffsetobligatoriutotalobligatoriuNumărul total de înregistrări care se potrivesc.
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl 'https://www.flowyer.ro/api/agent/matters/1234/documents?q=contract&limit=25' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.ro/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.ro/api/agent/matters/1234/documents?q=contract&limit=25",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Exemple de răspuns
{
"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": "Dosarul 1234 nu există, este arhivat sau nu este vizibil pentru titularul acestei chei API.",
"locale": "ro",
"details": {
"matter_id": 1234
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Listați folderele unui dosar
/api/agent/matters/{id}/folders
Listează fiecare folder al unui dosar, inclusiv cele goale: id, name, parent_id și calea separată prin "/", ordonate după cale. Transmiteți un id de folder ca folder_id către documents.upload.init. Răspunde cu 404 atunci când dosarul nu este vizibil pentru utilizator.
Parametri de cale
idobligatoriuId-ul dosarului.
1234Parametri de interogare
qDoar folderele a căror cale conține acest text (ignorând majusculele și diacriticele), de exemplu un nume de folder.
"Beadványok"limitDimensiunea paginii, 1-100. Valoarea implicită este 25.
2525offsetNumărul de înregistrări de omis. Folosiți offset + limit ale paginii anterioare pentru a o obține pe următoarea; pagination.total este numărul total.
00Răspunsuri
200
OK.
dataobligatoriuCâmpurile data
idId-ul folderului: transmiteți-l ca folder_id către documents.upload.init.
nameNumele folderului așa cum este afișat în Flowyer.
parent_idId-ul folderului părinte; null pentru un folder aflat la rădăcina dosarului.
pathCalea folderului în interiorul dosarului, separată prin "/", de exemplu "/Iratok/Beadványok" (aceeași cale pe care documents.list o afișează pentru folderul unui fișier).
updated_atTransmiteți aceasta către documents.folders.rename ca expected_updated_at.
paginationobligatoriuCâmpurile pagination
limitobligatoriuoffsetobligatoriutotalobligatoriuNumărul total de înregistrări care se potrivesc.
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl 'https://www.flowyer.ro/api/agent/matters/1234/folders?q=Beadv%C3%A1nyok&limit=25' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.ro/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.ro/api/agent/matters/1234/folders?q=Beadv%C3%A1nyok&limit=25",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Exemple de răspuns
{
"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": "Dosarul 1234 nu există, este arhivat sau nu este vizibil pentru titularul acestei chei API.",
"locale": "ro",
"details": {
"matter_id": 1234
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Creare folder de dosar
/api/agent/matters/{id}/folders
Creează un folder într-un dosar, la rădăcină sau sub parent_id (un folder al ACELUIAȘI dosar). Numele este text simplu ("<" și ">" nu sunt permise). Arhivați un document în el transmițând id-ul returnat ca folder_id către documents.upload.init. Răspunde cu 404 când dosarul nu este vizibil.
Parametri de cale
idobligatoriuDosarul de care aparține folderul (trebuie să fie vizibil).
1234Parametri de antet
Idempotency-KeyRecomandat la fiecare creare. O valoare unică per operație logică (de exemplu un UUID). Aceeași valoare returnează aceeași înregistrare: reîncercarea cu ea returnează înregistrarea creată prima dată, în loc să creeze o a doua. Valori diferite creează întotdeauna înregistrări diferite. Clienții care nu pot trimite anteturi pot transmite aceeași valoare în câmpul de corp idempotency_key. Litere, cifre, _, -, : sau ., cel mult 128 de caractere.
^[A-Za-z0-9_\-:.]{1,128}$Corpul cererii application/json
nameobligatoriuNumele folderului, cel mult 255 de caractere. Text simplu; "<" și ">" nu sunt permise.
^[^<>]*$"Beadványok"parent_idId-ul folderului părinte (din documents.folders) din interiorul ACELUIAȘI dosar; omiteți pentru un folder aflat la rădăcina dosarului.
idempotency_keyAcelași rol ca antetul Idempotency-Key, pentru clienții care nu pot trimite anteturi personalizate. Litere, cifre, _, -, : sau ., cel mult 128 de caractere.
^[A-Za-z0-9_\-:.]{1,128}$"b8f1c2e0-6f7a-4d2e-9c1b-2a3d4e5f6a7b"Răspunsuri
201
Creat.
dataobligatoriuCâmpurile data
idId-ul folderului: transmiteți-l ca folder_id către documents.upload.init, sau ca parent_id către documents.folders.create.
nameNumele folderului așa cum este afișat în Flowyer.
parent_idId-ul folderului părinte; null pentru un folder aflat la rădăcina dosarului.
pathCalea folderului în interiorul dosarului, separată prin "/", de exemplu "/Iratok/Beadványok".
updated_atTransmiteți aceasta către documents.folders.rename ca expected_updated_at.
createdtrue
200
Reluare idempotentă: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică în interval de 120 de secunde) a creat deja înregistrarea; aceasta este returnată din nou, nu s-a creat nimic nou.
dataobligatoriuCâmpurile data
idId-ul folderului: transmiteți-l ca folder_id către documents.upload.init, sau ca parent_id către documents.folders.create.
nameNumele folderului așa cum este afișat în Flowyer.
parent_idId-ul folderului părinte; null pentru un folder aflat la rădăcina dosarului.
pathCalea folderului în interiorul dosarului, separată prin "/", de exemplu "/Iratok/Beadványok".
updated_atTransmiteți aceasta către documents.folders.rename ca expected_updated_at.
createdfalseidempotent_replaytrue
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator. replay_not_visible: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică) a creat deja înregistrarea (details.record_id), dar aceasta a fost între timp ștearsă sau nu este vizibilă pentru utilizator; nu s-a creat nimic nou, nu o creați din nou.
replay_not_visible: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică) a creat deja înregistrarea (details.record_id), dar aceasta a fost între timp ștearsă sau nu este vizibilă pentru utilizator; nu s-a creat nimic nou, nu o creați din nou.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
409
Idempotency-Key a fost folosit pentru alt tip de resursă (idempotency_key_reused) sau, în lipsa unei chei, o cerere identică este procesată chiar acum (duplicate_in_progress; reîncercați în scurt timp).
idempotency_key_reused) sau, în lipsa unei chei, o cerere identică este procesată chiar acum (duplicate_in_progress; reîncercați în scurt timp).
413
Corpul cererii este prea mare (request_too_large).
request_too_large).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl -X POST 'https://www.flowyer.ro/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.ro/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.ro/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"
}
Exemple de răspuns
{
"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": "Cererea nu este validă. Erorile pe câmpuri se găsesc în \"details.fields\".",
"locale": "ro",
"details": {
"fields": {
"name": [
"Câmpul name este obligatoriu."
]
}
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Începeți încărcarea unui document
/api/agent/matters/{id}/documents/uploads
Începe încărcarea unui document: returnează un upload_url semnat și un upload_token. Trimiteți octeții acolo prin PUT, apoi apelați documents.upload.complete. Operația PUT este o cerere HTTPS obișnuită în afara acestui API și în afara instrumentelor MCP: un asistent fără propriul client HTTP ar trebui să ceară utilizatorului să încarce fișierul în Flowyer.
Parametri de cale
idobligatoriuDosarul căruia îi aparține documentul (trebuie să fie vizibil).
Corpul cererii application/json
filenameobligatoriuNumele fișierului cu extensie, de exemplu "Contract.pdf". Text simplu; "<" și ">" nu sunt permise. Tipurile de fișiere executabile și web sunt refuzate (422 blocked_file_type).
^[^<>]*$"Contract.pdf"content_typeobligatoriuTipul MIME trimis la operația PUT, de exemplu "application/pdf". Face parte din semnătură și trebuie să corespundă exact.
"application/pdf"sizeobligatoriuDimensiunea fișierului în octeți, cel mult 104857600 (limita de încărcare); o dimensiune mai mare răspunde cu 413 file_too_large.
248000folder_idFolderul din interiorul dosarului: un id de folder din documents.folders (acesta listează și folderele goale). Omiteți pentru rădăcina dosarului.
Răspunsuri
200
OK.
dataobligatoriuCâmpurile data
upload_urlURL semnat. Trimiteți octeții fișierului aici prin PUT, cu tipul de conținut indicat ȘI antetul if_generation_match de mai jos: o cerere HTTPS obișnuită făcută de propriul dumneavoastră client HTTP (niciun instrument API sau MCP nu o trimite).
upload_tokenTransmiteți aceasta către documents.upload.complete după ce operația PUT reușește.
content_typeTrimiteți exact acest Content-Type la operația PUT.
if_generation_matchTrimiteți această valoare ca antet "x-goog-if-generation-match" la operația PUT (întotdeauna "0"). Face încărcarea de unică folosință: operația PUT este acceptată doar cât timp obiectul nu există încă, astfel încât URL-ul semnat nu poate suprascrie un document deja arhivat.
object_keyNumele intern de stocare (pentru referință).
expires_inSecunde până la expirarea URL-ului de încărcare și a tokenului.
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
413
Corpul cererii este prea mare (request_too_large) sau fișierul depășește limita de încărcare (file_too_large; details.max indică limita în octeți).
request_too_large) sau fișierul depășește limita de încărcare (file_too_large; details.max indică limita în octeți).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl -X POST 'https://www.flowyer.ro/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.ro/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.ro/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
}
Exemple de răspuns
{
"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": "Cererea nu este validă. Erorile pe câmpuri se găsesc în \"details.fields\".",
"locale": "ro",
"details": {
"fields": {
"filename": [
"Câmpul filename este obligatoriu."
]
}
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Finalizați încărcarea unui document
/api/agent/matters/{id}/documents
Finalizează încărcarea unui document: după ce octeții au fost trimiși prin PUT către upload_url, înregistrează fișierul pe dosar ca o versiune nouă. Transmiteți upload_token de la documents.upload.init. Metadatele fișierului sunt preluate din token, nu din această cerere. Un folder șters între timp arhivează documentul la rădăcină.
Parametri de cale
idobligatoriuDosarul căruia îi aparține documentul (același ca la init).
Parametri de antet
Idempotency-KeyRecomandat la fiecare creare. O valoare unică per operație logică (de exemplu un UUID). Aceeași valoare returnează aceeași înregistrare: reîncercarea cu ea returnează înregistrarea creată prima dată, în loc să creeze o a doua. Valori diferite creează întotdeauna înregistrări diferite. Clienții care nu pot trimite anteturi pot transmite aceeași valoare în câmpul de corp idempotency_key. Litere, cifre, _, -, : sau ., cel mult 128 de caractere.
^[A-Za-z0-9_\-:.]{1,128}$Corpul cererii application/json
upload_tokenobligatoriuTokenul returnat de documents.upload.init.
idempotency_keyAcelași rol ca antetul Idempotency-Key, pentru clienții care nu pot trimite anteturi personalizate. Litere, cifre, _, -, : sau ., cel mult 128 de caractere.
^[A-Za-z0-9_\-:.]{1,128}$"b8f1c2e0-6f7a-4d2e-9c1b-2a3d4e5f6a7b"Răspunsuri
201
Creat.
dataobligatoriuCâmpurile data
idnameNumele fișierului așa cum este afișat în Flowyer: numele stocat împreună cu documentul sau numele de stocare al acestuia atunci când a fost importat dintr-un sistem mai vechi fără nume. documents.list este ordonat după numele stocat: documentele care au unul apar primele, în ordine alfabetică, apoi cele importate fără nume stocat, cele mai vechi primele (ordinea în care au fost arhivate în Flowyer), care, prin urmare, nu sunt sortate după numele afișat aici. Ordinea este aceeași pe fiecare pagină, astfel încât limit și offset parcurg lista fără repetări sau lacune.
"Contract_v2.docx"sizeOcteți.
versionNumărul versiunii curente a fișierului.
folderFolderul în care este arhivat documentul sau null la rădăcina dosarului. documents.upload.complete răspunde cu null atunci când folderul ales la documents.upload.init a fost șters în timp ce octeții se încărcau: documentul este atunci arhivat la rădăcina dosarului, unde îl afișează Flowyer. Dacă rădăcina conține deja un document cu acel nume, încărcarea este arhivată sub un nume cu sufix ("Contract_2.pdf") în loc să devină o versiune nouă a acelui document fără legătură; răspunsul 201 reia name stocat.
Câmpurile folder
idnamepathCalea folderului în interiorul dosarului, separată prin "/".
folder_deletedTrue atunci când documentul este arhivat într-un folder care nu mai există, lucru pe care lista de fișiere proprie a Flowyer nu îl afișează (folder este null pentru el, la fel ca pentru un document aflat la rădăcina dosarului). documents.upload.complete răspunde cu true doar dacă folderul a fost șters în timp ce octeții se încărcau ȘI mutarea fișierului stocat la rădăcina dosarului a eșuat: documentul este atunci păstrat în folderul șters, unde conținutul lui este încă accesibil. False pentru orice altceva, inclusiv o arhivare normală la rădăcină.
created_by_user_idcreated_bycreated_atupdated_atcreatedtrue
200
Reluare idempotentă: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică în interval de 120 de secunde) a creat deja înregistrarea; aceasta este returnată din nou, nu s-a creat nimic nou. Este, de asemenea, răspunsul atunci când acest upload_token a fost deja finalizat.
dataobligatoriuCâmpurile data
idnameNumele fișierului așa cum este afișat în Flowyer: numele stocat împreună cu documentul sau numele de stocare al acestuia atunci când a fost importat dintr-un sistem mai vechi fără nume. documents.list este ordonat după numele stocat: documentele care au unul apar primele, în ordine alfabetică, apoi cele importate fără nume stocat, cele mai vechi primele (ordinea în care au fost arhivate în Flowyer), care, prin urmare, nu sunt sortate după numele afișat aici. Ordinea este aceeași pe fiecare pagină, astfel încât limit și offset parcurg lista fără repetări sau lacune.
"Contract_v2.docx"sizeOcteți.
versionNumărul versiunii curente a fișierului.
folderFolderul în care este arhivat documentul sau null la rădăcina dosarului. documents.upload.complete răspunde cu null atunci când folderul ales la documents.upload.init a fost șters în timp ce octeții se încărcau: documentul este atunci arhivat la rădăcina dosarului, unde îl afișează Flowyer. Dacă rădăcina conține deja un document cu acel nume, încărcarea este arhivată sub un nume cu sufix ("Contract_2.pdf") în loc să devină o versiune nouă a acelui document fără legătură; răspunsul 201 reia name stocat.
Câmpurile folder
idnamepathCalea folderului în interiorul dosarului, separată prin "/".
folder_deletedTrue atunci când documentul este arhivat într-un folder care nu mai există, lucru pe care lista de fișiere proprie a Flowyer nu îl afișează (folder este null pentru el, la fel ca pentru un document aflat la rădăcina dosarului). documents.upload.complete răspunde cu true doar dacă folderul a fost șters în timp ce octeții se încărcau ȘI mutarea fișierului stocat la rădăcina dosarului a eșuat: documentul este atunci păstrat în folderul șters, unde conținutul lui este încă accesibil. False pentru orice altceva, inclusiv o arhivare normală la rădăcină.
created_by_user_idcreated_bycreated_atupdated_atcreatedfalseidempotent_replaytrue
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator. upload_not_finished: fișierul nu a ajuns încă în stocare; finalizați operația PUT către upload_url, apoi apelați complete din nou. replay_not_visible: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică) a creat deja înregistrarea (details.record_id), dar aceasta a fost între timp ștearsă sau nu este vizibilă pentru utilizator; nu s-a creat nimic nou, nu o creați din nou.
upload_not_finished: fișierul nu a ajuns încă în stocare; finalizați operația PUT către upload_url, apoi apelați complete din nou. replay_not_visible: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică) a creat deja înregistrarea (details.record_id), dar aceasta a fost între timp ștearsă sau nu este vizibilă pentru utilizator; nu s-a creat nimic nou, nu o creați din nou.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
409
Idempotency-Key a fost folosit pentru alt tip de resursă (idempotency_key_reused) sau, în lipsa unei chei, o cerere identică este procesată chiar acum (duplicate_in_progress; reîncercați în scurt timp).
idempotency_key_reused) sau, în lipsa unei chei, o cerere identică este procesată chiar acum (duplicate_in_progress; reîncercați în scurt timp).
413
Corpul cererii este prea mare (request_too_large) sau fișierul depășește limita de încărcare (file_too_large; details.max indică limita în octeți).
request_too_large) sau fișierul depășește limita de încărcare (file_too_large; details.max indică limita în octeți).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl -X POST 'https://www.flowyer.ro/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.ro/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.ro/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"
}
Exemple de răspuns
{
"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": "Cererea nu este validă. Erorile pe câmpuri se găsesc în \"details.fields\".",
"locale": "ro",
"details": {
"fields": {
"upload_token": [
"Câmpul upload token este obligatoriu."
]
}
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Descărcare document
/api/agent/documents/{id}/download
Returnează un URL semnat cu durată scurtă de viață pentru a descărca un document după id, dacă dosarul său este vizibil. Efectuați GET pe url pentru a prelua octeții; expiră în câteva minute.
Parametri de cale
idobligatoriuId-ul documentului (din documents.list).
Răspunsuri
200
OK.
dataobligatoriuCâmpurile data
download_urlURL semnat. Efectuați GET pe el pentru a descărca octeții fișierului.
filenameNumele de fișier pentru descărcare.
sizeOcteți.
expires_inNumărul de secunde până la expirarea URL-ului.
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl 'https://www.flowyer.ro/api/agent/documents/1234/download' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.ro/api/agent/documents/1234/download", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.ro/api/agent/documents/1234/download",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Exemple de răspuns
{
"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": "Înregistrarea nu a fost găsită sau nu este vizibilă pentru titularul acestei chei API.",
"locale": "ro",
"details": {
"record_type": "document",
"record_id": 1234
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Redenumire document
/api/agent/documents/{id}
Redenumește un document (doar numele afișat; conținutul fișierului rămâne neschimbat). Noul nume trebuie să fie unic în aceeași mapă a dosarului. Transmiteți expected_updated_at din ultima citire; o modificare conflictuală răspunde cu 409.
Parametri de cale
idobligatoriuId-ul înregistrării de modificat.
Corpul cererii application/json
expected_updated_atValoarea updated_at din cea mai recentă citire a acestei înregistrări (obligatorie ori de câte ori înregistrarea are una). Dacă înregistrarea s-a schimbat între timp (un coleg a editat-o), API-ul răspunde cu 409 și trebuie să o recitiți înainte de a reîncerca. O înregistrare veche al cărei updated_at este null acceptă null.
nameobligatoriuNoul nume de fișier, cel mult 255 de caractere INCLUSIV extensia. Extensia curentă este păstrată dacă nu furnizați una și contează la cele 255 (astfel, un nume fără extensie pentru "Beadvany.pdf" poate avea cel mult 251 de caractere). Text simplu; "<" și ">" nu sunt permise, deci un document al cărui nume stocat conține unul dintre ele poate fi redenumit doar în Flowyer.
^[^<>]*$"Contract_signed.pdf"Răspunsuri
200
Actualizat.
dataobligatoriuCâmpurile data
idnameNumele fișierului așa cum este afișat în Flowyer: numele stocat împreună cu documentul sau numele de stocare al acestuia atunci când a fost importat dintr-un sistem mai vechi fără nume. documents.list este ordonat după numele stocat: documentele care au unul apar primele, în ordine alfabetică, apoi cele importate fără nume stocat, cele mai vechi primele (ordinea în care au fost arhivate în Flowyer), care, prin urmare, nu sunt sortate după numele afișat aici. Ordinea este aceeași pe fiecare pagină, astfel încât limit și offset parcurg lista fără repetări sau lacune.
"Contract_v2.docx"sizeOcteți.
versionNumărul versiunii curente a fișierului.
folderFolderul în care este arhivat documentul sau null la rădăcina dosarului. documents.upload.complete răspunde cu null atunci când folderul ales la documents.upload.init a fost șters în timp ce octeții se încărcau: documentul este atunci arhivat la rădăcina dosarului, unde îl afișează Flowyer. Dacă rădăcina conține deja un document cu acel nume, încărcarea este arhivată sub un nume cu sufix ("Contract_2.pdf") în loc să devină o versiune nouă a acelui document fără legătură; răspunsul 201 reia name stocat.
Câmpurile folder
idnamepathCalea folderului în interiorul dosarului, separată prin "/".
folder_deletedTrue atunci când documentul este arhivat într-un folder care nu mai există, lucru pe care lista de fișiere proprie a Flowyer nu îl afișează (folder este null pentru el, la fel ca pentru un document aflat la rădăcina dosarului). documents.upload.complete răspunde cu true doar dacă folderul a fost șters în timp ce octeții se încărcau ȘI mutarea fișierului stocat la rădăcina dosarului a eșuat: documentul este atunci păstrat în folderul șters, unde conținutul lui este încă accesibil. False pentru orice altceva, inclusiv o arhivare normală la rădăcină.
created_by_user_idcreated_bycreated_atupdated_atupdatedtrue
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
409
Înregistrarea s-a modificat de când ați citit-o (record_conflict: expected_updated_at nu mai corespunde; citiți-o din nou și reîncercați cu noul updated_at), sau un alt document din aceeași mapă are deja acest nume (duplicate_name; alegeți alt nume, nu reîncercați cu același).
record_conflict: expected_updated_at nu mai corespunde; citiți-o din nou și reîncercați cu noul updated_at), sau un alt document din aceeași mapă are deja acest nume (duplicate_name; alegeți alt nume, nu reîncercați cu același).
413
Corpul cererii este prea mare (request_too_large).
request_too_large).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl -X PATCH 'https://www.flowyer.ro/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.ro/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.ro/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"
}
Exemple de răspuns
{
"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": "Înregistrarea s-a modificat de când ați citit-o (cineva a editat-o). Citiți-o din nou și reîncercați cu noua valoare updated_at.",
"locale": "ro",
"details": {
"current_updated_at": "2026-10-30T10:42:05+01:00",
"reason": "modified_since_read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Redenumire folder de dosar
/api/agent/folders/{id}
Redenumește un folder (doar numele lui; fișierele și subfolderele lui își păstrează locul). Numele este text simplu ("<" și ">" nu sunt permise). Transmiteți expected_updated_at din ultima citire (documents.folders îl listează); o modificare conflictuală răspunde cu 409.
Parametri de cale
idobligatoriuId-ul înregistrării de modificat.
Corpul cererii application/json
expected_updated_atValoarea updated_at din cea mai recentă citire a acestei înregistrări (obligatorie ori de câte ori înregistrarea are una). Dacă înregistrarea s-a schimbat între timp (un coleg a editat-o), API-ul răspunde cu 409 și trebuie să o recitiți înainte de a reîncerca. O înregistrare veche al cărei updated_at este null acceptă null.
nameobligatoriuNoul nume al folderului, cel mult 255 de caractere. Text simplu; "<" și ">" nu sunt permise.
^[^<>]*$"Beadványok"Răspunsuri
200
Actualizat.
dataobligatoriuCâmpurile data
idId-ul folderului: transmiteți-l ca folder_id către documents.upload.init, sau ca parent_id către documents.folders.create.
nameNumele folderului așa cum este afișat în Flowyer.
parent_idId-ul folderului părinte; null pentru un folder aflat la rădăcina dosarului.
pathCalea folderului în interiorul dosarului, separată prin "/", de exemplu "/Iratok/Beadványok".
updated_atTransmiteți aceasta către documents.folders.rename ca expected_updated_at.
updatedtrue
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
409
Înregistrarea s-a schimbat de când ați citit-o (record_conflict: expected_updated_at nu mai corespunde; citiți-o din nou și reîncercați cu noul updated_at).
record_conflict: expected_updated_at nu mai corespunde; citiți-o din nou și reîncercați cu noul updated_at).
413
Corpul cererii este prea mare (request_too_large).
request_too_large).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl -X PATCH 'https://www.flowyer.ro/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.ro/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.ro/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"
}
Exemple de răspuns
{
"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": "Înregistrarea s-a modificat de când ați citit-o (cineva a editat-o). Citiți-o din nou și reîncercați cu noua valoare updated_at.",
"locale": "ro",
"details": {
"current_updated_at": "2026-10-30T10:42:05+01:00",
"reason": "modified_since_read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Bază de cunoștințe
Listare articole din baza de cunoștințe
/api/agent/knowledge/articles
Listează articolele din baza de cunoștințe pe care utilizatorul le poate vedea (cele proprii ale autorului, articolele globale și articolele partajate cu rolul utilizatorului). Toate statusurile în mod implicit; filtrați după status sau transmiteți q pentru a căuta full-text în titluri, rezumate, conținut și etichete.
Parametri de interogare
qTermen de căutare full-text (titluri, rezumate, conținut și nume de etichete). Operatorii booleeni sunt eliminați.
"felmondási idő"statusDoar articolele cu acest status. Omiteți pentru a lista fiecare status.
"draft" "published" "archived" limitDimensiunea paginii, 1-100. Valoarea implicită este 25.
2525offsetNumărul de înregistrări de omis. Folosiți offset + limit ale paginii anterioare pentru a o obține pe următoarea; pagination.total este numărul total.
00Răspunsuri
200
OK.
dataobligatoriuCâmpurile data
id9876slugSlug de URL generat de server.
"felmondasi-ido"title"Felmondási idő a munka törvénykönyvében"excerptRezumat scurt (HTML îmbogățit, așa cum este stocat). Pentru corpul complet folosiți knowledge.articles.get.
status"draft" "published" "archived" is_featuredDacă articolul este fixat pe pagina principală a bazei de cunoștințe (nu poate fi setat prin API).
category_idcategory_nameauthor_idId-ul de utilizator al autorului; 0 pentru un articol global (implicit).
author_nameeditor_idId-ul de utilizator al ultimului editor, sau null dacă nu a fost editat niciodată.
editor_nameviews_countdownloads_countshared_rolesId-urile de rol cu care este partajat articolul (gol = doar autorul/global).
tagsNumele etichetelor de pe articol.
published_atCând a fost publicat prima dată articolul, sau null.
created_atupdated_atpaginationobligatoriuCâmpurile pagination
limitobligatoriuoffsetobligatoriutotalobligatoriuNumărul total de înregistrări care se potrivesc.
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Scope lipsă (scope_missing), API dezactivat pentru birou, licență expirată sau birou arhivat.
scope_missing), API dezactivat pentru birou, licență expirată sau birou arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl 'https://www.flowyer.ro/api/agent/knowledge/articles?q=felmond%C3%A1si%20id%C5%91&limit=25' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.ro/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.ro/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())
Exemple de răspuns
{
"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": "Această cheie API nu are permisiunea \"knowledge:read\". Permisiunile unei chei existente nu pot fi modificate, așa că titularul cheii trebuie să creeze în Flowyer, la Setări > Chei API, o cheie nouă cu această permisiune și să o folosească în locul celei vechi.",
"locale": "ro",
"details": {
"required_scope": "knowledge:read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Obținere articol din baza de cunoștințe
/api/agent/knowledge/articles/{id}
Returnează un articol din baza de cunoștințe, inclusiv conținutul complet, etichetele și rolurile partajate. Răspunde cu 404 când articolul nu există sau utilizatorul nu îl poate vedea.
Parametri de cale
idobligatoriuId-ul articolului.
9876Răspunsuri
200
OK.
dataobligatoriuCâmpurile data
id9876slugSlug de URL generat de server.
"felmondasi-ido"title"Felmondási idő a munka törvénykönyvében"excerptRezumat scurt (HTML îmbogățit, așa cum este stocat). Pentru corpul complet folosiți knowledge.articles.get.
status"draft" "published" "archived" is_featuredDacă articolul este fixat pe pagina principală a bazei de cunoștințe (nu poate fi setat prin API).
category_idcategory_nameauthor_idId-ul de utilizator al autorului; 0 pentru un articol global (implicit).
author_nameeditor_idId-ul de utilizator al ultimului editor, sau null dacă nu a fost editat niciodată.
editor_nameviews_countdownloads_countshared_rolesId-urile de rol cu care este partajat articolul (gol = doar autorul/global).
tagsNumele etichetelor de pe articol.
published_atCând a fost publicat prima dată articolul, sau null.
created_atupdated_atcontentCorpul complet al articolului așa cum este stocat (HTML îmbogățit).
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Scope lipsă (scope_missing), API dezactivat pentru birou, licență expirată sau birou arhivat.
scope_missing), API dezactivat pentru birou, licență expirată sau birou arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl 'https://www.flowyer.ro/api/agent/knowledge/articles/9876' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.ro/api/agent/knowledge/articles/9876", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.ro/api/agent/knowledge/articles/9876",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Exemple de răspuns
{
"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": "Înregistrarea nu a fost găsită sau nu este vizibilă pentru titularul acestei chei API.",
"locale": "ro",
"details": {
"article_id": 9876
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Creare articol în baza de cunoștințe
/api/agent/knowledge/articles
Creează un articol în baza de cunoștințe, având ca autor utilizatorul cheii. Slug-ul este generat din titlu. Categoria trebuie să existe și să fie activă. Partajați-l cu roluri prin shared_roles (altfel îl vede doar autorul). content și excerpt sunt HTML și sunt igienizate pe partea de server.
Parametri de antet
Idempotency-KeyRecomandat la fiecare creare. O valoare unică per operație logică (de exemplu un UUID). Aceeași valoare returnează aceeași înregistrare: reîncercarea cu ea returnează înregistrarea creată prima dată, în loc să creeze o a doua. Valori diferite creează întotdeauna înregistrări diferite. Clienții care nu pot trimite anteturi pot transmite aceeași valoare în câmpul de corp idempotency_key. Litere, cifre, _, -, : sau ., cel mult 128 de caractere.
^[A-Za-z0-9_\-:.]{1,128}$Corpul cererii application/json
titleobligatoriuTitlul articolului. Text simplu.
"Felmondási idő a munka törvénykönyvében"excerptRezumat scurt (HTML permis, igienizat pe partea de server), cel mult 200 de caractere.
contentobligatoriuCorpul articolului. HTML îmbogățit, igienizat pe partea de server cu profilul bazei de cunoștințe.
category_idobligatoriuId-ul unei categorii existente și active din baza de cunoștințe.
12statusobligatoriudraft, published sau archived. published marchează published_at.
"draft" "published" "archived" tagsNume de etichete; etichetele noi sunt create după necesitate.
shared_rolesId-urile de rol cu care se partajează articolul. Gol înseamnă că doar autorul îl poate vedea.
idempotency_keyAcelași rol ca antetul Idempotency-Key, pentru clienții care nu pot trimite anteturi personalizate. Litere, cifre, _, -, : sau ., cel mult 128 de caractere.
^[A-Za-z0-9_\-:.]{1,128}$"b8f1c2e0-6f7a-4d2e-9c1b-2a3d4e5f6a7b"Răspunsuri
201
Creat.
dataobligatoriuCâmpurile data
id9876slugSlug de URL generat de server.
"felmondasi-ido"title"Felmondási idő a munka törvénykönyvében"excerptRezumat scurt (HTML îmbogățit, așa cum este stocat). Pentru corpul complet folosiți knowledge.articles.get.
status"draft" "published" "archived" is_featuredDacă articolul este fixat pe pagina principală a bazei de cunoștințe (nu poate fi setat prin API).
category_idcategory_nameauthor_idId-ul de utilizator al autorului; 0 pentru un articol global (implicit).
author_nameeditor_idId-ul de utilizator al ultimului editor, sau null dacă nu a fost editat niciodată.
editor_nameviews_countdownloads_countshared_rolesId-urile de rol cu care este partajat articolul (gol = doar autorul/global).
tagsNumele etichetelor de pe articol.
published_atCând a fost publicat prima dată articolul, sau null.
created_atupdated_atcontentCorpul complet al articolului așa cum este stocat (HTML îmbogățit).
createdtrue
200
Reluare idempotentă: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică în interval de 120 de secunde) a creat deja înregistrarea; aceasta este returnată din nou, nu s-a creat nimic nou.
dataobligatoriuCâmpurile data
id9876slugSlug de URL generat de server.
"felmondasi-ido"title"Felmondási idő a munka törvénykönyvében"excerptRezumat scurt (HTML îmbogățit, așa cum este stocat). Pentru corpul complet folosiți knowledge.articles.get.
status"draft" "published" "archived" is_featuredDacă articolul este fixat pe pagina principală a bazei de cunoștințe (nu poate fi setat prin API).
category_idcategory_nameauthor_idId-ul de utilizator al autorului; 0 pentru un articol global (implicit).
author_nameeditor_idId-ul de utilizator al ultimului editor, sau null dacă nu a fost editat niciodată.
editor_nameviews_countdownloads_countshared_rolesId-urile de rol cu care este partajat articolul (gol = doar autorul/global).
tagsNumele etichetelor de pe articol.
published_atCând a fost publicat prima dată articolul, sau null.
created_atupdated_atcontentCorpul complet al articolului așa cum este stocat (HTML îmbogățit).
createdfalseidempotent_replaytrue
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Scope lipsă (scope_missing), API dezactivat pentru birou, licență expirată sau birou arhivat.
scope_missing), API dezactivat pentru birou, licență expirată sau birou arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator. replay_not_visible: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică) a creat deja înregistrarea (details.record_id), dar aceasta a fost între timp ștearsă sau nu este vizibilă pentru utilizator; nu s-a creat nimic nou, nu o creați din nou.
replay_not_visible: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică) a creat deja înregistrarea (details.record_id), dar aceasta a fost între timp ștearsă sau nu este vizibilă pentru utilizator; nu s-a creat nimic nou, nu o creați din nou.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
409
Idempotency-Key a fost folosit pentru alt tip de resursă (idempotency_key_reused) sau, în lipsa unei chei, o cerere identică este procesată chiar acum (duplicate_in_progress; reîncercați în scurt timp).
idempotency_key_reused) sau, în lipsa unei chei, o cerere identică este procesată chiar acum (duplicate_in_progress; reîncercați în scurt timp).
413
Corpul cererii este prea mare (request_too_large).
request_too_large).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl -X POST 'https://www.flowyer.ro/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.ro/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.ro/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"
}
Exemple de răspuns
{
"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": "Cererea nu este validă. Erorile pe câmpuri se găsesc în \"details.fields\".",
"locale": "ro",
"details": {
"fields": {
"title": [
"Câmpul title este obligatoriu."
]
}
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Actualizare articol din baza de cunoștințe
/api/agent/knowledge/articles/{id}
Modifică un articol din baza de cunoștințe: titlul (slug-ul este re-derivat), rezumatul, conținutul, categoria, statusul, etichetele sau rolurile partajate. Doar autorul (sau oricine, pentru un articol global) poate edita. Transmiteți expected_updated_at; o modificare conflictuală răspunde cu 409. content și excerpt sunt igienizate pe partea de server.
Parametri de cale
idobligatoriuId-ul înregistrării de modificat.
Corpul cererii application/json
expected_updated_atValoarea updated_at din cea mai recentă citire a acestei înregistrări (obligatorie ori de câte ori înregistrarea are una). Dacă înregistrarea s-a schimbat între timp (un coleg a editat-o), API-ul răspunde cu 409 și trebuie să o recitiți înainte de a reîncerca. O înregistrare veche al cărei updated_at este null acceptă null.
titleTitlul articolului (text simplu). null păstrează titlul curent; un titlu nou re-derivă slug-ul.
excerptRezumat scurt (HTML permis, igienizat), cel mult 200 de caractere ca valoare NOUĂ. Gol/null îl șterge; omiteți pentru a-l păstra.
contentCorpul articolului (HTML îmbogățit, igienizat). null păstrează conținutul curent; nu poate fi șters.
category_idMută articolul în această categorie existentă și activă. null o păstrează pe cea curentă.
statusdraft, published sau archived. Prima trecere la published marchează published_at; acesta nu este șters niciodată. null păstrează statusul curent.
"draft" "published" "archived" tagsÎnlocuiește întregul set de etichete (etichetele noi sunt create). Un array gol șterge toate etichetele; omiteți pentru a le păstra.
shared_rolesÎnlocuiește întregul set de roluri partajate. Un array gol elimină toată partajarea (doar autorul îl vede); omiteți pentru a-l păstra.
Răspunsuri
200
Actualizat.
dataobligatoriuCâmpurile data
id9876slugSlug de URL generat de server.
"felmondasi-ido"title"Felmondási idő a munka törvénykönyvében"excerptRezumat scurt (HTML îmbogățit, așa cum este stocat). Pentru corpul complet folosiți knowledge.articles.get.
status"draft" "published" "archived" is_featuredDacă articolul este fixat pe pagina principală a bazei de cunoștințe (nu poate fi setat prin API).
category_idcategory_nameauthor_idId-ul de utilizator al autorului; 0 pentru un articol global (implicit).
author_nameeditor_idId-ul de utilizator al ultimului editor, sau null dacă nu a fost editat niciodată.
editor_nameviews_countdownloads_countshared_rolesId-urile de rol cu care este partajat articolul (gol = doar autorul/global).
tagsNumele etichetelor de pe articol.
published_atCând a fost publicat prima dată articolul, sau null.
created_atupdated_atcontentCorpul complet al articolului așa cum este stocat (HTML îmbogățit).
updatedtrue
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Scope lipsă (scope_missing), API dezactivat pentru birou, licență expirată sau birou arhivat.
scope_missing), API dezactivat pentru birou, licență expirată sau birou arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
409
Înregistrarea s-a schimbat de când ați citit-o (record_conflict: expected_updated_at nu mai corespunde; citiți-o din nou și reîncercați cu noul updated_at).
record_conflict: expected_updated_at nu mai corespunde; citiți-o din nou și reîncercați cu noul updated_at).
413
Corpul cererii este prea mare (request_too_large).
request_too_large).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl -X PATCH 'https://www.flowyer.ro/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.ro/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.ro/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"
}
Exemple de răspuns
{
"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": "Înregistrarea s-a modificat de când ați citit-o (cineva a editat-o). Citiți-o din nou și reîncercați cu noua valoare updated_at.",
"locale": "ro",
"details": {
"current_updated_at": "2026-10-30T10:42:05+01:00",
"reason": "modified_since_read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Listare categorii din baza de cunoștințe
/api/agent/knowledge/categories
Listează categoriile din baza de cunoștințe pe care utilizatorul le poate vedea: categoriile implicite încorporate, cele proprii ale utilizatorului și cele partajate cu rolul utilizatorului. Ordonate ca în Flowyer (poziția de sortare, apoi numele).
Parametri de interogare
limitDimensiunea paginii, 1-100. Valoarea implicită este 25.
2525offsetNumărul de înregistrări de omis. Folosiți offset + limit ale paginii anterioare pentru a o obține pe următoarea; pagination.total este numărul total.
00Răspunsuri
200
OK.
dataobligatoriuCâmpurile data
id42slugSlug de URL, generat din nume.
"munkajog"name"Munkajog"descriptionDescriere în text simplu, sau null.
iconIdentificatorul pictogramei afișate lângă categorie, sau null.
order_columnPoziția de sortare între categoriile de același nivel.
0is_activeparent_idId-ul categoriei părinte, sau null pentru o categorie rădăcină.
author_idId-ul de utilizator al creatorului; 0 pentru o categorie implicită încorporată, vizibilă tuturor.
author_nameNumele afișat al creatorului, sau null pentru o categorie implicită.
articles_countNumărul de articole publicate din această categorie pe care apelantul le poate vedea.
shared_rolesId-urile de rol cu care este partajată această categorie. Gol înseamnă că doar autorul o vede (o categorie implicită cu author_id 0 este vizibilă tuturor).
created_atupdated_atpaginationobligatoriuCâmpurile pagination
limitobligatoriuoffsetobligatoriutotalobligatoriuNumărul total de înregistrări care se potrivesc.
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Scope lipsă (scope_missing), API dezactivat pentru birou, licență expirată sau birou arhivat.
scope_missing), API dezactivat pentru birou, licență expirată sau birou arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl 'https://www.flowyer.ro/api/agent/knowledge/categories?limit=25' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.ro/api/agent/knowledge/categories?limit=25", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.ro/api/agent/knowledge/categories?limit=25",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Exemple de răspuns
{
"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": "Această cheie API nu are permisiunea \"knowledge:read\". Permisiunile unei chei existente nu pot fi modificate, așa că titularul cheii trebuie să creeze în Flowyer, la Setări > Chei API, o cheie nouă cu această permisiune și să o folosească în locul celei vechi.",
"locale": "ro",
"details": {
"required_scope": "knowledge:read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Obținere categorie din baza de cunoștințe
/api/agent/knowledge/categories/{id}
Returnează o categorie din baza de cunoștințe. Răspunde cu 404 când categoria nu există sau nu este vizibilă pentru utilizatorul care deține această cheie API.
Parametri de cale
idobligatoriuId-ul categoriei.
42Răspunsuri
200
OK.
dataobligatoriuCâmpurile data
id42slugSlug de URL, generat din nume.
"munkajog"name"Munkajog"descriptionDescriere în text simplu, sau null.
iconIdentificatorul pictogramei afișate lângă categorie, sau null.
order_columnPoziția de sortare între categoriile de același nivel.
0is_activeparent_idId-ul categoriei părinte, sau null pentru o categorie rădăcină.
author_idId-ul de utilizator al creatorului; 0 pentru o categorie implicită încorporată, vizibilă tuturor.
author_nameNumele afișat al creatorului, sau null pentru o categorie implicită.
articles_countNumărul de articole publicate din această categorie pe care apelantul le poate vedea.
shared_rolesId-urile de rol cu care este partajată această categorie. Gol înseamnă că doar autorul o vede (o categorie implicită cu author_id 0 este vizibilă tuturor).
created_atupdated_at
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Scope lipsă (scope_missing), API dezactivat pentru birou, licență expirată sau birou arhivat.
scope_missing), API dezactivat pentru birou, licență expirată sau birou arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl 'https://www.flowyer.ro/api/agent/knowledge/categories/42' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.ro/api/agent/knowledge/categories/42", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.ro/api/agent/knowledge/categories/42",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Exemple de răspuns
{
"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": "Înregistrarea nu a fost găsită sau nu este vizibilă pentru titularul acestei chei API.",
"locale": "ro",
"details": {
"category_id": 42
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Creare categorie în baza de cunoștințe
/api/agent/knowledge/categories
Creează o categorie în baza de cunoștințe. Slug-ul de URL este generat din nume. Partajați-o cu roluri prin shared_roles sau omiteți-le astfel încât doar dumneavoastră (autorul) să o puteți vedea. Un parent_id, când este furnizat, trebuie să fie o categorie existentă și activă.
Parametri de antet
Idempotency-KeyRecomandat la fiecare creare. O valoare unică per operație logică (de exemplu un UUID). Aceeași valoare returnează aceeași înregistrare: reîncercarea cu ea returnează înregistrarea creată prima dată, în loc să creeze o a doua. Valori diferite creează întotdeauna înregistrări diferite. Clienții care nu pot trimite anteturi pot transmite aceeași valoare în câmpul de corp idempotency_key. Litere, cifre, _, -, : sau ., cel mult 128 de caractere.
^[A-Za-z0-9_\-:.]{1,128}$Corpul cererii application/json
nameobligatoriuNumele categoriei. Text simplu; "<" și ">" nu sunt permise.
^[^<>]*$"Munkajog"descriptionDescriere opțională, text simplu.
parent_idId-ul categoriei părinte (trebuie să existe și să fie activă). Omiteți pentru o categorie rădăcină.
iconIdentificator de pictogramă opțional. Text simplu; "<" și ">" nu sunt permise.
^[^<>]*$is_activeDacă categoria este activă. Implicit true.
trueorder_columnPoziția de sortare între categoriile de același nivel. Implicit 0.
0shared_rolesId-urile de rol cu care se partajează această categorie. Omiteți astfel încât doar dumneavoastră (autorul) să o puteți vedea.
idempotency_keyAcelași rol ca antetul Idempotency-Key, pentru clienții care nu pot trimite anteturi personalizate. Litere, cifre, _, -, : sau ., cel mult 128 de caractere.
^[A-Za-z0-9_\-:.]{1,128}$"b8f1c2e0-6f7a-4d2e-9c1b-2a3d4e5f6a7b"Răspunsuri
201
Creat.
dataobligatoriuCâmpurile data
id42slugSlug de URL, generat din nume.
"munkajog"name"Munkajog"descriptionDescriere în text simplu, sau null.
iconIdentificatorul pictogramei afișate lângă categorie, sau null.
order_columnPoziția de sortare între categoriile de același nivel.
0is_activeparent_idId-ul categoriei părinte, sau null pentru o categorie rădăcină.
author_idId-ul de utilizator al creatorului; 0 pentru o categorie implicită încorporată, vizibilă tuturor.
author_nameNumele afișat al creatorului, sau null pentru o categorie implicită.
articles_countNumărul de articole publicate din această categorie pe care apelantul le poate vedea.
shared_rolesId-urile de rol cu care este partajată această categorie. Gol înseamnă că doar autorul o vede (o categorie implicită cu author_id 0 este vizibilă tuturor).
created_atupdated_atcreatedtrue
200
Reluare idempotentă: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică în interval de 120 de secunde) a creat deja înregistrarea; aceasta este returnată din nou, nu s-a creat nimic nou.
dataobligatoriuCâmpurile data
id42slugSlug de URL, generat din nume.
"munkajog"name"Munkajog"descriptionDescriere în text simplu, sau null.
iconIdentificatorul pictogramei afișate lângă categorie, sau null.
order_columnPoziția de sortare între categoriile de același nivel.
0is_activeparent_idId-ul categoriei părinte, sau null pentru o categorie rădăcină.
author_idId-ul de utilizator al creatorului; 0 pentru o categorie implicită încorporată, vizibilă tuturor.
author_nameNumele afișat al creatorului, sau null pentru o categorie implicită.
articles_countNumărul de articole publicate din această categorie pe care apelantul le poate vedea.
shared_rolesId-urile de rol cu care este partajată această categorie. Gol înseamnă că doar autorul o vede (o categorie implicită cu author_id 0 este vizibilă tuturor).
created_atupdated_atcreatedfalseidempotent_replaytrue
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Scope lipsă (scope_missing), API dezactivat pentru birou, licență expirată sau birou arhivat.
scope_missing), API dezactivat pentru birou, licență expirată sau birou arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator. replay_not_visible: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică) a creat deja înregistrarea (details.record_id), dar aceasta a fost între timp ștearsă sau nu este vizibilă pentru utilizator; nu s-a creat nimic nou, nu o creați din nou.
replay_not_visible: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică) a creat deja înregistrarea (details.record_id), dar aceasta a fost între timp ștearsă sau nu este vizibilă pentru utilizator; nu s-a creat nimic nou, nu o creați din nou.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
409
Idempotency-Key a fost folosit pentru alt tip de resursă (idempotency_key_reused) sau, în lipsa unei chei, o cerere identică este procesată chiar acum (duplicate_in_progress; reîncercați în scurt timp).
idempotency_key_reused) sau, în lipsa unei chei, o cerere identică este procesată chiar acum (duplicate_in_progress; reîncercați în scurt timp).
413
Corpul cererii este prea mare (request_too_large).
request_too_large).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl -X POST 'https://www.flowyer.ro/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.ro/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.ro/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
}
Exemple de răspuns
{
"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": "Cererea nu este validă. Erorile pe câmpuri se găsesc în \"details.fields\".",
"locale": "ro",
"details": {
"fields": {
"name": [
"Câmpul name este obligatoriu."
]
}
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Actualizare categorie din baza de cunoștințe
/api/agent/knowledge/categories/{id}
Modifică o categorie din baza de cunoștințe: numele (slug-ul îl urmează), descrierea, pictograma, părintele, indicatorul activ, poziția de sortare sau rolurile cu care este partajată. Doar autorul o poate modifica (o categorie implicită încorporată poate fi editată de oricine). Transmiteți expected_updated_at; o modificare conflictuală răspunde cu 409.
Parametri de cale
idobligatoriuId-ul înregistrării de modificat.
Corpul cererii application/json
expected_updated_atValoarea updated_at din cea mai recentă citire a acestei înregistrări (obligatorie ori de câte ori înregistrarea are una). Dacă înregistrarea s-a schimbat între timp (un coleg a editat-o), API-ul răspunde cu 409 și trebuie să o recitiți înainte de a reîncerca. O înregistrare veche al cărei updated_at este null acceptă null.
nameNumele categoriei. Cel mult 255 de caractere ca valoare NOUĂ; "<" și ">" nu pot fi introduse, dar un nume stocat care este mai lung sau le conține poate fi trimis înapoi nemodificat. null păstrează numele curent.
descriptionDescriere în text simplu. null o șterge.
parent_idMută categoria sub acest părinte (trebuie să existe, să fie activ și să nu creeze un ciclu), sau null pentru a o face o categorie rădăcină.
iconIdentificator de pictogramă. Cel mult 100 de caractere ca valoare NOUĂ; "<" și ">" nu pot fi introduse. null îl șterge.
is_activeIndicator activ. Omiteți sau null pentru a păstra valoarea curentă.
order_columnPoziția de sortare între categoriile de același nivel. Omiteți sau null pentru a păstra valoarea curentă.
shared_rolesÎnlocuiește setul de id-uri de rol cu care este partajată această categorie. Un array gol elimină toată partajarea (doar autorul o vede). Omiteți pentru a lăsa partajarea neschimbată.
Răspunsuri
200
Actualizat.
dataobligatoriuCâmpurile data
id42slugSlug de URL, generat din nume.
"munkajog"name"Munkajog"descriptionDescriere în text simplu, sau null.
iconIdentificatorul pictogramei afișate lângă categorie, sau null.
order_columnPoziția de sortare între categoriile de același nivel.
0is_activeparent_idId-ul categoriei părinte, sau null pentru o categorie rădăcină.
author_idId-ul de utilizator al creatorului; 0 pentru o categorie implicită încorporată, vizibilă tuturor.
author_nameNumele afișat al creatorului, sau null pentru o categorie implicită.
articles_countNumărul de articole publicate din această categorie pe care apelantul le poate vedea.
shared_rolesId-urile de rol cu care este partajată această categorie. Gol înseamnă că doar autorul o vede (o categorie implicită cu author_id 0 este vizibilă tuturor).
created_atupdated_atupdatedtrue
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Scope lipsă (scope_missing), API dezactivat pentru birou, licență expirată sau birou arhivat.
scope_missing), API dezactivat pentru birou, licență expirată sau birou arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
409
Înregistrarea s-a schimbat de când ați citit-o (record_conflict: expected_updated_at nu mai corespunde; citiți-o din nou și reîncercați cu noul updated_at).
record_conflict: expected_updated_at nu mai corespunde; citiți-o din nou și reîncercați cu noul updated_at).
413
Corpul cererii este prea mare (request_too_large).
request_too_large).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl -X PATCH 'https://www.flowyer.ro/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.ro/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.ro/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"
}
Exemple de răspuns
{
"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": "Înregistrarea s-a modificat de când ați citit-o (cineva a editat-o). Citiți-o din nou și reîncercați cu noua valoare updated_at.",
"locale": "ro",
"details": {
"current_updated_at": "2026-10-30T10:42:05+01:00",
"reason": "modified_since_read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
E-mailuri
Listare e-mailuri de dosar
/api/agent/matters/{id}/emails
Listează e-mailurile salvate pe un dosar: numele și adresa expeditorului, subiectul, dimensiunea și colegul care a salvat fiecare, cele mai nou trimise primele. Doar antet și metadate, niciodată corpul sau HTML-ul brut. Folosiți emails.get pentru corpul în text simplu al unui singur mesaj.
Parametri de cale
idobligatoriuId-ul dosarului.
1234Parametri de interogare
qFiltrați după subiect, numele expeditorului sau adresa expeditorului (fără sensibilitate la diacritice și majuscule/minuscule). Nu după corp.
"invoice"limitDimensiunea paginii, 1-100. Valoarea implicită este 25.
2525offsetNumărul de înregistrări de omis. Folosiți offset + limit ale paginii anterioare pentru a o obține pe următoarea; pagination.total este numărul total.
00Răspunsuri
200
OK.
dataobligatoriuCâmpurile data
idId-ul e-mailului (folosiți cu emails.get).
1234from_nameNumele afișat al părții externe. Stocarea nu păstrează coloane de direcție sau de destinatar, așa că aceasta este întotdeauna partea externă, niciodată un coleg, iar API-ul nu poate spune dacă e-mailul a fost primit sau trimis.
from_addressAdresa SMTP a părții externe.
subjectsent_atCând a fost trimis mesajul. Fusul orar al valorii stocate este inconsecvent în funcție de calea de preluare (workerul IMAP stochează UTC, add-inul Outlook stochează o oră de perete în fusul biroului), așa că este pe cât posibil și ordinea listei după el poate fi decalată cu offsetul UTC al biroului între surse. created_at este marcajul temporal fiabil.
sizeOcteții fișierului .eml/.msg stocat.
extension"msg" (add-in Outlook) sau "eml" (IMAP / implicit); null pe unele rânduri mai vechi.
saved_by_user_idId-ul de utilizator al colegului care a salvat e-mailul în Flowyer.
saved_byNumele afișat al acelui coleg.
created_atCând a fost salvat e-mailul în Flowyer (oră de perete în fusul biroului). Marcajul temporal fiabil pentru o paginare stabilă.
paginationobligatoriuCâmpurile pagination
limitobligatoriuoffsetobligatoriutotalobligatoriuNumărul total de înregistrări care se potrivesc.
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl 'https://www.flowyer.ro/api/agent/matters/1234/emails?q=invoice&limit=25' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.ro/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.ro/api/agent/matters/1234/emails?q=invoice&limit=25",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Exemple de răspuns
{
"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": "Dosarul 1234 nu există, este arhivat sau nu este vizibil pentru titularul acestei chei API.",
"locale": "ro",
"details": {
"matter_id": 1234
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Obținere e-mail
/api/agent/emails/{id}
Returnează un e-mail salvat al unui dosar cu corpul său în text simplu (expeditor, subiect, dimensiune și cine l-a salvat). Corpul HTML brut nu este returnat niciodată. Răspunde cu 404 când e-mailul nu există sau dosarul său nu este vizibil pentru utilizatorul care deține această cheie API.
Parametri de cale
idobligatoriuId-ul e-mailului.
1234Răspunsuri
200
OK.
dataobligatoriuCâmpurile data
id1234matterDosarul sub care este arhivat e-mailul, sau null pentru un e-mail fără dosar (salvat în afara oricărui caz).
Câmpurile matter
idcase_numberfrom_nameNumele afișat al părții externe (niciodată un coleg; stocarea nu are o coloană de direcție).
from_addressAdresa SMTP a părții externe.
subjectbodyCorpul mesajului în text simplu. Corpul HTML brut nu este returnat niciodată în mod deliberat (HTML terț, de încredere scăzută). Text simplu, pe cât posibil: dacă HTML-ul original conținea <style>/<script>, textul lor interior poate supraviețui în el.
sent_atCând a fost trimis mesajul. Fusul orar este inconsecvent în funcție de calea de preluare (IMAP stochează UTC, add-inul Outlook o oră de perete în fusul biroului); created_at este marcajul temporal fiabil.
sizeOcteții fișierului .eml/.msg stocat.
extension"msg" sau "eml"; null pe unele rânduri mai vechi.
saved_by_user_idId-ul de utilizator al colegului care a salvat e-mailul în Flowyer.
saved_byNumele afișat al acelui coleg.
created_atCând a fost salvat e-mailul în Flowyer (oră de perete în fusul biroului).
updated_at
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl 'https://www.flowyer.ro/api/agent/emails/1234' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.ro/api/agent/emails/1234", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.ro/api/agent/emails/1234",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Exemple de răspuns
{
"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": "E-mailul :id nu există sau aparține unui dosar care nu este vizibil pentru utilizatorul acestei chei API.",
"locale": "ro",
"details": {
"email_id": 1234
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Istoric litigiu
Listare istoric litigiu al dosarului
/api/agent/matters/{id}/litigation
Listează intrările din istoricul litigiului (pertörténet) ale unui dosar, cel mai nou eveniment primul: o notă datată cu un titlu, o descriere HTML și o locație. Răspunde cu 404 când dosarul nu este vizibil pentru utilizator.
Parametri de cale
idobligatoriuId-ul dosarului.
1234Parametri de interogare
limitDimensiunea paginii, 1-100. Valoarea implicită este 25.
2525offsetNumărul de înregistrări de omis. Folosiți offset + limit ale paginii anterioare pentru a o obține pe următoarea; pagination.total este numărul total.
00Răspunsuri
200
OK.
dataobligatoriuCâmpurile data
id4521titleTitlul intrării. Text simplu.
"Első tárgyalás elhalasztva"descriptionDetaliile intrării ca HTML îmbogățit, igienizat pe partea de server.
locationUnde a avut loc (text simplu), de exemplu o sală de judecată; poate fi null.
event_dateZiua intrării, YYYY-MM-DD. Flowyer înregistrează doar data, fără ora din zi.
user_idAutorul (utilizatorul care a creat intrarea).
created_byNumele afișat al autorului.
last_editor_idUtilizatorul care a editat ultima dată intrarea.
last_editorNumele afișat al ultimului editor.
created_atupdated_atTransmiteți aceasta către litigation.update ca expected_updated_at.
created_via_apiPrezent atunci când un agent extern a creat intrarea prin acest API.
Câmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduseratpaginationobligatoriuCâmpurile pagination
limitobligatoriuoffsetobligatoriutotalobligatoriuNumărul total de înregistrări care se potrivesc.
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl 'https://www.flowyer.ro/api/agent/matters/1234/litigation?limit=25' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.ro/api/agent/matters/1234/litigation?limit=25", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.ro/api/agent/matters/1234/litigation?limit=25",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Exemple de răspuns
{
"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": "Dosarul 1234 nu există, este arhivat sau nu este vizibil pentru titularul acestei chei API.",
"locale": "ro",
"details": {
"matter_id": 1234
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Creare intrare în istoricul litigiului
/api/agent/matters/{id}/litigation
Adaugă o intrare în istoricul litigiului (pertörténet) la un dosar: un titlu (text simplu, "<"/">" nu sunt permise), o descriere HTML opțională (igienizată pe partea de server), o locație opțională și o dată a evenimentului (implicit astăzi). Răspunde cu 404 când dosarul nu este vizibil.
Parametri de cale
idobligatoriuDosarul de care aparține intrarea (trebuie să fie vizibil).
1234Parametri de antet
Idempotency-KeyRecomandat la fiecare creare. O valoare unică per operație logică (de exemplu un UUID). Aceeași valoare returnează aceeași înregistrare: reîncercarea cu ea returnează înregistrarea creată prima dată, în loc să creeze o a doua. Valori diferite creează întotdeauna înregistrări diferite. Clienții care nu pot trimite anteturi pot transmite aceeași valoare în câmpul de corp idempotency_key. Litere, cifre, _, -, : sau ., cel mult 128 de caractere.
^[A-Za-z0-9_\-:.]{1,128}$Corpul cererii application/json
titleobligatoriuTitlul intrării, cel mult 2000 de caractere. Text simplu; "<" și ">" nu sunt permise.
^[^<>]*$"Első tárgyalás elhalasztva"descriptionDetaliile intrării. HTML îmbogățit, igienizat pe partea de server cu profilul bazei de cunoștințe.
locationUnde a avut loc (text simplu, cel mult 255 de caractere); "<" și ">" nu sunt permise.
^[^<>]*$"Fővárosi Törvényszék, 215. tárgyaló"event_dateZiua intrării, YYYY-MM-DD. Implicit astăzi (fusul orar al biroului).
"2026-11-15"idempotency_keyAcelași rol ca antetul Idempotency-Key, pentru clienții care nu pot trimite anteturi personalizate. Litere, cifre, _, -, : sau ., cel mult 128 de caractere.
^[A-Za-z0-9_\-:.]{1,128}$"b8f1c2e0-6f7a-4d2e-9c1b-2a3d4e5f6a7b"Răspunsuri
201
Creat.
dataobligatoriuCâmpurile data
id4521titleTitlul intrării. Text simplu.
"Első tárgyalás elhalasztva"descriptionDetaliile intrării ca HTML îmbogățit, igienizat pe partea de server.
locationUnde a avut loc (text simplu), de exemplu o sală de judecată; poate fi null.
event_dateZiua intrării, YYYY-MM-DD. Flowyer înregistrează doar data, fără ora din zi.
user_idAutorul (utilizatorul care a creat intrarea).
created_byNumele afișat al autorului.
last_editor_idUtilizatorul care a editat ultima dată intrarea.
last_editorNumele afișat al ultimului editor.
created_atupdated_atTransmiteți aceasta către litigation.update ca expected_updated_at.
created_via_apiPrezent atunci când un agent extern a creat intrarea prin acest API.
Câmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduseratcreatedtrue
200
Reluare idempotentă: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică în interval de 120 de secunde) a creat deja înregistrarea; aceasta este returnată din nou, nu s-a creat nimic nou.
dataobligatoriuCâmpurile data
id4521titleTitlul intrării. Text simplu.
"Első tárgyalás elhalasztva"descriptionDetaliile intrării ca HTML îmbogățit, igienizat pe partea de server.
locationUnde a avut loc (text simplu), de exemplu o sală de judecată; poate fi null.
event_dateZiua intrării, YYYY-MM-DD. Flowyer înregistrează doar data, fără ora din zi.
user_idAutorul (utilizatorul care a creat intrarea).
created_byNumele afișat al autorului.
last_editor_idUtilizatorul care a editat ultima dată intrarea.
last_editorNumele afișat al ultimului editor.
created_atupdated_atTransmiteți aceasta către litigation.update ca expected_updated_at.
created_via_apiPrezent atunci când un agent extern a creat intrarea prin acest API.
Câmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduseratcreatedfalseidempotent_replaytrue
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator. replay_not_visible: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică) a creat deja înregistrarea (details.record_id), dar aceasta a fost între timp ștearsă sau nu este vizibilă pentru utilizator; nu s-a creat nimic nou, nu o creați din nou.
replay_not_visible: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică) a creat deja înregistrarea (details.record_id), dar aceasta a fost între timp ștearsă sau nu este vizibilă pentru utilizator; nu s-a creat nimic nou, nu o creați din nou.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
409
Idempotency-Key a fost folosit pentru alt tip de resursă (idempotency_key_reused) sau, în lipsa unei chei, o cerere identică este procesată chiar acum (duplicate_in_progress; reîncercați în scurt timp).
idempotency_key_reused) sau, în lipsa unei chei, o cerere identică este procesată chiar acum (duplicate_in_progress; reîncercați în scurt timp).
413
Corpul cererii este prea mare (request_too_large).
request_too_large).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl -X POST 'https://www.flowyer.ro/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.ro/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.ro/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"
}
Exemple de răspuns
{
"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": "Cererea nu este validă. Erorile pe câmpuri se găsesc în \"details.fields\".",
"locale": "ro",
"details": {
"fields": {
"title": [
"Câmpul title este obligatoriu."
]
}
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Actualizare intrare din istoricul litigiului
/api/agent/litigation/{id}
Modifică o intrare din istoricul litigiului (pertörténet): titlul, descrierea, locația sau data evenimentului. Se scriu doar câmpurile pe care le trimiteți; descrierea este igienizată pe partea de server. Transmiteți expected_updated_at din ultima citire; o modificare conflictuală răspunde cu 409.
Parametri de cale
idobligatoriuId-ul înregistrării de modificat.
Corpul cererii application/json
expected_updated_atValoarea updated_at din cea mai recentă citire a acestei înregistrări (obligatorie ori de câte ori înregistrarea are una). Dacă înregistrarea s-a schimbat între timp (un coleg a editat-o), API-ul răspunde cu 409 și trebuie să o recitiți înainte de a reîncerca. O înregistrare veche al cărei updated_at este null acceptă null.
titleTitlu nou, cel mult 2000 de caractere (text simplu; "<"/">" nu sunt permise). Omiteți pentru a-l păstra pe cel curent.
^[^<>]*$"Ítélethirdetés elhalasztva"descriptionDetalii noi (HTML îmbogățit, igienizat). Omiteți pentru a le păstra pe cele curente; null/gol le șterge.
locationLocație nouă (text simplu, cel mult 255 de caractere; "<"/">" nu sunt permise). Omiteți pentru a o păstra; null/gol o șterge.
^[^<>]*$event_dateNoua zi a evenimentului, YYYY-MM-DD. Omiteți pentru a o păstra; null o șterge.
Răspunsuri
200
Actualizat.
dataobligatoriuCâmpurile data
id4521titleTitlul intrării. Text simplu.
"Első tárgyalás elhalasztva"descriptionDetaliile intrării ca HTML îmbogățit, igienizat pe partea de server.
locationUnde a avut loc (text simplu), de exemplu o sală de judecată; poate fi null.
event_dateZiua intrării, YYYY-MM-DD. Flowyer înregistrează doar data, fără ora din zi.
user_idAutorul (utilizatorul care a creat intrarea).
created_byNumele afișat al autorului.
last_editor_idUtilizatorul care a editat ultima dată intrarea.
last_editorNumele afișat al ultimului editor.
created_atupdated_atTransmiteți aceasta către litigation.update ca expected_updated_at.
created_via_apiPrezent atunci când un agent extern a creat intrarea prin acest API.
Câmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduseratupdatedtrue
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
409
Înregistrarea s-a schimbat de când ați citit-o (record_conflict: expected_updated_at nu mai corespunde; citiți-o din nou și reîncercați cu noul updated_at).
record_conflict: expected_updated_at nu mai corespunde; citiți-o din nou și reîncercați cu noul updated_at).
413
Corpul cererii este prea mare (request_too_large).
request_too_large).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl -X PATCH 'https://www.flowyer.ro/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.ro/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.ro/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"
}
Exemple de răspuns
{
"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": "Înregistrarea s-a modificat de când ați citit-o (cineva a editat-o). Citiți-o din nou și reîncercați cu noua valoare updated_at.",
"locale": "ro",
"details": {
"current_updated_at": "2026-10-30T10:42:05+01:00",
"reason": "modified_since_read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Registru de corespondență
Listare registru de corespondență
/api/agent/mail-register
Listează intrările din registrul de corespondență (Postakönyv) arhivate pe dosarele pe care utilizatorul le poate vedea, cele mai noi primele. Filtrați după dosar, direcție, text liber (subiect/expeditor/destinatar/număr de urmărire) și interval de date. Corespondența dosarelor arhivate este ascunsă, cu excepția cazului în care include_archived este true.
Parametri de interogare
matter_idDoar intrările acestui dosar (trebuie să fie vizibil pentru utilizator).
1234directionDoar intrările incoming (primite) sau outgoing (trimise).
"incoming" "outgoing" qCăutare text liber în subiect, expeditor, destinatar, recipient și numărul de urmărire (ignorând majusculele/minusculele).
"Kúria"date_fromDoar intrările a căror dată este în această zi sau ulterioară (YYYY-MM-DD).
"2026-01-01"date_toDoar intrările a căror dată este în această zi sau anterioară (YYYY-MM-DD).
"2026-12-31"updated_sinceDoar intrările modificate la acest moment sau după el (ISO 8601).
"2026-10-01T00:00:00+02:00"include_archivedInclude intrările dosarelor arhivate.
falselimitDimensiunea paginii, 1-100. Valoarea implicită este 25.
2525offsetNumărul de înregistrări de omis. Folosiți offset + limit ale paginii anterioare pentru a o obține pe următoarea; pagination.total este numărul total.
00Răspunsuri
200
OK.
dataobligatoriuCâmpurile data
idId-ul intrării din registrul de corespondență (folosiți cu mail_register.get / .update).
4321matterDosarul pe care este arhivată intrarea.
Câmpurile matter
idcase_numberdirectionincoming = primită, outgoing = trimisă.
"incoming" "outgoing" dateData poștală/înregistrată, YYYY-MM-DD (fără ora din zi).
subjectsenderFeladó: expeditorul (text liber).
toCímzett: destinatarul (text liber).
recipientPentru o corespondență incoming: numele afișat al colegului care a primit-o. Pentru o corespondență outgoing: destinatarul/primitorul în text liber.
recipient_user_idSetat doar pentru o corespondență incoming al cărei destinatar este un coleg (un id de utilizator); null pentru o corespondență outgoing.
electronicTrue când elementul a fost înregistrat ca electronic (type_of_mail).
delivery_method_idId-ul metodei de livrare (mail_delivery_methods).
delivery_methodEticheta localizată a metodei de livrare (Posta, Cégkapu, Perkapu, ...), sau varianta de rezervă electronic/neelectronic pentru un rând mai vechi.
tracking_noAzonosító: numărul de urmărire.
folder_pathrecorded_by_user_idColegul care a înregistrat intrarea.
recorded_bycreated_atupdated_atTransmiteți aceasta către mail_register.update ca expected_updated_at.
created_via_apiPrezent atunci când un agent extern a creat intrarea prin acest API.
Câmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduseratpaginationobligatoriuCâmpurile pagination
limitobligatoriuoffsetobligatoriutotalobligatoriuNumărul total de înregistrări care se potrivesc.
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl 'https://www.flowyer.ro/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.ro/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.ro/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())
Exemple de răspuns
{
"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": "Această cheie API nu are permisiunea \"mail_register:read\". Permisiunile unei chei existente nu pot fi modificate, așa că titularul cheii trebuie să creeze în Flowyer, la Setări > Chei API, o cheie nouă cu această permisiune și să o folosească în locul celei vechi.",
"locale": "ro",
"details": {
"required_scope": "mail_register:read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Obținere intrare din registrul de corespondență
/api/agent/mail-register/{id}
Returnează o intrare din registrul de corespondență (Postakönyv) după id, cu updated_at al acesteia (tokenul pe care îl acceptă mail_register.update). Răspunde cu 404 când intrarea nu există sau dosarul său nu este vizibil pentru utilizator.
Parametri de cale
idobligatoriuId-ul intrării din registrul de corespondență.
4321Răspunsuri
200
OK.
dataobligatoriuCâmpurile data
idId-ul intrării din registrul de corespondență (folosiți cu mail_register.get / .update).
4321matterDosarul pe care este arhivată intrarea.
Câmpurile matter
idcase_numberdirectionincoming = primită, outgoing = trimisă.
"incoming" "outgoing" dateData poștală/înregistrată, YYYY-MM-DD (fără ora din zi).
subjectsenderFeladó: expeditorul (text liber).
toCímzett: destinatarul (text liber).
recipientPentru o corespondență incoming: numele afișat al colegului care a primit-o. Pentru o corespondență outgoing: destinatarul/primitorul în text liber.
recipient_user_idSetat doar pentru o corespondență incoming al cărei destinatar este un coleg (un id de utilizator); null pentru o corespondență outgoing.
electronicTrue când elementul a fost înregistrat ca electronic (type_of_mail).
delivery_method_idId-ul metodei de livrare (mail_delivery_methods).
delivery_methodEticheta localizată a metodei de livrare (Posta, Cégkapu, Perkapu, ...), sau varianta de rezervă electronic/neelectronic pentru un rând mai vechi.
tracking_noAzonosító: numărul de urmărire.
folder_pathrecorded_by_user_idColegul care a înregistrat intrarea.
recorded_bycreated_atupdated_atTransmiteți aceasta către mail_register.update ca expected_updated_at.
created_via_apiPrezent atunci când un agent extern a creat intrarea prin acest API.
Câmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduserat
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl 'https://www.flowyer.ro/api/agent/mail-register/4321' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.ro/api/agent/mail-register/4321", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.ro/api/agent/mail-register/4321",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Exemple de răspuns
{
"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": "Înregistrarea nu a fost găsită sau nu este vizibilă pentru titularul acestei chei API.",
"locale": "ro",
"details": {
"record_type": "mail",
"record_id": 4321
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Creare intrare în registrul de corespondență
/api/agent/mail-register
Arhivează o nouă intrare în registrul de corespondență (Postakönyv) pe un dosar. Folosiți recipient_user_id pentru o corespondență incoming primită de un coleg, sau recipient (text liber) pentru una outgoing. delivery_method_id trebuie să fie o metodă cunoscută. Răspunde cu 404 când dosarul nu este vizibil.
Parametri de antet
Idempotency-KeyRecomandat la fiecare creare. O valoare unică per operație logică (de exemplu un UUID). Aceeași valoare returnează aceeași înregistrare: reîncercarea cu ea returnează înregistrarea creată prima dată, în loc să creeze o a doua. Valori diferite creează întotdeauna înregistrări diferite. Clienții care nu pot trimite anteturi pot transmite aceeași valoare în câmpul de corp idempotency_key. Litere, cifre, _, -, : sau ., cel mult 128 de caractere.
^[A-Za-z0-9_\-:.]{1,128}$Corpul cererii application/json
matter_idobligatoriuDosarul de care aparține intrarea (trebuie să fie vizibil).
1234directionobligatoriuincoming = primită, outgoing = trimisă.
"incoming" "outgoing" dateobligatoriuData poștală/înregistrată, YYYY-MM-DD (fără ora din zi).
"2026-11-03"subjectobligatoriuSubiectul corespondenței. Text simplu; "<" și ">" nu sunt permise.
^[^<>]*$"Fellebbezés a Kúriához"senderFeladó: expeditorul (text liber). Text simplu; "<" și ">" nu sunt permise.
^[^<>]*$toCímzett: destinatarul (text liber). Text simplu; "<" și ">" nu sunt permise.
^[^<>]*$recipientCorespondență outgoing: destinatarul/primitorul în text liber. Nu este permis împreună cu recipient_user_id. Text simplu; "<" și ">" nu sunt permise.
^[^<>]*$recipient_user_idCorespondență incoming: colegul care a primit-o (un id de utilizator din colleagues.list), stocat ca recipient numeric. Nu este permis împreună cu recipient.
electronicDacă elementul este electronic (type_of_mail); independent de metoda de livrare. Implicit false.
falsedelivery_method_idId-ul metodei de livrare (mail_delivery_methods): de exemplu 1 Posta, 4 Cégkapu, 7 Perkapu. 422 când este necunoscut.
tracking_noAzonosító: numărul de urmărire. Text simplu; "<" și ">" nu sunt permise.
^[^<>]*$folder_path^[^<>]*$idempotency_keyAcelași rol ca antetul Idempotency-Key, pentru clienții care nu pot trimite anteturi personalizate. Litere, cifre, _, -, : sau ., cel mult 128 de caractere.
^[A-Za-z0-9_\-:.]{1,128}$"b8f1c2e0-6f7a-4d2e-9c1b-2a3d4e5f6a7b"Răspunsuri
201
Creat.
dataobligatoriuCâmpurile data
idId-ul intrării din registrul de corespondență (folosiți cu mail_register.get / .update).
4321matterDosarul pe care este arhivată intrarea.
Câmpurile matter
idcase_numberdirectionincoming = primită, outgoing = trimisă.
"incoming" "outgoing" dateData poștală/înregistrată, YYYY-MM-DD (fără ora din zi).
subjectsenderFeladó: expeditorul (text liber).
toCímzett: destinatarul (text liber).
recipientPentru o corespondență incoming: numele afișat al colegului care a primit-o. Pentru o corespondență outgoing: destinatarul/primitorul în text liber.
recipient_user_idSetat doar pentru o corespondență incoming al cărei destinatar este un coleg (un id de utilizator); null pentru o corespondență outgoing.
electronicTrue când elementul a fost înregistrat ca electronic (type_of_mail).
delivery_method_idId-ul metodei de livrare (mail_delivery_methods).
delivery_methodEticheta localizată a metodei de livrare (Posta, Cégkapu, Perkapu, ...), sau varianta de rezervă electronic/neelectronic pentru un rând mai vechi.
tracking_noAzonosító: numărul de urmărire.
folder_pathrecorded_by_user_idColegul care a înregistrat intrarea.
recorded_bycreated_atupdated_atTransmiteți aceasta către mail_register.update ca expected_updated_at.
created_via_apiPrezent atunci când un agent extern a creat intrarea prin acest API.
Câmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduseratcreatedtrue
200
Reluare idempotentă: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică în interval de 120 de secunde) a creat deja înregistrarea; aceasta este returnată din nou, nu s-a creat nimic nou.
dataobligatoriuCâmpurile data
idId-ul intrării din registrul de corespondență (folosiți cu mail_register.get / .update).
4321matterDosarul pe care este arhivată intrarea.
Câmpurile matter
idcase_numberdirectionincoming = primită, outgoing = trimisă.
"incoming" "outgoing" dateData poștală/înregistrată, YYYY-MM-DD (fără ora din zi).
subjectsenderFeladó: expeditorul (text liber).
toCímzett: destinatarul (text liber).
recipientPentru o corespondență incoming: numele afișat al colegului care a primit-o. Pentru o corespondență outgoing: destinatarul/primitorul în text liber.
recipient_user_idSetat doar pentru o corespondență incoming al cărei destinatar este un coleg (un id de utilizator); null pentru o corespondență outgoing.
electronicTrue când elementul a fost înregistrat ca electronic (type_of_mail).
delivery_method_idId-ul metodei de livrare (mail_delivery_methods).
delivery_methodEticheta localizată a metodei de livrare (Posta, Cégkapu, Perkapu, ...), sau varianta de rezervă electronic/neelectronic pentru un rând mai vechi.
tracking_noAzonosító: numărul de urmărire.
folder_pathrecorded_by_user_idColegul care a înregistrat intrarea.
recorded_bycreated_atupdated_atTransmiteți aceasta către mail_register.update ca expected_updated_at.
created_via_apiPrezent atunci când un agent extern a creat intrarea prin acest API.
Câmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduseratcreatedfalseidempotent_replaytrue
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator. replay_not_visible: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică) a creat deja înregistrarea (details.record_id), dar aceasta a fost între timp ștearsă sau nu este vizibilă pentru utilizator; nu s-a creat nimic nou, nu o creați din nou.
replay_not_visible: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică) a creat deja înregistrarea (details.record_id), dar aceasta a fost între timp ștearsă sau nu este vizibilă pentru utilizator; nu s-a creat nimic nou, nu o creați din nou.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
409
Idempotency-Key a fost folosit pentru alt tip de resursă (idempotency_key_reused) sau, în lipsa unei chei, o cerere identică este procesată chiar acum (duplicate_in_progress; reîncercați în scurt timp).
idempotency_key_reused) sau, în lipsa unei chei, o cerere identică este procesată chiar acum (duplicate_in_progress; reîncercați în scurt timp).
413
Corpul cererii este prea mare (request_too_large).
request_too_large).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl -X POST 'https://www.flowyer.ro/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.ro/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.ro/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"
}
Exemple de răspuns
{
"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": "Cererea nu este validă. Erorile pe câmpuri se găsesc în \"details.fields\".",
"locale": "ro",
"details": {
"fields": {
"matter_id": [
"Câmpul matter id este obligatoriu."
]
}
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Actualizare intrare din registrul de corespondență
/api/agent/mail-register/{id}
Actualizează o intrare din registrul de corespondență (Postakönyv); se modifică doar câmpurile pe care le trimiteți. Intrarea rămâne pe dosarul său. Transmiteți expected_updated_at din ultima citire; o modificare conflictuală răspunde cu 409. Răspunde cu 404 când intrarea nu este vizibilă.
Parametri de cale
idobligatoriuId-ul înregistrării de modificat.
Corpul cererii application/json
expected_updated_atValoarea updated_at din cea mai recentă citire a acestei înregistrări (obligatorie ori de câte ori înregistrarea are una). Dacă înregistrarea s-a schimbat între timp (un coleg a editat-o), API-ul răspunde cu 409 și trebuie să o recitiți înainte de a reîncerca. O înregistrare veche al cărei updated_at este null acceptă null.
directionincoming = primită, outgoing = trimisă.
"incoming" "outgoing" dateData poștală/înregistrată, YYYY-MM-DD.
subjectSubiect. Text simplu; "<" și ">" nu sunt permise.
^[^<>]*$senderFeladó: expeditorul (text liber). Text simplu; "<" și ">" nu sunt permise.
^[^<>]*$toCímzett: destinatarul (text liber). Text simplu; "<" și ">" nu sunt permise.
^[^<>]*$recipientCorespondență outgoing: destinatarul în text liber. Nu este permis împreună cu recipient_user_id. Text simplu; "<" și ">" nu sunt permise.
^[^<>]*$recipient_user_idCorespondență incoming: colegul care primește (un id de utilizator), stocat ca recipient numeric. Nu este permis împreună cu recipient.
electronicDacă elementul este electronic (type_of_mail).
delivery_method_idId-ul metodei de livrare (mail_delivery_methods); 422 când este necunoscut.
tracking_noAzonosító: numărul de urmărire. Text simplu; "<" și ">" nu sunt permise.
^[^<>]*$folder_path^[^<>]*$Răspunsuri
200
Actualizat.
dataobligatoriuCâmpurile data
idId-ul intrării din registrul de corespondență (folosiți cu mail_register.get / .update).
4321matterDosarul pe care este arhivată intrarea.
Câmpurile matter
idcase_numberdirectionincoming = primită, outgoing = trimisă.
"incoming" "outgoing" dateData poștală/înregistrată, YYYY-MM-DD (fără ora din zi).
subjectsenderFeladó: expeditorul (text liber).
toCímzett: destinatarul (text liber).
recipientPentru o corespondență incoming: numele afișat al colegului care a primit-o. Pentru o corespondență outgoing: destinatarul/primitorul în text liber.
recipient_user_idSetat doar pentru o corespondență incoming al cărei destinatar este un coleg (un id de utilizator); null pentru o corespondență outgoing.
electronicTrue când elementul a fost înregistrat ca electronic (type_of_mail).
delivery_method_idId-ul metodei de livrare (mail_delivery_methods).
delivery_methodEticheta localizată a metodei de livrare (Posta, Cégkapu, Perkapu, ...), sau varianta de rezervă electronic/neelectronic pentru un rând mai vechi.
tracking_noAzonosító: numărul de urmărire.
folder_pathrecorded_by_user_idColegul care a înregistrat intrarea.
recorded_bycreated_atupdated_atTransmiteți aceasta către mail_register.update ca expected_updated_at.
created_via_apiPrezent atunci când un agent extern a creat intrarea prin acest API.
Câmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduseratupdatedtrue
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
409
Înregistrarea s-a schimbat de când ați citit-o (record_conflict: expected_updated_at nu mai corespunde; citiți-o din nou și reîncercați cu noul updated_at).
record_conflict: expected_updated_at nu mai corespunde; citiți-o din nou și reîncercați cu noul updated_at).
413
Corpul cererii este prea mare (request_too_large).
request_too_large).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl -X PATCH 'https://www.flowyer.ro/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.ro/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.ro/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"
}
Exemple de răspuns
{
"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": "Înregistrarea s-a modificat de când ați citit-o (cineva a editat-o). Citiți-o din nou și reîncercați cu noua valoare updated_at.",
"locale": "ro",
"details": {
"current_updated_at": "2026-10-30T10:42:05+01:00",
"reason": "modified_since_read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Comentarii
Listare comentarii de dosar
/api/agent/matters/{id}/comments
Listează comentariile unui dosar, cele mai vechi primele: id, autor, corp (HTML îmbogățit) și parent_id-ul unui răspuns. Plat, nu imbricat - reconstruiți firele cu un singur nivel din parent_id. Transmiteți top_level_only pentru a exclude răspunsurile. Răspunde cu 404 când dosarul nu este vizibil pentru utilizator.
Parametri de cale
idobligatoriuId-ul dosarului (trebuie să fie vizibil).
1234Parametri de interogare
top_level_onlyDoar comentariile de nivel superior (exclude răspunsurile). Implicit false.
falselimitDimensiunea paginii, 1-100. Valoarea implicită este 25.
2525offsetNumărul de înregistrări de omis. Folosiți offset + limit ale paginii anterioare pentru a o obține pe următoarea; pagination.total este numărul total.
00Răspunsuri
200
OK.
dataobligatoriuCâmpurile data
id9876matter_idDosarul (= case_id) de care aparține comentariul.
parent_idComentariul de nivel superior la care răspunde acesta; null pentru un comentariu de nivel superior. Răspunsurile au un singur nivel de adâncime.
author_user_idId-ul de utilizator al autorului (null pentru un import mai vechi).
author_nameNumele afișat al autorului, sau null.
bodyComentariul așa cum este stocat: HTML îmbogățit, deja curățat cu HTMLPurifier pentru comentariile scrise prin acest API.
created_atCând a fost postat comentariul, ISO 8601 în fusul biroului.
updated_atToken de blocare optimistă: transmiteți-l către comments.update ca expected_updated_at. Nu este un moment de afișare; null pentru un comentariu mai vechi care nu are unul.
editedTrue când comentariul a fost editat de când a fost postat.
paginationobligatoriuCâmpurile pagination
limitobligatoriuoffsetobligatoriutotalobligatoriuNumărul total de înregistrări care se potrivesc.
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl 'https://www.flowyer.ro/api/agent/matters/1234/comments?limit=25' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.ro/api/agent/matters/1234/comments?limit=25", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.ro/api/agent/matters/1234/comments?limit=25",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Exemple de răspuns
{
"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": "Dosarul 1234 nu există, este arhivat sau nu este vizibil pentru titularul acestei chei API.",
"locale": "ro",
"details": {
"matter_id": 1234
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Postare comentariu de dosar
/api/agent/matters/{id}/comments
Postează un comentariu pe un dosar, sau un răspuns de un singur nivel (parent_id = un comentariu de NIVEL SUPERIOR al ACELUIAȘI dosar). Corpul este HTML îmbogățit, igienizat pe partea de server înainte de stocare. Răspunde cu 404 când dosarul nu este vizibil, cu 422 când parent_id nu este un comentariu de nivel superior al dosarului.
Parametri de cale
idobligatoriuId-ul dosarului (trebuie să fie vizibil).
1234Parametri de antet
Idempotency-KeyRecomandat la fiecare creare. O valoare unică per operație logică (de exemplu un UUID). Aceeași valoare returnează aceeași înregistrare: reîncercarea cu ea returnează înregistrarea creată prima dată, în loc să creeze o a doua. Valori diferite creează întotdeauna înregistrări diferite. Clienții care nu pot trimite anteturi pot transmite aceeași valoare în câmpul de corp idempotency_key. Litere, cifre, _, -, : sau ., cel mult 128 de caractere.
^[A-Za-z0-9_\-:.]{1,128}$Corpul cererii application/json
bodyobligatoriuComentariul, HTML îmbogățit (așa cum îl produce TinyMCE). Curățat pe partea de server cu HTMLPurifier înainte de stocare. Cel mult 100000 de caractere.
"<p>Egyetértek, a határidő tartható.</p>"parent_idRăspuns la acest comentariu de NIVEL SUPERIOR al ACELUIAȘI dosar (din comments.list, parent_id = null); omiteți pentru un nou comentariu de nivel superior.
idempotency_keyAcelași rol ca antetul Idempotency-Key, pentru clienții care nu pot trimite anteturi personalizate. Litere, cifre, _, -, : sau ., cel mult 128 de caractere.
^[A-Za-z0-9_\-:.]{1,128}$"b8f1c2e0-6f7a-4d2e-9c1b-2a3d4e5f6a7b"Răspunsuri
201
Creat.
dataobligatoriuCâmpurile data
id9876matter_idDosarul (= case_id) de care aparține comentariul.
parent_idComentariul de nivel superior la care răspunde acesta; null pentru un comentariu de nivel superior. Răspunsurile au un singur nivel de adâncime.
author_user_idId-ul de utilizator al autorului (null pentru un import mai vechi).
author_nameNumele afișat al autorului, sau null.
bodyComentariul așa cum este stocat: HTML îmbogățit, deja curățat cu HTMLPurifier pentru comentariile scrise prin acest API.
created_atCând a fost postat comentariul, ISO 8601 în fusul biroului.
updated_atToken de blocare optimistă: transmiteți-l către comments.update ca expected_updated_at. Nu este un moment de afișare; null pentru un comentariu mai vechi care nu are unul.
editedTrue când comentariul a fost editat de când a fost postat.
createdtrue
200
Reluare idempotentă: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică în interval de 120 de secunde) a creat deja înregistrarea; aceasta este returnată din nou, nu s-a creat nimic nou.
dataobligatoriuCâmpurile data
id9876matter_idDosarul (= case_id) de care aparține comentariul.
parent_idComentariul de nivel superior la care răspunde acesta; null pentru un comentariu de nivel superior. Răspunsurile au un singur nivel de adâncime.
author_user_idId-ul de utilizator al autorului (null pentru un import mai vechi).
author_nameNumele afișat al autorului, sau null.
bodyComentariul așa cum este stocat: HTML îmbogățit, deja curățat cu HTMLPurifier pentru comentariile scrise prin acest API.
created_atCând a fost postat comentariul, ISO 8601 în fusul biroului.
updated_atToken de blocare optimistă: transmiteți-l către comments.update ca expected_updated_at. Nu este un moment de afișare; null pentru un comentariu mai vechi care nu are unul.
editedTrue când comentariul a fost editat de când a fost postat.
createdfalseidempotent_replaytrue
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator. replay_not_visible: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică) a creat deja înregistrarea (details.record_id), dar aceasta a fost între timp ștearsă sau nu este vizibilă pentru utilizator; nu s-a creat nimic nou, nu o creați din nou.
replay_not_visible: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică) a creat deja înregistrarea (details.record_id), dar aceasta a fost între timp ștearsă sau nu este vizibilă pentru utilizator; nu s-a creat nimic nou, nu o creați din nou.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
409
Idempotency-Key a fost folosit pentru alt tip de resursă (idempotency_key_reused) sau, în lipsa unei chei, o cerere identică este procesată chiar acum (duplicate_in_progress; reîncercați în scurt timp).
idempotency_key_reused) sau, în lipsa unei chei, o cerere identică este procesată chiar acum (duplicate_in_progress; reîncercați în scurt timp).
413
Corpul cererii este prea mare (request_too_large).
request_too_large).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl -X POST 'https://www.flowyer.ro/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.ro/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.ro/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>"
}
Exemple de răspuns
{
"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": "Cererea nu este validă. Erorile pe câmpuri se găsesc în \"details.fields\".",
"locale": "ro",
"details": {
"fields": {
"body": [
"Câmpul body este obligatoriu."
]
}
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Editare comentariu propriu de dosar
/api/agent/comments/{id}
Editează unul dintre comentariile dumneavoastră PROPRII (doar corpul acestuia; HTML îmbogățit, igienizat pe partea de server înainte de stocare). Transmiteți expected_updated_at din ultima citire; o modificare conflictuală răspunde cu 409. Răspunde cu 404 pentru un comentariu care nu este al dumneavoastră sau care se află pe un dosar pe care nu îl puteți vedea.
Parametri de cale
idobligatoriuId-ul înregistrării de modificat.
Corpul cererii application/json
expected_updated_atValoarea updated_at din cea mai recentă citire a acestei înregistrări (obligatorie ori de câte ori înregistrarea are una). Dacă înregistrarea s-a schimbat între timp (un coleg a editat-o), API-ul răspunde cu 409 și trebuie să o recitiți înainte de a reîncerca. O înregistrare veche al cărei updated_at este null acceptă null.
bodyobligatoriuCorpul nou al comentariului, HTML îmbogățit (așa cum îl produce TinyMCE). Curățat pe partea de server cu HTMLPurifier înainte de stocare. Cel mult 100000 de caractere.
"<p>Pontosítás: a határidő november 15.</p>"Răspunsuri
200
Actualizat.
dataobligatoriuCâmpurile data
id9876matter_idDosarul (= case_id) de care aparține comentariul.
parent_idComentariul de nivel superior la care răspunde acesta; null pentru un comentariu de nivel superior. Răspunsurile au un singur nivel de adâncime.
author_user_idId-ul de utilizator al autorului (null pentru un import mai vechi).
author_nameNumele afișat al autorului, sau null.
bodyComentariul așa cum este stocat: HTML îmbogățit, deja curățat cu HTMLPurifier pentru comentariile scrise prin acest API.
created_atCând a fost postat comentariul, ISO 8601 în fusul biroului.
updated_atToken de blocare optimistă: transmiteți-l către comments.update ca expected_updated_at. Nu este un moment de afișare; null pentru un comentariu mai vechi care nu are unul.
editedTrue când comentariul a fost editat de când a fost postat.
updatedtrue
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
409
Înregistrarea s-a schimbat de când ați citit-o (record_conflict: expected_updated_at nu mai corespunde; citiți-o din nou și reîncercați cu noul updated_at).
record_conflict: expected_updated_at nu mai corespunde; citiți-o din nou și reîncercați cu noul updated_at).
413
Corpul cererii este prea mare (request_too_large).
request_too_large).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl -X PATCH 'https://www.flowyer.ro/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.ro/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.ro/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>"
}
Exemple de răspuns
{
"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": "Înregistrarea s-a modificat de când ați citit-o (cineva a editat-o). Citiți-o din nou și reîncercați cu noua valoare updated_at.",
"locale": "ro",
"details": {
"current_updated_at": "2026-10-30T10:42:05+01:00",
"reason": "modified_since_read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Termene de judecată
Listare termene de judecată ale dosarului
/api/agent/matters/{id}/trials
Listează termenele de judecată (tárgyalások) ale unui dosar: data, instanța, locul, colegii participanți și judecătorul, cele mai noi primele. Opțional filtrate după un interval de zile from/to sau după updated_since. Răspunde cu 404 când dosarul nu este vizibil pentru utilizator.
Parametri de cale
idobligatoriuId-ul dosarului.
1234Parametri de interogare
fromDoar termenele din această zi sau ulterioare (YYYY-MM-DD), în fusul orar al biroului.
"2026-01-01"toDoar termenele din această zi sau anterioare (YYYY-MM-DD), în fusul orar al biroului.
"2026-12-31"updated_sinceDoar termenele modificate la acest moment ISO 8601 sau după el.
limitDimensiunea paginii, 1-100. Valoarea implicită este 25.
2525offsetNumărul de înregistrări de omis. Folosiți offset + limit ale paginii anterioare pentru a o obține pe următoarea; pagination.total este numărul total.
00Răspunsuri
200
OK.
dataobligatoriuCâmpurile data
id4321matterDosarul (cazul) de care aparține termenul.
Câmpurile matter
idcase_numberdateData și ora termenului, ISO 8601 în fusul orar al biroului. Este stocat în UTC, așa că comparați momente, nu textul orei de perete.
"2026-03-02T09:00:00+01:00"participationDacă este necesară prezența unui coleg: "required", "not_required", sau null când nu este setat.
"required" "not_required" courtInstanța termenului, rezolvată din registrul partajat al instanțelor; null când nu este setată nicio instanță.
Câmpurile court
idnamecityzipaddresssourceÎntotdeauna "registry": instanța este o referință către registrul partajat al instanțelor (courts.list), nu text liber.
placeSala sau locația termenului. Text simplu.
name_of_the_judgeNumele judecătorului. Text simplu.
notesNote în text liber despre termen. Text simplu.
responsiblesColegii care participă la termen (id-uri din colleagues.list).
Câmpurile responsibles
user_idnamerecorded_byColegul care a înregistrat termenul.
Câmpurile recorded_by
user_idnamecreated_atupdated_atTransmiteți aceasta către trials.update ca expected_updated_at.
created_via_apiPrezent atunci când un agent extern a creat înregistrarea prin acest API.
Câmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduseratpaginationobligatoriuCâmpurile pagination
limitobligatoriuoffsetobligatoriutotalobligatoriuNumărul total de înregistrări care se potrivesc.
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl 'https://www.flowyer.ro/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.ro/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.ro/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())
Exemple de răspuns
{
"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": "Dosarul 1234 nu există, este arhivat sau nu este vizibil pentru titularul acestei chei API.",
"locale": "ro",
"details": {
"matter_id": 1234
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Obținere termen de judecată
/api/agent/trials/{id}
Returnează un termen de judecată (tárgyalás) cu dosarul său, instanța, colegii participanți și tokenul de blocare updated_at pentru trials.update. Răspunde cu 404 când termenul nu există sau utilizatorul nu îi poate vedea dosarul.
Parametri de cale
idobligatoriuId-ul termenului.
4321Răspunsuri
200
OK.
dataobligatoriuCâmpurile data
id4321matterDosarul (cazul) de care aparține termenul.
Câmpurile matter
idcase_numberdateData și ora termenului, ISO 8601 în fusul orar al biroului. Este stocat în UTC, așa că comparați momente, nu textul orei de perete.
"2026-03-02T09:00:00+01:00"participationDacă este necesară prezența unui coleg: "required", "not_required", sau null când nu este setat.
"required" "not_required" courtInstanța termenului, rezolvată din registrul partajat al instanțelor; null când nu este setată nicio instanță.
Câmpurile court
idnamecityzipaddresssourceÎntotdeauna "registry": instanța este o referință către registrul partajat al instanțelor (courts.list), nu text liber.
placeSala sau locația termenului. Text simplu.
name_of_the_judgeNumele judecătorului. Text simplu.
notesNote în text liber despre termen. Text simplu.
responsiblesColegii care participă la termen (id-uri din colleagues.list).
Câmpurile responsibles
user_idnamerecorded_byColegul care a înregistrat termenul.
Câmpurile recorded_by
user_idnamecreated_atupdated_atTransmiteți aceasta către trials.update ca expected_updated_at.
created_via_apiPrezent atunci când un agent extern a creat înregistrarea prin acest API.
Câmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduserat
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl 'https://www.flowyer.ro/api/agent/trials/4321' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.ro/api/agent/trials/4321", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.ro/api/agent/trials/4321",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Exemple de răspuns
{
"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": "Înregistrarea nu a fost găsită sau nu este vizibilă pentru titularul acestei chei API.",
"locale": "ro",
"details": {
"record_type": "trial",
"record_id": 4321
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Creare termen de judecată
/api/agent/matters/{id}/trials
Înregistrează un termen de judecată (tárgyalás) pe un dosar: ora, o instanță opțională (court_id din courts.list), sala, judecătorul, notele și colegii participanți. Dosarul trebuie să fie vizibil și nearhivat; participanții sunt notificați. O oră fără offset este citită în fusul biroului.
Parametri de cale
idobligatoriuDosarul de care aparține termenul (trebuie să fie vizibil și nearhivat).
1234Parametri de antet
Idempotency-KeyRecomandat la fiecare creare. O valoare unică per operație logică (de exemplu un UUID). Aceeași valoare returnează aceeași înregistrare: reîncercarea cu ea returnează înregistrarea creată prima dată, în loc să creeze o a doua. Valori diferite creează întotdeauna înregistrări diferite. Clienții care nu pot trimite anteturi pot transmite aceeași valoare în câmpul de corp idempotency_key. Litere, cifre, _, -, : sau ., cel mult 128 de caractere.
^[A-Za-z0-9_\-:.]{1,128}$Corpul cererii application/json
dateobligatoriuData și ora termenului, ISO 8601. Cu un offset, acesta este respectat; fără unul, este citit în fusul orar al biroului. Stocat în UTC.
"2026-03-02T09:00:00+01:00"court_idInstanța termenului: un id din courts.list (registrul partajat al instanțelor). Omiteți când instanța nu este cunoscută.
42participationDacă este necesară prezența unui coleg. Omiteți pentru a-l lăsa nesetat.
"required" "not_required" placeSala sau locația termenului. Text simplu; "<" și ">" nu sunt permise.
^[^<>]*$"II. emelet 205."name_of_the_judgeNumele judecătorului. Text simplu; "<" și ">" nu sunt permise.
^[^<>]*$notesNote în text liber despre termen. Text simplu; "<" și ">" nu sunt permise.
^[^<>]*$responsible_user_idsId-urile de utilizator ale colegilor (din colleagues.list) care participă la termen.
idempotency_keyAcelași rol ca antetul Idempotency-Key, pentru clienții care nu pot trimite anteturi personalizate. Litere, cifre, _, -, : sau ., cel mult 128 de caractere.
^[A-Za-z0-9_\-:.]{1,128}$"b8f1c2e0-6f7a-4d2e-9c1b-2a3d4e5f6a7b"Răspunsuri
201
Creat.
dataobligatoriuCâmpurile data
id4321matterDosarul (cazul) de care aparține termenul.
Câmpurile matter
idcase_numberdateData și ora termenului, ISO 8601 în fusul orar al biroului. Este stocat în UTC, așa că comparați momente, nu textul orei de perete.
"2026-03-02T09:00:00+01:00"participationDacă este necesară prezența unui coleg: "required", "not_required", sau null când nu este setat.
"required" "not_required" courtInstanța termenului, rezolvată din registrul partajat al instanțelor; null când nu este setată nicio instanță.
Câmpurile court
idnamecityzipaddresssourceÎntotdeauna "registry": instanța este o referință către registrul partajat al instanțelor (courts.list), nu text liber.
placeSala sau locația termenului. Text simplu.
name_of_the_judgeNumele judecătorului. Text simplu.
notesNote în text liber despre termen. Text simplu.
responsiblesColegii care participă la termen (id-uri din colleagues.list).
Câmpurile responsibles
user_idnamerecorded_byColegul care a înregistrat termenul.
Câmpurile recorded_by
user_idnamecreated_atupdated_atTransmiteți aceasta către trials.update ca expected_updated_at.
created_via_apiPrezent atunci când un agent extern a creat înregistrarea prin acest API.
Câmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduseratcreatedtrue
200
Reluare idempotentă: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică în interval de 120 de secunde) a creat deja înregistrarea; aceasta este returnată din nou, nu s-a creat nimic nou.
dataobligatoriuCâmpurile data
id4321matterDosarul (cazul) de care aparține termenul.
Câmpurile matter
idcase_numberdateData și ora termenului, ISO 8601 în fusul orar al biroului. Este stocat în UTC, așa că comparați momente, nu textul orei de perete.
"2026-03-02T09:00:00+01:00"participationDacă este necesară prezența unui coleg: "required", "not_required", sau null când nu este setat.
"required" "not_required" courtInstanța termenului, rezolvată din registrul partajat al instanțelor; null când nu este setată nicio instanță.
Câmpurile court
idnamecityzipaddresssourceÎntotdeauna "registry": instanța este o referință către registrul partajat al instanțelor (courts.list), nu text liber.
placeSala sau locația termenului. Text simplu.
name_of_the_judgeNumele judecătorului. Text simplu.
notesNote în text liber despre termen. Text simplu.
responsiblesColegii care participă la termen (id-uri din colleagues.list).
Câmpurile responsibles
user_idnamerecorded_byColegul care a înregistrat termenul.
Câmpurile recorded_by
user_idnamecreated_atupdated_atTransmiteți aceasta către trials.update ca expected_updated_at.
created_via_apiPrezent atunci când un agent extern a creat înregistrarea prin acest API.
Câmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduseratcreatedfalseidempotent_replaytrue
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator. replay_not_visible: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică) a creat deja înregistrarea (details.record_id), dar aceasta a fost între timp ștearsă sau nu este vizibilă pentru utilizator; nu s-a creat nimic nou, nu o creați din nou.
replay_not_visible: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică) a creat deja înregistrarea (details.record_id), dar aceasta a fost între timp ștearsă sau nu este vizibilă pentru utilizator; nu s-a creat nimic nou, nu o creați din nou.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
409
Idempotency-Key a fost folosit pentru alt tip de resursă (idempotency_key_reused) sau, în lipsa unei chei, o cerere identică este procesată chiar acum (duplicate_in_progress; reîncercați în scurt timp).
idempotency_key_reused) sau, în lipsa unei chei, o cerere identică este procesată chiar acum (duplicate_in_progress; reîncercați în scurt timp).
413
Corpul cererii este prea mare (request_too_large).
request_too_large).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl -X POST 'https://www.flowyer.ro/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.ro/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.ro/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."
}
Exemple de răspuns
{
"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": "Cererea nu este validă. Erorile pe câmpuri se găsesc în \"details.fields\".",
"locale": "ro",
"details": {
"fields": {
"date": [
"Câmpul date este obligatoriu."
]
}
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Actualizare termen de judecată
/api/agent/trials/{id}
Actualizează un termen de judecată (tárgyalás): ora, instanța, locul, judecătorul, notele, indicatorul de prezență și participanții. Scrie doar câmpurile pe care le trimiteți; trimiteți responsible_user_ids pentru a înlocui întreaga listă de participanți. Transmiteți expected_updated_at din ultima citire; o modificare conflictuală răspunde cu 409.
Parametri de cale
idobligatoriuId-ul înregistrării de modificat.
Corpul cererii application/json
expected_updated_atValoarea updated_at din cea mai recentă citire a acestei înregistrări (obligatorie ori de câte ori înregistrarea are una). Dacă înregistrarea s-a schimbat între timp (un coleg a editat-o), API-ul răspunde cu 409 și trebuie să o recitiți înainte de a reîncerca. O înregistrare veche al cărei updated_at este null acceptă null.
dateNoua dată și oră a termenului, ISO 8601 (un offset este respectat, o oră naivă este citită în fusul biroului). Stocat în UTC.
"2026-03-02T09:00:00+01:00"court_idNoul id de instanță din courts.list; null pentru a șterge instanța.
participationDacă este necesară prezența unui coleg; null pentru a-l șterge.
"required" "not_required" placeSala sau locația. Text simplu; "<" și ">" nu sunt permise. "" o șterge.
^[^<>]*$name_of_the_judgeNumele judecătorului. Text simplu; "<" și ">" nu sunt permise. "" îl șterge.
^[^<>]*$notesNote în text liber. Text simplu; "<" și ">" nu sunt permise. "" le șterge.
^[^<>]*$responsible_user_idsSetul complet de înlocuire al id-urilor de utilizator ale participanților (din colleagues.list). Omiteți pentru a lăsa participanții neschimbați.
Răspunsuri
200
Actualizat.
dataobligatoriuCâmpurile data
id4321matterDosarul (cazul) de care aparține termenul.
Câmpurile matter
idcase_numberdateData și ora termenului, ISO 8601 în fusul orar al biroului. Este stocat în UTC, așa că comparați momente, nu textul orei de perete.
"2026-03-02T09:00:00+01:00"participationDacă este necesară prezența unui coleg: "required", "not_required", sau null când nu este setat.
"required" "not_required" courtInstanța termenului, rezolvată din registrul partajat al instanțelor; null când nu este setată nicio instanță.
Câmpurile court
idnamecityzipaddresssourceÎntotdeauna "registry": instanța este o referință către registrul partajat al instanțelor (courts.list), nu text liber.
placeSala sau locația termenului. Text simplu.
name_of_the_judgeNumele judecătorului. Text simplu.
notesNote în text liber despre termen. Text simplu.
responsiblesColegii care participă la termen (id-uri din colleagues.list).
Câmpurile responsibles
user_idnamerecorded_byColegul care a înregistrat termenul.
Câmpurile recorded_by
user_idnamecreated_atupdated_atTransmiteți aceasta către trials.update ca expected_updated_at.
created_via_apiPrezent atunci când un agent extern a creat înregistrarea prin acest API.
Câmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduseratupdatedtrue
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
409
Înregistrarea s-a schimbat de când ați citit-o (record_conflict: expected_updated_at nu mai corespunde; citiți-o din nou și reîncercați cu noul updated_at).
record_conflict: expected_updated_at nu mai corespunde; citiți-o din nou și reîncercați cu noul updated_at).
413
Corpul cererii este prea mare (request_too_large).
request_too_large).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl -X PATCH 'https://www.flowyer.ro/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.ro/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.ro/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"
}
Exemple de răspuns
{
"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": "Înregistrarea s-a modificat de când ați citit-o (cineva a editat-o). Citiți-o din nou și reîncercați cu noua valoare updated_at.",
"locale": "ro",
"details": {
"current_updated_at": "2026-10-30T10:42:05+01:00",
"reason": "modified_since_read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Instanțe
Listare instanțe
/api/agent/courts
Listează registrul partajat al instanțelor (id, nume, oraș) pentru court_id al trials.create / trials.update. Cu q (un nume de instanță așa cum a fost auzit; diacriticele, majusculele/minusculele și micile greșeli de tastare sunt tolerate) răspunde cu statusul exact/similar/none: doar "exact" este sigur de folosit direct. Este directorul instanțelor din Ungaria.
Parametri de interogare
qUn nume de instanță de căutat, așa cum a fost auzit sau dictat, în orice ordine a cuvintelor. Omiteți-l pentru a lista fiecare instanță.
"Fővárosi Törvényszék"limitNumărul maxim de instanțe de returnat (implicit 200).
200Răspunsuri
200
OK.
dataobligatoriuCâmpurile data
statusDoar cu q: exact = o singură potrivire sigură (id-ul ei se poate folosi în siguranță), similar = potrivire aproximativă sau mai multe potriviri (confirmați mai întâi cu utilizatorul), none = nicio potrivire (întrebați utilizatorul). Null fără q.
"exact" "similar" "none" courtsInstanțe, cea mai bună potrivire prima cu q, altfel după nume.
Câmpurile courts
idId-ul instanței: transmiteți-l ca court_id către trials.create / trials.update.
nameNumele instanței așa cum este afișat în Flowyer.
cityzipaddresstotalCâte instanțe au corespuns (toate instanțele fără q) înainte ca lista să fie redusă la limit.
truncatedTrue când au corespuns mai multe instanțe decât au fost returnate: restrângeți q sau măriți limit.
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Scope lipsă (scope_missing), API dezactivat pentru birou, licență expirată sau birou arhivat.
scope_missing), API dezactivat pentru birou, licență expirată sau birou arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl 'https://www.flowyer.ro/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.ro/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.ro/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())
Exemple de răspuns
{
"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": "Această cheie API nu are permisiunea \"courts:read\". Permisiunile unei chei existente nu pot fi modificate, așa că titularul cheii trebuie să creeze în Flowyer, la Setări > Chei API, o cheie nouă cu această permisiune și să o folosească în locul celei vechi.",
"locale": "ro",
"details": {
"required_scope": "courts:read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
HR
Listare concedii ale personalului
/api/agent/hr/leaves
Listează concediile aprobate ale personalului (cine este sau va fi în concediu): colegul, datele de început/sfârșit, numărul de zile lucrătoare, o categorie redactată pentru confidențialitate (leave/unpaid; boala este unificată în leave și niciodată identificabilă) și eventualul înlocuitor. Nu returnează niciodată tipul concediului, notele sau cine l-a aprobat.
Parametri de interogare
user_idDoar concediile acestui coleg. Un id central de utilizator (din colleagues.list), potrivit cu angajatul din spatele concediului.
1234on_dateCine este în concediu în această zi exactă (start_date <= on_date <= end_date). Când este setat, suprascrie date_from, date_to și timeframe.
date_fromDoar concediile care sunt încă în desfășurare la această dată sau după ea (end_date >= date_from). Implicit astăzi, astfel încât concediile complet trecute sunt excluse în mod implicit.
date_toDoar concediile care încep la această dată sau înainte de ea (start_date <= date_to). Omiteți pentru un viitor fără limită.
timeframeConstrângere suplimentară a datei de început față de astăzi: current = deja începute (în desfășurare), upcoming = încă neîncepute, all = fără constrângere suplimentară. Ignorată când on_date este setat.
"current" "upcoming" "all" "all"limitDimensiunea paginii, 1-100. Valoarea implicită este 25.
2525offsetNumărul de înregistrări de omis. Folosiți offset + limit ale paginii anterioare pentru a o obține pe următoarea; pagination.total este numărul total.
00Răspunsuri
200
OK.
dataobligatoriuCâmpurile data
idId-ul cererii de concediu (doar un identificator; nu este sensibil).
user_idColegul aflat în concediu (id central de utilizator).
userNumele afișat al colegului.
start_datePrima zi de concediu (YYYY-MM-DD).
end_dateUltima zi de concediu, inclusiv (YYYY-MM-DD).
days_countZile lucrătoare de concediu. Nu dezvăluie tipul.
categoryTipul de concediu redactat pentru confidențialitate: annual și sick devin ambele "leave" (boala nu este niciodată identificabilă), unpaid rămâne "unpaid". Tipul brut al concediului nu este niciodată expus.
"leave" "unpaid" statusÎntotdeauna "approved" - sunt returnate doar concediile aprobate; pending, rejected și cancelled nu apar niciodată.
"approved" substitute_user_idColegul care asigură înlocuirea pentru acest concediu (id central de utilizator), sau null.
substitute_userNumele afișat al colegului înlocuitor, sau null.
paginationobligatoriuCâmpurile pagination
limitobligatoriuoffsetobligatoriutotalobligatoriuNumărul total de înregistrări care se potrivesc.
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl 'https://www.flowyer.ro/api/agent/hr/leaves?user_id=1234&limit=25' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.ro/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.ro/api/agent/hr/leaves?user_id=1234&limit=25",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Exemple de răspuns
{
"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": "Această cheie API nu are permisiunea \"hr:read\". Permisiunile unei chei existente nu pot fi modificate, așa că titularul cheii trebuie să creeze în Flowyer, la Setări > Chei API, o cheie nouă cu această permisiune și să o folosească în locul celei vechi.",
"locale": "ro",
"details": {
"required_scope": "hr:read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Calendar
Listare evenimente de calendar
/api/agent/calendar/events
Listează evenimentele de calendar care se suprapun cu un interval de date [from, to]: calendarul biroului, cel propriu și calendarele partajate cu dumneavoastră. Evenimentele recurente sunt returnate o singură dată (is_recurring), NU extinse. Ordonate după start. Un eveniment personal nepartajat cu dumneavoastră nu apare niciodată.
Parametri de interogare
fromobligatoriuÎnceputul intervalului (inclusiv), ISO 8601. Sunt returnate evenimentele care se suprapun cu [from, to]. O oră fără offset este citită în fusul biroului.
"2026-03-01T00:00:00+01:00"toobligatoriuSfârșitul intervalului (inclusiv), ISO 8601. Trebuie să fie la from sau după el (altfel 422) și cel mult la 366 de zile după el.
"2026-03-31T23:59:59+01:00"calendar_idsRestrângeți la aceste id-uri de calendar container; fiecare este intersectat cu calendarele pe care le puteți vizualiza, astfel încât un id pe care nu îl puteți vedea este eliminat în tăcere. Omiteți pentru fiecare calendar vizibil.
include_recurringInclude evenimentele principale recurente a căror regulă se suprapune cu intervalul (returnate neextinse, is_recurring = true). Implicit true.
truelimitDimensiunea paginii, 1-100. Valoarea implicită este 25.
2525offsetNumărul de înregistrări de omis. Folosiți offset + limit ale paginii anterioare pentru a o obține pe următoarea; pagination.total este numărul total.
00Răspunsuri
200
OK.
dataobligatoriuCâmpurile data
id5501calendarCalendarul de care aparține evenimentul.
Câmpurile calendar
idId-ul calendarului container, sau null pentru calendarul partajat al biroului implicit (un eveniment mai vechi fără container).
nametype"office" = calendarul partajat al biroului (orice utilizator al biroului îl poate vizualiza și edita); "personal" = calendarul propriu al unui utilizator, vizibil doar pentru proprietarul lui și cei cu care este partajat.
"office" "personal" ownerProprietarul unui calendar personal; null pentru calendarul biroului.
Câmpurile owner
user_idnametitleTitlul evenimentului. Text simplu.
descriptionDescrierea evenimentului. Text simplu.
locationLocația. Text simplu.
participantsParticipanți, text liber. Text simplu.
startUn eveniment pe toată ziua: data de început "YYYY-MM-DD". Un eveniment cu oră: ISO 8601 în fusul orar al biroului (momentul UTC stocat).
"2026-03-02T09:00:00+01:00"endAceeași codificare ca start. Pentru un eveniment pe toată ziua, data de sfârșit este INCLUSIVĂ (valoarea stocată, nu valoarea +1 zi folosită de o grilă de calendar). Null când evenimentul nu are sfârșit.
all_dayTrue pentru un eveniment pe toată ziua (start/end sunt date simple); false pentru un eveniment cu oră (start/end sunt momente ISO 8601).
colorCuloarea de afișare, de exemplu "#2c7be5".
is_recurringTrue când evenimentul este un eveniment principal recurent. Evenimentele recurente sunt returnate o singură dată, NU extinse în apariții, și nu pot fi modificate prin calendar.events.update.
recurrenceRegula de recurență a unui eveniment principal recurent, sau null pentru un eveniment singular. Doar pentru citire.
Câmpurile recurrence
freqdaily | weekly | monthly | yearly.
intervalbyweekdayCoduri de zile ale săptămânii separate prin virgulă (de exemplu "MO,WE,FR").
untilcountcreated_byColegul care a creat evenimentul.
Câmpurile created_by
user_idnamecreated_atupdated_atTransmiteți aceasta către calendar.events.update ca expected_updated_at.
created_via_apiPrezent atunci când un agent extern a creat înregistrarea prin acest API.
Câmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduseratpaginationobligatoriuCâmpurile pagination
limitobligatoriuoffsetobligatoriutotalobligatoriuNumărul total de înregistrări care se potrivesc.
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl 'https://www.flowyer.ro/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.ro/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.ro/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())
Exemple de răspuns
{
"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": "Această cheie API nu are permisiunea \"calendar:read\". Permisiunile unei chei existente nu pot fi modificate, așa că titularul cheii trebuie să creeze în Flowyer, la Setări > Chei API, o cheie nouă cu această permisiune și să o folosească în locul celei vechi.",
"locale": "ro",
"details": {
"required_scope": "calendar:read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Obținere eveniment de calendar
/api/agent/calendar/events/{id}
Returnează un eveniment de calendar cu calendarul său, rezumatul recurenței și tokenul de blocare updated_at pentru calendar.events.update. Răspunde cu 404 când evenimentul nu există sau calendarul său nu este vizibil pentru utilizator.
Parametri de cale
idobligatoriuId-ul evenimentului.
5501Răspunsuri
200
OK.
dataobligatoriuCâmpurile data
id5501calendarCalendarul de care aparține evenimentul.
Câmpurile calendar
idId-ul calendarului container, sau null pentru calendarul partajat al biroului implicit (un eveniment mai vechi fără container).
nametype"office" = calendarul partajat al biroului (orice utilizator al biroului îl poate vizualiza și edita); "personal" = calendarul propriu al unui utilizator, vizibil doar pentru proprietarul lui și cei cu care este partajat.
"office" "personal" ownerProprietarul unui calendar personal; null pentru calendarul biroului.
Câmpurile owner
user_idnametitleTitlul evenimentului. Text simplu.
descriptionDescrierea evenimentului. Text simplu.
locationLocația. Text simplu.
participantsParticipanți, text liber. Text simplu.
startUn eveniment pe toată ziua: data de început "YYYY-MM-DD". Un eveniment cu oră: ISO 8601 în fusul orar al biroului (momentul UTC stocat).
"2026-03-02T09:00:00+01:00"endAceeași codificare ca start. Pentru un eveniment pe toată ziua, data de sfârșit este INCLUSIVĂ (valoarea stocată, nu valoarea +1 zi folosită de o grilă de calendar). Null când evenimentul nu are sfârșit.
all_dayTrue pentru un eveniment pe toată ziua (start/end sunt date simple); false pentru un eveniment cu oră (start/end sunt momente ISO 8601).
colorCuloarea de afișare, de exemplu "#2c7be5".
is_recurringTrue când evenimentul este un eveniment principal recurent. Evenimentele recurente sunt returnate o singură dată, NU extinse în apariții, și nu pot fi modificate prin calendar.events.update.
recurrenceRegula de recurență a unui eveniment principal recurent, sau null pentru un eveniment singular. Doar pentru citire.
Câmpurile recurrence
freqdaily | weekly | monthly | yearly.
intervalbyweekdayCoduri de zile ale săptămânii separate prin virgulă (de exemplu "MO,WE,FR").
untilcountcreated_byColegul care a creat evenimentul.
Câmpurile created_by
user_idnamecreated_atupdated_atTransmiteți aceasta către calendar.events.update ca expected_updated_at.
created_via_apiPrezent atunci când un agent extern a creat înregistrarea prin acest API.
Câmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduserat
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl 'https://www.flowyer.ro/api/agent/calendar/events/5501' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.ro/api/agent/calendar/events/5501", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.ro/api/agent/calendar/events/5501",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Exemple de răspuns
{
"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": "Înregistrarea nu a fost găsită sau nu este vizibilă pentru titularul acestei chei API.",
"locale": "ro",
"details": {
"record_type": "calendar_event",
"record_id": 5501
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Creare eveniment de calendar
/api/agent/calendar/events
Creează un singur eveniment de calendar (cu oră sau pe toată ziua) în calendarul biroului sau într-un calendar pe care îl puteți edita. Un start/end cu oră respectă un offset ISO 8601, o oră naivă este citită în fusul biroului; o dată de sfârșit pe toată ziua este inclusivă. Evenimentele recurente nu sunt create aici. Nu sunt transmise către calendare externe.
Parametri de antet
Idempotency-KeyRecomandat la fiecare creare. O valoare unică per operație logică (de exemplu un UUID). Aceeași valoare returnează aceeași înregistrare: reîncercarea cu ea returnează înregistrarea creată prima dată, în loc să creeze o a doua. Valori diferite creează întotdeauna înregistrări diferite. Clienții care nu pot trimite anteturi pot transmite aceeași valoare în câmpul de corp idempotency_key. Litere, cifre, _, -, : sau ., cel mult 128 de caractere.
^[A-Za-z0-9_\-:.]{1,128}$Corpul cererii application/json
titleobligatoriuTitlul evenimentului. Text simplu; "<" și ">" nu sunt permise (acesta trece neescapat în notificarea de memento).
^[^<>]*$"Ügyfél egyeztetés"startobligatoriuPe toată ziua (all_day true): o dată "YYYY-MM-DD". Cu oră (all_day false): ISO 8601; un offset este respectat, o oră naivă este citită în fusul biroului.
"2026-03-02T09:00:00+01:00"endAceeași codificare ca start. Implicit = start. Pentru un eveniment pe toată ziua, data de sfârșit este INCLUSIVĂ. Nu trebuie să fie înainte de start (altfel 422).
all_dayDacă evenimentul este pe toată ziua. Implicit false (cu oră).
falsecalendar_idCalendarul container țintă; implicit = calendarul biroului. Trebuie să dețineți drepturi de editare asupra lui (altfel 403). Doar pe un tenant cu funcția de calendar personal.
locationLocația. Text simplu; "<" și ">" nu sunt permise.
^[^<>]*$descriptionDescriere, text simplu (nu HTML); "<" și ">" nu sunt permise.
^[^<>]*$participantsParticipanți, text liber. Text simplu; "<" și ">" nu sunt permise.
^[^<>]*$colorCuloarea de afișare, de exemplu "#2c7be5".
^#?[A-Za-z0-9_-]{1,31}$idempotency_keyAcelași rol ca antetul Idempotency-Key, pentru clienții care nu pot trimite anteturi personalizate. Litere, cifre, _, -, : sau ., cel mult 128 de caractere.
^[A-Za-z0-9_\-:.]{1,128}$"b8f1c2e0-6f7a-4d2e-9c1b-2a3d4e5f6a7b"Răspunsuri
201
Creat.
dataobligatoriuCâmpurile data
id5501calendarCalendarul de care aparține evenimentul.
Câmpurile calendar
idId-ul calendarului container, sau null pentru calendarul partajat al biroului implicit (un eveniment mai vechi fără container).
nametype"office" = calendarul partajat al biroului (orice utilizator al biroului îl poate vizualiza și edita); "personal" = calendarul propriu al unui utilizator, vizibil doar pentru proprietarul lui și cei cu care este partajat.
"office" "personal" ownerProprietarul unui calendar personal; null pentru calendarul biroului.
Câmpurile owner
user_idnametitleTitlul evenimentului. Text simplu.
descriptionDescrierea evenimentului. Text simplu.
locationLocația. Text simplu.
participantsParticipanți, text liber. Text simplu.
startUn eveniment pe toată ziua: data de început "YYYY-MM-DD". Un eveniment cu oră: ISO 8601 în fusul orar al biroului (momentul UTC stocat).
"2026-03-02T09:00:00+01:00"endAceeași codificare ca start. Pentru un eveniment pe toată ziua, data de sfârșit este INCLUSIVĂ (valoarea stocată, nu valoarea +1 zi folosită de o grilă de calendar). Null când evenimentul nu are sfârșit.
all_dayTrue pentru un eveniment pe toată ziua (start/end sunt date simple); false pentru un eveniment cu oră (start/end sunt momente ISO 8601).
colorCuloarea de afișare, de exemplu "#2c7be5".
is_recurringTrue când evenimentul este un eveniment principal recurent. Evenimentele recurente sunt returnate o singură dată, NU extinse în apariții, și nu pot fi modificate prin calendar.events.update.
recurrenceRegula de recurență a unui eveniment principal recurent, sau null pentru un eveniment singular. Doar pentru citire.
Câmpurile recurrence
freqdaily | weekly | monthly | yearly.
intervalbyweekdayCoduri de zile ale săptămânii separate prin virgulă (de exemplu "MO,WE,FR").
untilcountcreated_byColegul care a creat evenimentul.
Câmpurile created_by
user_idnamecreated_atupdated_atTransmiteți aceasta către calendar.events.update ca expected_updated_at.
created_via_apiPrezent atunci când un agent extern a creat înregistrarea prin acest API.
Câmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduseratcreatedtrue
200
Reluare idempotentă: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică în interval de 120 de secunde) a creat deja înregistrarea; aceasta este returnată din nou, nu s-a creat nimic nou.
dataobligatoriuCâmpurile data
id5501calendarCalendarul de care aparține evenimentul.
Câmpurile calendar
idId-ul calendarului container, sau null pentru calendarul partajat al biroului implicit (un eveniment mai vechi fără container).
nametype"office" = calendarul partajat al biroului (orice utilizator al biroului îl poate vizualiza și edita); "personal" = calendarul propriu al unui utilizator, vizibil doar pentru proprietarul lui și cei cu care este partajat.
"office" "personal" ownerProprietarul unui calendar personal; null pentru calendarul biroului.
Câmpurile owner
user_idnametitleTitlul evenimentului. Text simplu.
descriptionDescrierea evenimentului. Text simplu.
locationLocația. Text simplu.
participantsParticipanți, text liber. Text simplu.
startUn eveniment pe toată ziua: data de început "YYYY-MM-DD". Un eveniment cu oră: ISO 8601 în fusul orar al biroului (momentul UTC stocat).
"2026-03-02T09:00:00+01:00"endAceeași codificare ca start. Pentru un eveniment pe toată ziua, data de sfârșit este INCLUSIVĂ (valoarea stocată, nu valoarea +1 zi folosită de o grilă de calendar). Null când evenimentul nu are sfârșit.
all_dayTrue pentru un eveniment pe toată ziua (start/end sunt date simple); false pentru un eveniment cu oră (start/end sunt momente ISO 8601).
colorCuloarea de afișare, de exemplu "#2c7be5".
is_recurringTrue când evenimentul este un eveniment principal recurent. Evenimentele recurente sunt returnate o singură dată, NU extinse în apariții, și nu pot fi modificate prin calendar.events.update.
recurrenceRegula de recurență a unui eveniment principal recurent, sau null pentru un eveniment singular. Doar pentru citire.
Câmpurile recurrence
freqdaily | weekly | monthly | yearly.
intervalbyweekdayCoduri de zile ale săptămânii separate prin virgulă (de exemplu "MO,WE,FR").
untilcountcreated_byColegul care a creat evenimentul.
Câmpurile created_by
user_idnamecreated_atupdated_atTransmiteți aceasta către calendar.events.update ca expected_updated_at.
created_via_apiPrezent atunci când un agent extern a creat înregistrarea prin acest API.
Câmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduseratcreatedfalseidempotent_replaytrue
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator. replay_not_visible: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică) a creat deja înregistrarea (details.record_id), dar aceasta a fost între timp ștearsă sau nu este vizibilă pentru utilizator; nu s-a creat nimic nou, nu o creați din nou.
replay_not_visible: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică) a creat deja înregistrarea (details.record_id), dar aceasta a fost între timp ștearsă sau nu este vizibilă pentru utilizator; nu s-a creat nimic nou, nu o creați din nou.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
409
Idempotency-Key a fost folosit pentru alt tip de resursă (idempotency_key_reused) sau, în lipsa unei chei, o cerere identică este procesată chiar acum (duplicate_in_progress; reîncercați în scurt timp).
idempotency_key_reused) sau, în lipsa unei chei, o cerere identică este procesată chiar acum (duplicate_in_progress; reîncercați în scurt timp).
413
Corpul cererii este prea mare (request_too_large).
request_too_large).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl -X POST 'https://www.flowyer.ro/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.ro/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.ro/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"
}
Exemple de răspuns
{
"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": "Cererea nu este validă. Erorile pe câmpuri se găsesc în \"details.fields\".",
"locale": "ro",
"details": {
"fields": {
"title": [
"Câmpul title este obligatoriu."
]
}
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Actualizare eveniment de calendar
/api/agent/calendar/events/{id}
Actualizează un singur eveniment de calendar: titlul, start/end, all_day, locația, descrierea, participanții, culoarea. Scrie doar câmpurile pe care le trimiteți; "" șterge location/description/participants. Un eveniment recurent răspunde cu 422. Transmiteți expected_updated_at din ultima citire; o modificare conflictuală răspunde cu 409.
Parametri de cale
idobligatoriuId-ul înregistrării de modificat.
Corpul cererii application/json
expected_updated_atValoarea updated_at din cea mai recentă citire a acestei înregistrări (obligatorie ori de câte ori înregistrarea are una). Dacă înregistrarea s-a schimbat între timp (un coleg a editat-o), API-ul răspunde cu 409 și trebuie să o recitiți înainte de a reîncerca. O înregistrare veche al cărei updated_at este null acceptă null.
titleTitlu nou. Text simplu; "<" și ">" nu sunt permise.
^[^<>]*$startStart nou. Pe toată ziua: "YYYY-MM-DD". Cu oră: ISO 8601 (un offset respectat, o oră naivă citită în fusul biroului). Recodificat dacă all_day se schimbă.
endEnd nou, aceeași codificare ca start; "" îl șterge. Pentru un eveniment pe toată ziua, data de sfârșit este inclusivă. Nu trebuie să fie înainte de start (altfel 422).
all_dayDacă este trimis, start/end sunt recodificate în consecință; dacă este omis, se folosește all_day curent al rândului.
locationLocația. Text simplu; "<" și ">" nu sunt permise. "" o șterge.
^[^<>]*$descriptionDescriere, text simplu (nu HTML); "<" și ">" nu sunt permise. "" o șterge.
^[^<>]*$participantsParticipanți, text liber. Text simplu; "<" și ">" nu sunt permise. "" îi șterge.
^[^<>]*$colorCuloarea de afișare, de exemplu "#2c7be5". "" o șterge.
^#?[A-Za-z0-9_-]{1,31}$Răspunsuri
200
Actualizat.
dataobligatoriuCâmpurile data
id5501calendarCalendarul de care aparține evenimentul.
Câmpurile calendar
idId-ul calendarului container, sau null pentru calendarul partajat al biroului implicit (un eveniment mai vechi fără container).
nametype"office" = calendarul partajat al biroului (orice utilizator al biroului îl poate vizualiza și edita); "personal" = calendarul propriu al unui utilizator, vizibil doar pentru proprietarul lui și cei cu care este partajat.
"office" "personal" ownerProprietarul unui calendar personal; null pentru calendarul biroului.
Câmpurile owner
user_idnametitleTitlul evenimentului. Text simplu.
descriptionDescrierea evenimentului. Text simplu.
locationLocația. Text simplu.
participantsParticipanți, text liber. Text simplu.
startUn eveniment pe toată ziua: data de început "YYYY-MM-DD". Un eveniment cu oră: ISO 8601 în fusul orar al biroului (momentul UTC stocat).
"2026-03-02T09:00:00+01:00"endAceeași codificare ca start. Pentru un eveniment pe toată ziua, data de sfârșit este INCLUSIVĂ (valoarea stocată, nu valoarea +1 zi folosită de o grilă de calendar). Null când evenimentul nu are sfârșit.
all_dayTrue pentru un eveniment pe toată ziua (start/end sunt date simple); false pentru un eveniment cu oră (start/end sunt momente ISO 8601).
colorCuloarea de afișare, de exemplu "#2c7be5".
is_recurringTrue când evenimentul este un eveniment principal recurent. Evenimentele recurente sunt returnate o singură dată, NU extinse în apariții, și nu pot fi modificate prin calendar.events.update.
recurrenceRegula de recurență a unui eveniment principal recurent, sau null pentru un eveniment singular. Doar pentru citire.
Câmpurile recurrence
freqdaily | weekly | monthly | yearly.
intervalbyweekdayCoduri de zile ale săptămânii separate prin virgulă (de exemplu "MO,WE,FR").
untilcountcreated_byColegul care a creat evenimentul.
Câmpurile created_by
user_idnamecreated_atupdated_atTransmiteți aceasta către calendar.events.update ca expected_updated_at.
created_via_apiPrezent atunci când un agent extern a creat înregistrarea prin acest API.
Câmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduseratupdatedtrue
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
409
Înregistrarea s-a schimbat de când ați citit-o (record_conflict: expected_updated_at nu mai corespunde; citiți-o din nou și reîncercați cu noul updated_at).
record_conflict: expected_updated_at nu mai corespunde; citiți-o din nou și reîncercați cu noul updated_at).
413
Corpul cererii este prea mare (request_too_large).
request_too_large).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl -X PATCH 'https://www.flowyer.ro/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.ro/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.ro/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"
}
Exemple de răspuns
{
"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": "Înregistrarea s-a modificat de când ați citit-o (cineva a editat-o). Citiți-o din nou și reîncercați cu noua valoare updated_at.",
"locale": "ro",
"details": {
"current_updated_at": "2026-10-30T10:42:05+01:00",
"reason": "modified_since_read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Programări
Listare programări
/api/agent/bookings
Listează programările (időpontfoglalások) biroului, cele mai noi primele. Opțional filtrate după un interval de zile from/to (fusul orar al programării), un avocat (user_id), un status sau updated_since. Fiecare deținător de cheie vede programările tuturor avocaților.
Parametri de interogare
fromDoar programările din această zi sau ulterioare (YYYY-MM-DD), comparate literal cu data în fusul programării.
"2026-01-01"toDoar programările din această zi sau anterioare (YYYY-MM-DD).
"2026-12-31"user_idFiltrați la un singur avocat (user_id din colleagues.list). Omiteți pentru fiecare avocat al biroului.
statusFiltrați după status.
"pending" "confirmed" "cancelled" "completed" "awaiting_payment" "expired" updated_sinceDoar programările modificate la acest moment ISO 8601 sau după el (updated_at este o valoare naivă, în fusul biroului).
limitDimensiunea paginii, 1-100. Valoarea implicită este 25.
2525offsetNumărul de înregistrări de omis. Folosiți offset + limit ale paginii anterioare pentru a o obține pe următoarea; pagination.total este numărul total.
00Răspunsuri
200
OK.
dataobligatoriuCâmpurile data
id4321booking_numberNumărul lizibil al programării, de exemplu "#B-0001".
statuspending = așteaptă confirmarea avocatului; confirmed = aprobată; cancelled/completed; awaiting_payment/expired aparțin fluxului de plată înainte de confirmare.
"pending" "confirmed" "cancelled" "completed" "awaiting_payment" "expired" sourceDe unde provine programarea. O programare creată prin API este "manual".
"flowyer" "website" "embed_widget" "manual" lawyerAvocatul (user_id din colleagues.list) cu care este programarea.
Câmpurile lawyer
user_idnamedateData calendaristică în fusul orar al programării (YYYY-MM-DD), stocată literal.
start_timeOra de început HH:MM în fusul orar al programării.
end_timeOra de sfârșit HH:MM în fusul orar al programării.
startMomentul ISO 8601 neambiguu al începutului, compus cu fusul orar al programării. Folosiți-l pentru a compara momente între fusuri.
endMomentul ISO 8601 neambiguu al sfârșitului.
timezoneFusul orar al programării (booking_settings.timezone), de exemplu "Europe/Budapest". Acesta guvernează date, start_time și end_time.
location_preferenceDacă consultația are loc la birou sau online.
"office" "online" meeting_linkURL-ul întâlnirii online, când este setat.
clientClientul extern care a făcut programarea: nume, e-mail, telefon și obiectul/notele. Date cu caracter personal - doar pentru personalul biroului.
Câmpurile client
nameemailphonedescriptiongdpr_consentDacă este înregistrat consimțământul clientului privind prelucrarea datelor.
gdpr_consent_atCând a fost înregistrat consimțământul.
cancel_reasonMotivul înregistrat la anulare.
paymentStarea de plată, doar pentru citire. API-ul nu modifică niciodată plata; taxele de programare sunt gestionate în Flowyer.
Câmpurile payment
status"none" "awaiting" "partial" "paid" "refunded" method"card" "transfer" amountcurrencyinvoice_numberconfirmed_atcancelled_atcreated_atupdated_atTransmiteți aceasta către bookings.update / bookings.confirm / bookings.cancel ca expected_updated_at.
created_via_apiPrezent atunci când un agent extern a creat programarea prin acest API.
Câmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduseratpaginationobligatoriuCâmpurile pagination
limitobligatoriuoffsetobligatoriutotalobligatoriuNumărul total de înregistrări care se potrivesc.
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Scope lipsă (scope_missing), API dezactivat pentru birou, licență expirată sau birou arhivat.
scope_missing), API dezactivat pentru birou, licență expirată sau birou arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl 'https://www.flowyer.ro/api/agent/bookings?from=2026-01-01&to=2026-12-31&limit=25' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.ro/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.ro/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())
Exemple de răspuns
{
"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": "Această cheie API nu are permisiunea \"bookings:read\". Permisiunile unei chei existente nu pot fi modificate, așa că titularul cheii trebuie să creeze în Flowyer, la Setări > Chei API, o cheie nouă cu această permisiune și să o folosească în locul celei vechi.",
"locale": "ro",
"details": {
"required_scope": "bookings:read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Obținere programare
/api/agent/bookings/{id}
Returnează o programare cu avocatul, detaliile clientului, momentele de început/sfârșit, starea de plată și tokenul de blocare updated_at pentru bookings.update / .confirm / .cancel. Răspunde cu 404 când programarea nu există în acest birou.
Parametri de cale
idobligatoriuId-ul programării.
4321Răspunsuri
200
OK.
dataobligatoriuCâmpurile data
id4321booking_numberNumărul lizibil al programării, de exemplu "#B-0001".
statuspending = așteaptă confirmarea avocatului; confirmed = aprobată; cancelled/completed; awaiting_payment/expired aparțin fluxului de plată înainte de confirmare.
"pending" "confirmed" "cancelled" "completed" "awaiting_payment" "expired" sourceDe unde provine programarea. O programare creată prin API este "manual".
"flowyer" "website" "embed_widget" "manual" lawyerAvocatul (user_id din colleagues.list) cu care este programarea.
Câmpurile lawyer
user_idnamedateData calendaristică în fusul orar al programării (YYYY-MM-DD), stocată literal.
start_timeOra de început HH:MM în fusul orar al programării.
end_timeOra de sfârșit HH:MM în fusul orar al programării.
startMomentul ISO 8601 neambiguu al începutului, compus cu fusul orar al programării. Folosiți-l pentru a compara momente între fusuri.
endMomentul ISO 8601 neambiguu al sfârșitului.
timezoneFusul orar al programării (booking_settings.timezone), de exemplu "Europe/Budapest". Acesta guvernează date, start_time și end_time.
location_preferenceDacă consultația are loc la birou sau online.
"office" "online" meeting_linkURL-ul întâlnirii online, când este setat.
clientClientul extern care a făcut programarea: nume, e-mail, telefon și obiectul/notele. Date cu caracter personal - doar pentru personalul biroului.
Câmpurile client
nameemailphonedescriptiongdpr_consentDacă este înregistrat consimțământul clientului privind prelucrarea datelor.
gdpr_consent_atCând a fost înregistrat consimțământul.
cancel_reasonMotivul înregistrat la anulare.
paymentStarea de plată, doar pentru citire. API-ul nu modifică niciodată plata; taxele de programare sunt gestionate în Flowyer.
Câmpurile payment
status"none" "awaiting" "partial" "paid" "refunded" method"card" "transfer" amountcurrencyinvoice_numberconfirmed_atcancelled_atcreated_atupdated_atTransmiteți aceasta către bookings.update / bookings.confirm / bookings.cancel ca expected_updated_at.
created_via_apiPrezent atunci când un agent extern a creat programarea prin acest API.
Câmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduserat
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Scope lipsă (scope_missing), API dezactivat pentru birou, licență expirată sau birou arhivat.
scope_missing), API dezactivat pentru birou, licență expirată sau birou arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl 'https://www.flowyer.ro/api/agent/bookings/4321' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.ro/api/agent/bookings/4321", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.ro/api/agent/bookings/4321",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Exemple de răspuns
{
"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": "Înregistrarea nu a fost găsită sau nu este vizibilă pentru titularul acestei chei API.",
"locale": "ro",
"details": {
"record_type": "booking",
"record_id": 4321
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Creare programare
/api/agent/bookings
Rezervă o programare și TRIMITE UN E-MAIL CLIENTULUI cu confirmarea. Necesită un interval liber pentru avocat (altfel 409); calendarul biroului nu blochează niciodată. source este "manual". O reluare cu Idempotency-Key nici nu reprogramează, nici nu retrimite e-mailul.
Parametri de antet
Idempotency-KeyRecomandat la fiecare creare. O valoare unică per operație logică (de exemplu un UUID). Aceeași valoare returnează aceeași înregistrare: reîncercarea cu ea returnează înregistrarea creată prima dată, în loc să creeze o a doua. Valori diferite creează întotdeauna înregistrări diferite. Clienții care nu pot trimite anteturi pot transmite aceeași valoare în câmpul de corp idempotency_key. Litere, cifre, _, -, : sau ., cel mult 128 de caractere.
^[A-Za-z0-9_\-:.]{1,128}$Corpul cererii application/json
user_idobligatoriuAvocatul cu care este programarea (user_id din colleagues.list; trebuie să fie un coleg activ al biroului).
42dateobligatoriuZiua programării (YYYY-MM-DD) în fusul orar al programării.
"2026-03-02"timeobligatoriuOra de început HH:MM (24h) în fusul orar al programării. Ora de sfârșit este time + durata intervalului biroului. Trebuie să fie un interval liber.
^([01]\d|2[0-3]):[0-5]\d$"09:00"client_nameobligatoriuNumele clientului. Text simplu; "<" și ">" nu sunt permise.
^[^<>]*$"Kovács Anna"client_emailobligatoriuE-mailul clientului: destinatarul confirmării.
"anna@example.com"client_phoneTelefonul clientului. Text simplu.
^[^<>]*$client_descriptionObiectul / notele de la client. Text simplu.
^[^<>]*$location_preferenceConsultație la birou sau online. Implicit "office".
"office" "online" "office"meeting_linkURL-ul întâlnirii online (http/https), pentru o consultație online.
gdpr_consentÎnregistrează consimțământul clientului privind prelucrarea datelor. Implicit true (personalul biroului face programarea în numele clientului).
trueauto_confirmCând este true (sau biroul are confirmarea automată activată), creează programarea deja confirmată: rulează sincronizarea calendarului și trimite clientului o confirmare în loc de o cerere. În caz contrar, aceasta este pending.
falseidempotency_keyAcelași rol ca antetul Idempotency-Key, pentru clienții care nu pot trimite anteturi personalizate. Litere, cifre, _, -, : sau ., cel mult 128 de caractere.
^[A-Za-z0-9_\-:.]{1,128}$"b8f1c2e0-6f7a-4d2e-9c1b-2a3d4e5f6a7b"Răspunsuri
201
Creat.
dataobligatoriuCâmpurile data
id4321booking_numberNumărul lizibil al programării, de exemplu "#B-0001".
statuspending = așteaptă confirmarea avocatului; confirmed = aprobată; cancelled/completed; awaiting_payment/expired aparțin fluxului de plată înainte de confirmare.
"pending" "confirmed" "cancelled" "completed" "awaiting_payment" "expired" sourceDe unde provine programarea. O programare creată prin API este "manual".
"flowyer" "website" "embed_widget" "manual" lawyerAvocatul (user_id din colleagues.list) cu care este programarea.
Câmpurile lawyer
user_idnamedateData calendaristică în fusul orar al programării (YYYY-MM-DD), stocată literal.
start_timeOra de început HH:MM în fusul orar al programării.
end_timeOra de sfârșit HH:MM în fusul orar al programării.
startMomentul ISO 8601 neambiguu al începutului, compus cu fusul orar al programării. Folosiți-l pentru a compara momente între fusuri.
endMomentul ISO 8601 neambiguu al sfârșitului.
timezoneFusul orar al programării (booking_settings.timezone), de exemplu "Europe/Budapest". Acesta guvernează date, start_time și end_time.
location_preferenceDacă consultația are loc la birou sau online.
"office" "online" meeting_linkURL-ul întâlnirii online, când este setat.
clientClientul extern care a făcut programarea: nume, e-mail, telefon și obiectul/notele. Date cu caracter personal - doar pentru personalul biroului.
Câmpurile client
nameemailphonedescriptiongdpr_consentDacă este înregistrat consimțământul clientului privind prelucrarea datelor.
gdpr_consent_atCând a fost înregistrat consimțământul.
cancel_reasonMotivul înregistrat la anulare.
paymentStarea de plată, doar pentru citire. API-ul nu modifică niciodată plata; taxele de programare sunt gestionate în Flowyer.
Câmpurile payment
status"none" "awaiting" "partial" "paid" "refunded" method"card" "transfer" amountcurrencyinvoice_numberconfirmed_atcancelled_atcreated_atupdated_atTransmiteți aceasta către bookings.update / bookings.confirm / bookings.cancel ca expected_updated_at.
created_via_apiPrezent atunci când un agent extern a creat programarea prin acest API.
Câmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduseratcreatedtrue
200
Reluare idempotentă: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică în interval de 120 de secunde) a creat deja înregistrarea; aceasta este returnată din nou, nu s-a creat nimic nou.
dataobligatoriuCâmpurile data
id4321booking_numberNumărul lizibil al programării, de exemplu "#B-0001".
statuspending = așteaptă confirmarea avocatului; confirmed = aprobată; cancelled/completed; awaiting_payment/expired aparțin fluxului de plată înainte de confirmare.
"pending" "confirmed" "cancelled" "completed" "awaiting_payment" "expired" sourceDe unde provine programarea. O programare creată prin API este "manual".
"flowyer" "website" "embed_widget" "manual" lawyerAvocatul (user_id din colleagues.list) cu care este programarea.
Câmpurile lawyer
user_idnamedateData calendaristică în fusul orar al programării (YYYY-MM-DD), stocată literal.
start_timeOra de început HH:MM în fusul orar al programării.
end_timeOra de sfârșit HH:MM în fusul orar al programării.
startMomentul ISO 8601 neambiguu al începutului, compus cu fusul orar al programării. Folosiți-l pentru a compara momente între fusuri.
endMomentul ISO 8601 neambiguu al sfârșitului.
timezoneFusul orar al programării (booking_settings.timezone), de exemplu "Europe/Budapest". Acesta guvernează date, start_time și end_time.
location_preferenceDacă consultația are loc la birou sau online.
"office" "online" meeting_linkURL-ul întâlnirii online, când este setat.
clientClientul extern care a făcut programarea: nume, e-mail, telefon și obiectul/notele. Date cu caracter personal - doar pentru personalul biroului.
Câmpurile client
nameemailphonedescriptiongdpr_consentDacă este înregistrat consimțământul clientului privind prelucrarea datelor.
gdpr_consent_atCând a fost înregistrat consimțământul.
cancel_reasonMotivul înregistrat la anulare.
paymentStarea de plată, doar pentru citire. API-ul nu modifică niciodată plata; taxele de programare sunt gestionate în Flowyer.
Câmpurile payment
status"none" "awaiting" "partial" "paid" "refunded" method"card" "transfer" amountcurrencyinvoice_numberconfirmed_atcancelled_atcreated_atupdated_atTransmiteți aceasta către bookings.update / bookings.confirm / bookings.cancel ca expected_updated_at.
created_via_apiPrezent atunci când un agent extern a creat programarea prin acest API.
Câmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduseratcreatedfalseidempotent_replaytrue
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Scope lipsă (scope_missing), API dezactivat pentru birou, licență expirată sau birou arhivat.
scope_missing), API dezactivat pentru birou, licență expirată sau birou arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator. replay_not_visible: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică) a creat deja înregistrarea (details.record_id), dar aceasta a fost între timp ștearsă sau nu este vizibilă pentru utilizator; nu s-a creat nimic nou, nu o creați din nou.
replay_not_visible: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică) a creat deja înregistrarea (details.record_id), dar aceasta a fost între timp ștearsă sau nu este vizibilă pentru utilizator; nu s-a creat nimic nou, nu o creați din nou.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
409
Idempotency-Key a fost folosit pentru alt tip de resursă (idempotency_key_reused) sau, în lipsa unei chei, o cerere identică este procesată chiar acum (duplicate_in_progress; reîncercați în scurt timp).
idempotency_key_reused) sau, în lipsa unei chei, o cerere identică este procesată chiar acum (duplicate_in_progress; reîncercați în scurt timp).
413
Corpul cererii este prea mare (request_too_large).
request_too_large).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl -X POST 'https://www.flowyer.ro/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.ro/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.ro/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"
}
Exemple de răspuns
{
"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": "Cererea nu este validă. Erorile pe câmpuri se găsesc în \"details.fields\".",
"locale": "ro",
"details": {
"fields": {
"user_id": [
"Câmpul user id este obligatoriu."
]
}
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Actualizare programare
/api/agent/bookings/{id}
Reprogramează (date + time împreună, reverificate pentru un interval liber) sau editează o programare (telefon, note, link de întâlnire, locație). Scrie doar câmpurile pe care le trimiteți. Notifică avocatul despre o reprogramare, niciodată clientul. Transmiteți expected_updated_at din ultima citire; o scriere învechită răspunde cu 409.
Parametri de cale
idobligatoriuId-ul înregistrării de modificat.
Corpul cererii application/json
expected_updated_atValoarea updated_at din cea mai recentă citire a acestei înregistrări (obligatorie ori de câte ori înregistrarea are una). Dacă înregistrarea s-a schimbat între timp (un coleg a editat-o), API-ul răspunde cu 409 și trebuie să o recitiți înainte de a reîncerca. O înregistrare veche al cărei updated_at este null acceptă null.
dateZiua nouă (YYYY-MM-DD) în fusul orar al programării. Trimiteți date ȘI time împreună pentru a reprograma.
"2026-03-05"timeNoua oră de început HH:MM. Ora de sfârșit este recalculată din durata intervalului biroului. Trimiteți date ȘI time împreună.
^([01]\d|2[0-3]):[0-5]\d$"11:00"client_phoneTelefonul clientului. Text simplu. "" îl șterge.
^[^<>]*$client_descriptionObiectul / notele. Text simplu. "" le șterge.
^[^<>]*$meeting_linkURL-ul întâlnirii online (http/https). "" îl șterge.
location_preferenceConsultație la birou sau online.
"office" "online" Răspunsuri
200
Actualizat.
dataobligatoriuCâmpurile data
id4321booking_numberNumărul lizibil al programării, de exemplu "#B-0001".
statuspending = așteaptă confirmarea avocatului; confirmed = aprobată; cancelled/completed; awaiting_payment/expired aparțin fluxului de plată înainte de confirmare.
"pending" "confirmed" "cancelled" "completed" "awaiting_payment" "expired" sourceDe unde provine programarea. O programare creată prin API este "manual".
"flowyer" "website" "embed_widget" "manual" lawyerAvocatul (user_id din colleagues.list) cu care este programarea.
Câmpurile lawyer
user_idnamedateData calendaristică în fusul orar al programării (YYYY-MM-DD), stocată literal.
start_timeOra de început HH:MM în fusul orar al programării.
end_timeOra de sfârșit HH:MM în fusul orar al programării.
startMomentul ISO 8601 neambiguu al începutului, compus cu fusul orar al programării. Folosiți-l pentru a compara momente între fusuri.
endMomentul ISO 8601 neambiguu al sfârșitului.
timezoneFusul orar al programării (booking_settings.timezone), de exemplu "Europe/Budapest". Acesta guvernează date, start_time și end_time.
location_preferenceDacă consultația are loc la birou sau online.
"office" "online" meeting_linkURL-ul întâlnirii online, când este setat.
clientClientul extern care a făcut programarea: nume, e-mail, telefon și obiectul/notele. Date cu caracter personal - doar pentru personalul biroului.
Câmpurile client
nameemailphonedescriptiongdpr_consentDacă este înregistrat consimțământul clientului privind prelucrarea datelor.
gdpr_consent_atCând a fost înregistrat consimțământul.
cancel_reasonMotivul înregistrat la anulare.
paymentStarea de plată, doar pentru citire. API-ul nu modifică niciodată plata; taxele de programare sunt gestionate în Flowyer.
Câmpurile payment
status"none" "awaiting" "partial" "paid" "refunded" method"card" "transfer" amountcurrencyinvoice_numberconfirmed_atcancelled_atcreated_atupdated_atTransmiteți aceasta către bookings.update / bookings.confirm / bookings.cancel ca expected_updated_at.
created_via_apiPrezent atunci când un agent extern a creat programarea prin acest API.
Câmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduseratupdatedtrue
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Scope lipsă (scope_missing), API dezactivat pentru birou, licență expirată sau birou arhivat.
scope_missing), API dezactivat pentru birou, licență expirată sau birou arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
409
Înregistrarea s-a schimbat de când ați citit-o (record_conflict: expected_updated_at nu mai corespunde; citiți-o din nou și reîncercați cu noul updated_at).
record_conflict: expected_updated_at nu mai corespunde; citiți-o din nou și reîncercați cu noul updated_at).
413
Corpul cererii este prea mare (request_too_large).
request_too_large).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl -X PATCH 'https://www.flowyer.ro/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.ro/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.ro/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"
}
Exemple de răspuns
{
"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": "Înregistrarea s-a modificat de când ați citit-o (cineva a editat-o). Citiți-o din nou și reîncercați cu noua valoare updated_at.",
"locale": "ro",
"details": {
"current_updated_at": "2026-10-30T10:42:05+01:00",
"reason": "modified_since_read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Confirmare programare
/api/agent/bookings/{id}/confirm
Confirmă o programare pending și TRIMITE UN E-MAIL CLIENTULUI cu confirmarea (cu linkul de întâlnire pentru una online). Doar o programare pending poate fi confirmată; orice alt status răspunde cu 409, astfel încât o reîncercare nu retrimite niciodată e-mailul. Opțional, transmiteți expected_updated_at ca token de blocare.
Parametri de cale
idobligatoriuId-ul programării.
4321Corpul cererii application/json
expected_updated_atToken opțional de blocare optimistă: updated_at din ultima citire. Dacă programarea s-a schimbat între timp, API-ul răspunde cu 409 și o recitiți înainte de a reîncerca.
meeting_linkURL-ul întâlnirii online (http/https) de setat pe programare înainte de trimiterea e-mailului de confirmare.
Răspunsuri
200
OK.
dataobligatoriuCâmpurile data
id4321booking_numberNumărul lizibil al programării, de exemplu "#B-0001".
statuspending = așteaptă confirmarea avocatului; confirmed = aprobată; cancelled/completed; awaiting_payment/expired aparțin fluxului de plată înainte de confirmare.
"pending" "confirmed" "cancelled" "completed" "awaiting_payment" "expired" sourceDe unde provine programarea. O programare creată prin API este "manual".
"flowyer" "website" "embed_widget" "manual" lawyerAvocatul (user_id din colleagues.list) cu care este programarea.
Câmpurile lawyer
user_idnamedateData calendaristică în fusul orar al programării (YYYY-MM-DD), stocată literal.
start_timeOra de început HH:MM în fusul orar al programării.
end_timeOra de sfârșit HH:MM în fusul orar al programării.
startMomentul ISO 8601 neambiguu al începutului, compus cu fusul orar al programării. Folosiți-l pentru a compara momente între fusuri.
endMomentul ISO 8601 neambiguu al sfârșitului.
timezoneFusul orar al programării (booking_settings.timezone), de exemplu "Europe/Budapest". Acesta guvernează date, start_time și end_time.
location_preferenceDacă consultația are loc la birou sau online.
"office" "online" meeting_linkURL-ul întâlnirii online, când este setat.
clientClientul extern care a făcut programarea: nume, e-mail, telefon și obiectul/notele. Date cu caracter personal - doar pentru personalul biroului.
Câmpurile client
nameemailphonedescriptiongdpr_consentDacă este înregistrat consimțământul clientului privind prelucrarea datelor.
gdpr_consent_atCând a fost înregistrat consimțământul.
cancel_reasonMotivul înregistrat la anulare.
paymentStarea de plată, doar pentru citire. API-ul nu modifică niciodată plata; taxele de programare sunt gestionate în Flowyer.
Câmpurile payment
status"none" "awaiting" "partial" "paid" "refunded" method"card" "transfer" amountcurrencyinvoice_numberconfirmed_atcancelled_atcreated_atupdated_atTransmiteți aceasta către bookings.update / bookings.confirm / bookings.cancel ca expected_updated_at.
created_via_apiPrezent atunci când un agent extern a creat programarea prin acest API.
Câmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduserat
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Scope lipsă (scope_missing), API dezactivat pentru birou, licență expirată sau birou arhivat.
scope_missing), API dezactivat pentru birou, licență expirată sau birou arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
413
Corpul cererii este prea mare (request_too_large).
request_too_large).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl -X POST 'https://www.flowyer.ro/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.ro/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.ro/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"
}
Exemple de răspuns
{
"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": "Înregistrarea nu a fost găsită sau nu este vizibilă pentru titularul acestei chei API.",
"locale": "ro",
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Anulare programare
/api/agent/bookings/{id}/cancel
Anulează o programare și TRIMITE UN E-MAIL CLIENTULUI (și avocatului) cu anularea. O programare deja cancelled sau completed răspunde cu 409, astfel încât o reîncercare nu retrimite niciodată e-mailul. O programare plătită este anulată, dar niciodată rambursată (biroul se ocupă de acest lucru). Opțional, transmiteți expected_updated_at.
Parametri de cale
idobligatoriuId-ul programării.
4321Corpul cererii application/json
expected_updated_atToken opțional de blocare optimistă: updated_at din ultima citire. Dacă programarea s-a schimbat între timp, API-ul răspunde cu 409.
reasonMotivul înregistrat ca cancel_reason și afișat în e-mailul de anulare. Text simplu; "<" și ">" nu sunt permise.
^[^<>]*$Răspunsuri
200
OK.
dataobligatoriuCâmpurile data
id4321booking_numberNumărul lizibil al programării, de exemplu "#B-0001".
statuspending = așteaptă confirmarea avocatului; confirmed = aprobată; cancelled/completed; awaiting_payment/expired aparțin fluxului de plată înainte de confirmare.
"pending" "confirmed" "cancelled" "completed" "awaiting_payment" "expired" sourceDe unde provine programarea. O programare creată prin API este "manual".
"flowyer" "website" "embed_widget" "manual" lawyerAvocatul (user_id din colleagues.list) cu care este programarea.
Câmpurile lawyer
user_idnamedateData calendaristică în fusul orar al programării (YYYY-MM-DD), stocată literal.
start_timeOra de început HH:MM în fusul orar al programării.
end_timeOra de sfârșit HH:MM în fusul orar al programării.
startMomentul ISO 8601 neambiguu al începutului, compus cu fusul orar al programării. Folosiți-l pentru a compara momente între fusuri.
endMomentul ISO 8601 neambiguu al sfârșitului.
timezoneFusul orar al programării (booking_settings.timezone), de exemplu "Europe/Budapest". Acesta guvernează date, start_time și end_time.
location_preferenceDacă consultația are loc la birou sau online.
"office" "online" meeting_linkURL-ul întâlnirii online, când este setat.
clientClientul extern care a făcut programarea: nume, e-mail, telefon și obiectul/notele. Date cu caracter personal - doar pentru personalul biroului.
Câmpurile client
nameemailphonedescriptiongdpr_consentDacă este înregistrat consimțământul clientului privind prelucrarea datelor.
gdpr_consent_atCând a fost înregistrat consimțământul.
cancel_reasonMotivul înregistrat la anulare.
paymentStarea de plată, doar pentru citire. API-ul nu modifică niciodată plata; taxele de programare sunt gestionate în Flowyer.
Câmpurile payment
status"none" "awaiting" "partial" "paid" "refunded" method"card" "transfer" amountcurrencyinvoice_numberconfirmed_atcancelled_atcreated_atupdated_atTransmiteți aceasta către bookings.update / bookings.confirm / bookings.cancel ca expected_updated_at.
created_via_apiPrezent atunci când un agent extern a creat programarea prin acest API.
Câmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduserat
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Scope lipsă (scope_missing), API dezactivat pentru birou, licență expirată sau birou arhivat.
scope_missing), API dezactivat pentru birou, licență expirată sau birou arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
413
Corpul cererii este prea mare (request_too_large).
request_too_large).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl -X POST 'https://www.flowyer.ro/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.ro/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.ro/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"
}
Exemple de răspuns
{
"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": "Înregistrarea nu a fost găsită sau nu este vizibilă pentru titularul acestei chei API.",
"locale": "ro",
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Tichete de asistență
Listare tichete de asistență
/api/agent/tickets
Listează tichetele de asistență pe care utilizatorul le poate vedea (vizibilitate per căsuță poștală), cea mai recentă activitate prima. Filtrați după status (implicit open_states = new+open+pending; "all" include și cele închise), căsuță poștală, responsabil, e-mailul solicitantului sau text liber în subiect/solicitant/numărul tichetului.
Parametri de interogare
statusopen_states (implicit) = new+open+pending (vizualizarea implicită din web); "all" include și cele închise; sau un status exact.
"new" "open" "pending" "closed" "open_states" "all" "open_states"mailbox_idDoar tichetele din această căsuță poștală. O căsuță poștală pe care utilizatorul nu o poate vedea produce o listă goală (niciodată o scurgere).
7assigned_to_user_idDoar tichetele atribuite acestui coleg (id din colleagues.list); 0 = doar tichetele neatribuite. Omiteți pentru orice responsabil.
requester_emailDoar tichetele al căror e-mail al solicitantului extern se potrivește exact (fără sensibilitate la majuscule/minuscule).
"ugyfel@example.com"qCăutare text liber în subiect, numele/e-mailul solicitantului și numărul tichetului (ignorând majusculele/minusculele).
"számla"limitDimensiunea paginii, 1-100. Valoarea implicită este 25.
2525offsetNumărul de înregistrări de omis. Folosiți offset + limit ale paginii anterioare pentru a o obține pe următoarea; pagination.total este numărul total.
00Răspunsuri
200
OK.
dataobligatoriuCâmpurile data
idId-ul tichetului (folosiți cu tickets.get / tickets.update).
4321ticket_numberNumărul lizibil al tichetului, de exemplu FLW-000123.
subjectstatus"new" "open" "pending" "closed" priority"low" "normal" "high" mailboxCăsuța poștală prin care a sosit tichetul (registru central).
Câmpurile mailbox
idemaildisplay_namerequesterPersoana externă care a scris.
Câmpurile requester
emailnameassigned_toColegul căruia îi este atribuit tichetul, sau null când este neatribuit.
Câmpurile assigned_to
user_idnamematterDosarul legat de tichet, sau null.
Câmpurile matter
idcase_numberclientClientul legat de tichet, sau null.
Câmpurile client
idnamelast_message_atMomentul celei mai recente activități din fir; lista este ordonată după acesta, cele mai noi primele.
created_atupdated_atTransmiteți aceasta către tickets.update ca expected_updated_at.
created_via_apiPrezent atunci când tichetul a fost creat prin acest API.
Câmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduseratpaginationobligatoriuCâmpurile pagination
limitobligatoriuoffsetobligatoriutotalobligatoriuNumărul total de înregistrări care se potrivesc.
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl 'https://www.flowyer.ro/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.ro/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.ro/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())
Exemple de răspuns
{
"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": "Această cheie API nu are permisiunea \"tickets:read\". Permisiunile unei chei existente nu pot fi modificate, așa că titularul cheii trebuie să creeze în Flowyer, la Setări > Chei API, o cheie nouă cu această permisiune și să o folosească în locul celei vechi.",
"locale": "ro",
"details": {
"required_scope": "tickets:read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Obținere tichet de asistență
/api/agent/tickets/{id}
Returnează un tichet de asistență cu firul său de mesaje (cele mai vechi primele) și dosarul/clientul legat. Răspunde cu 404 când tichetul nu există sau se află într-o căsuță poștală pe care utilizatorul nu o poate vedea. Citirea nu modifică niciodată tichetul (un tichet NEW nu este trecut la OPEN).
Parametri de cale
idobligatoriuId-ul tichetului.
4321Parametri de interogare
messages_limitReturnează doar cele mai noi N mesaje ale firului (prezentate totuși cele mai vechi primele). Omiteți pentru întregul fir.
Răspunsuri
200
OK.
dataobligatoriuCâmpurile data
idId-ul tichetului (folosiți cu tickets.get / tickets.update).
4321ticket_numberNumărul lizibil al tichetului, de exemplu FLW-000123.
subjectstatus"new" "open" "pending" "closed" priority"low" "normal" "high" mailboxCăsuța poștală prin care a sosit tichetul (registru central).
Câmpurile mailbox
idemaildisplay_namerequesterPersoana externă care a scris.
Câmpurile requester
emailnameassigned_toColegul căruia îi este atribuit tichetul, sau null când este neatribuit.
Câmpurile assigned_to
user_idnamematterDosarul legat de tichet, sau null.
Câmpurile matter
idcase_numberclientClientul legat de tichet, sau null.
Câmpurile client
idnamelast_message_atMomentul celei mai recente activități din fir; lista este ordonată după acesta, cele mai noi primele.
created_atupdated_atTransmiteți aceasta către tickets.update ca expected_updated_at.
created_via_apiPrezent atunci când tichetul a fost creat prin acest API.
Câmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduseratmessagesFirul de mesaje, cele mai vechi primele.
Câmpurile messages
iddirectionin = de la solicitant, out = răspuns/confirmare automată trimis din căsuța poștală, note = intern.
"in" "out" "note" fromCâmpurile from
emailnametoCâmpurile to
emailnameccCâmpurile cc
emailnamesent_statusStarea de livrare a unui mesaj de ieșire; null pentru in/note.
"pending" "sent" "failed" "scheduled" body_textCorpul mesajului ca text simplu. Corpul HTML este omis intenționat pentru a păstra firul compact; dacă textul stocat este gol, este generat din HTML.
has_attachmentsauthorColegul care a scris un mesaj out/note; null pentru un mesaj primit.
Câmpurile author
user_idnamecreated_atlinked_matterDosarul legat de tichet (la fel ca matter).
Câmpurile linked_matter
idcase_numberlinked_clientClientul legat de tichet (la fel ca client).
Câmpurile linked_client
idname
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl 'https://www.flowyer.ro/api/agent/tickets/4321' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.ro/api/agent/tickets/4321", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.ro/api/agent/tickets/4321",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Exemple de răspuns
{
"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": "Înregistrarea nu a fost găsită sau nu este vizibilă pentru titularul acestei chei API.",
"locale": "ro",
"details": {
"record_type": "ticket",
"record_id": 4321
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Răspuns la tichet
/api/agent/tickets/{id}/reply
Răspunde la un tichet de asistență și TRIMITE răspunsul prin e-mail către solicitantul extern (prin căsuța poștală a tichetului). Corpul este HTML îmbogățit, igienizat pe partea de server înainte de stocare. O reîncercare cu același Idempotency-Key nu trimite niciodată un al doilea e-mail.
Parametri de cale
idobligatoriuId-ul tichetului (trebuie să fie vizibil prin ACL-ul căsuței poștale).
4321Parametri de antet
Idempotency-KeyRecomandat la fiecare creare. O valoare unică per operație logică (de exemplu un UUID). Aceeași valoare returnează aceeași înregistrare: reîncercarea cu ea returnează înregistrarea creată prima dată, în loc să creeze o a doua. Valori diferite creează întotdeauna înregistrări diferite. Clienții care nu pot trimite anteturi pot transmite aceeași valoare în câmpul de corp idempotency_key. Litere, cifre, _, -, : sau ., cel mult 128 de caractere.
^[A-Za-z0-9_\-:.]{1,128}$Corpul cererii application/json
body_htmlobligatoriuRăspunsul, HTML îmbogățit (așa cum îl produce TinyMCE). Curățat pe partea de server cu HTMLPurifier înainte de stocare și înainte de trimitere. Cel mult 100000 de caractere; respins dacă prin igienizare nu rămâne nimic.
"<p>Köszönjük megkeresését, csatoltan küldjük a választ.</p>"ccDestinatari Cc suplimentari (cel mult 10). Solicitantul și căsuța poștală sunt excluse automat; o adresă invalidă răspunde cu 422.
statusStatusul tichetului de setat după răspuns (implicit "pending" = în așteptarea solicitantului). Înregistrează un eveniment de schimbare a statusului.
"new" "open" "pending" "closed" "pending"append_signatureAdaugă semnătura de tichet salvată a utilizatorului cheii doar la e-mailul de IEȘIRE (niciodată stocată în fir).
falseidempotency_keyAcelași rol ca antetul Idempotency-Key, pentru clienții care nu pot trimite anteturi personalizate. Litere, cifre, _, -, : sau ., cel mult 128 de caractere.
^[A-Za-z0-9_\-:.]{1,128}$"b8f1c2e0-6f7a-4d2e-9c1b-2a3d4e5f6a7b"Răspunsuri
201
Creat.
dataobligatoriuCâmpurile data
ticket_id4321message_idId-ul rândului ticket_messages de ieșire creat.
98765directionÎntotdeauna "out".
sent_status"pending" la momentul creării; trimiterea asincronă îl schimbă ulterior la sent/failed.
"pending" "sent" "failed" "scheduled" statusStatusul tichetului după răspuns.
"new" "open" "pending" "closed" created_atcreated_via_apiPrezent atunci când răspunsul a fost creat prin acest API.
Câmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduseratcreatedtrue
200
Reluare idempotentă: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică în interval de 120 de secunde) a creat deja înregistrarea; aceasta este returnată din nou, nu s-a creat nimic nou.
dataobligatoriuCâmpurile data
ticket_id4321message_idId-ul rândului ticket_messages de ieșire creat.
98765directionÎntotdeauna "out".
sent_status"pending" la momentul creării; trimiterea asincronă îl schimbă ulterior la sent/failed.
"pending" "sent" "failed" "scheduled" statusStatusul tichetului după răspuns.
"new" "open" "pending" "closed" created_atcreated_via_apiPrezent atunci când răspunsul a fost creat prin acest API.
Câmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduseratcreatedfalseidempotent_replaytrue
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator. replay_not_visible: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică) a creat deja înregistrarea (details.record_id), dar aceasta a fost între timp ștearsă sau nu este vizibilă pentru utilizator; nu s-a creat nimic nou, nu o creați din nou.
replay_not_visible: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică) a creat deja înregistrarea (details.record_id), dar aceasta a fost între timp ștearsă sau nu este vizibilă pentru utilizator; nu s-a creat nimic nou, nu o creați din nou.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
409
Idempotency-Key a fost folosit pentru alt tip de resursă (idempotency_key_reused) sau, în lipsa unei chei, o cerere identică este procesată chiar acum (duplicate_in_progress; reîncercați în scurt timp).
idempotency_key_reused) sau, în lipsa unei chei, o cerere identică este procesată chiar acum (duplicate_in_progress; reîncercați în scurt timp).
413
Corpul cererii este prea mare (request_too_large).
request_too_large).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl -X POST 'https://www.flowyer.ro/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.ro/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.ro/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>"
}
Exemple de răspuns
{
"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": "Cererea nu este validă. Erorile pe câmpuri se găsesc în \"details.fields\".",
"locale": "ro",
"details": {
"fields": {
"body_html": [
"Câmpul body html este obligatoriu."
]
}
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Schimbare status tichet
/api/agent/tickets/{id}
Schimbă statusul unui tichet (new, open, pending sau closed). "closed" marchează closed_at; orice alt status îl șterge. Transmiteți expected_updated_at din ultima citire; o modificare conflictuală răspunde cu 409. Răspunde cu 404 când tichetul nu este vizibil.
Parametri de cale
idobligatoriuId-ul înregistrării de modificat.
Corpul cererii application/json
expected_updated_atValoarea updated_at din cea mai recentă citire a acestei înregistrări (obligatorie ori de câte ori înregistrarea are una). Dacă înregistrarea s-a schimbat între timp (un coleg a editat-o), API-ul răspunde cu 409 și trebuie să o recitiți înainte de a reîncerca. O înregistrare veche al cărei updated_at este null acceptă null.
statusobligatoriuNoul status. "closed" marchează closed_at; orice alt status îl șterge.
"new" "open" "pending" "closed" "open"Răspunsuri
200
Actualizat.
dataobligatoriuCâmpurile data
idId-ul tichetului (folosiți cu tickets.get / tickets.update).
4321ticket_numberNumărul lizibil al tichetului, de exemplu FLW-000123.
subjectstatus"new" "open" "pending" "closed" priority"low" "normal" "high" mailboxCăsuța poștală prin care a sosit tichetul (registru central).
Câmpurile mailbox
idemaildisplay_namerequesterPersoana externă care a scris.
Câmpurile requester
emailnameassigned_toColegul căruia îi este atribuit tichetul, sau null când este neatribuit.
Câmpurile assigned_to
user_idnamematterDosarul legat de tichet, sau null.
Câmpurile matter
idcase_numberclientClientul legat de tichet, sau null.
Câmpurile client
idnamelast_message_atMomentul celei mai recente activități din fir; lista este ordonată după acesta, cele mai noi primele.
created_atupdated_atTransmiteți aceasta către tickets.update ca expected_updated_at.
created_via_apiPrezent atunci când tichetul a fost creat prin acest API.
Câmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduseratupdatedtrue
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
409
Înregistrarea s-a schimbat de când ați citit-o (record_conflict: expected_updated_at nu mai corespunde; citiți-o din nou și reîncercați cu noul updated_at).
record_conflict: expected_updated_at nu mai corespunde; citiți-o din nou și reîncercați cu noul updated_at).
413
Corpul cererii este prea mare (request_too_large).
request_too_large).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl -X PATCH 'https://www.flowyer.ro/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.ro/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.ro/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"
}
Exemple de răspuns
{
"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": "Înregistrarea s-a modificat de când ați citit-o (cineva a editat-o). Citiți-o din nou și reîncercați cu noua valoare updated_at.",
"locale": "ro",
"details": {
"current_updated_at": "2026-10-30T10:42:05+01:00",
"reason": "modified_since_read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Portal clienți
Listare portaluri client
/api/agent/portals
Listează portalurile client (firele) la care utilizatorul are acces: dosarul, participanții din partea clientului, numărul de mesaje și de participanți și ora ultimului mesaj, cele mai noi primele. Opțional filtrate la un singur dosar (matter_id). Un dosar are cel mult un portal.
Parametri de interogare
matter_idDoar portalul acestui dosar (404 matter_not_visible când dosarul nu este vizibil). Un dosar are cel mult un portal.
1234limitDimensiunea paginii, 1-100. Valoarea implicită este 25.
2525offsetNumărul de înregistrări de omis. Folosiți offset + limit ale paginii anterioare pentru a o obține pe următoarea; pagination.total este numărul total.
00Răspunsuri
200
OK.
dataobligatoriuCâmpurile data
idId-ul portalului (firului) - identificatorul pentru portal.messages.list și portal.reply.
57matterDosarul (cazul) de care aparține portalul.
Câmpurile matter
idcase_numberclient_participantsParticipanții externi din partea clientului cu care discută firma.
Câmpurile client_participants
namekindclient = un mandant, contact = o persoană de contact a clientului, email = un acces mai vechi doar prin e-mail.
"client" "contact" "email" participant_countNumărul de participanți activi (personal și client).
message_countNumărul de mesaje neșterse din fir.
last_message_atCând a fost postat cel mai nou mesaj neșters, ISO 8601 în fusul biroului; null pentru un fir gol.
unread_for_meMesaje necitite pentru propriul rând de participant al utilizatorului care acționează; null când utilizatorul care acționează nu este participant al acestui portal.
created_atpaginationobligatoriuCâmpurile pagination
limitobligatoriuoffsetobligatoriutotalobligatoriuNumărul total de înregistrări care se potrivesc.
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl 'https://www.flowyer.ro/api/agent/portals?matter_id=1234&limit=25' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.ro/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.ro/api/agent/portals?matter_id=1234&limit=25",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Exemple de răspuns
{
"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": "Această cheie API nu are permisiunea \"portal:read\". Permisiunile unei chei existente nu pot fi modificate, așa că titularul cheii trebuie să creeze în Flowyer, la Setări > Chei API, o cheie nouă cu această permisiune și să o folosească în locul celei vechi.",
"locale": "ro",
"details": {
"required_scope": "portal:read"
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Listare mesaje de portal
/api/agent/portals/{id}/messages
Listează mesajele unui fir de portal client, cele mai vechi primele, cu autorul (personal sau client), corpul în text simplu și eventualele metadate ale atașamentelor. Răspunde cu 404 când portalul nu există sau nu este accesibil. Nu marchează mesajele ca citite.
Parametri de cale
idobligatoriuId-ul portalului (trebuie să fie accesibil).
57Parametri de interogare
include_deletedInclude mesajele șterse (corpul lor este golit). Implicit false.
falselimitDimensiunea paginii, 1-100. Valoarea implicită este 25.
2525offsetNumărul de înregistrări de omis. Folosiți offset + limit ale paginii anterioare pentru a o obține pe următoarea; pagination.total este numărul total.
00Răspunsuri
200
OK.
dataobligatoriuCâmpurile data
idportal_messages.id.
8012authorCine a scris mesajul.
Câmpurile author
participant_idnamekindstaff = un coleg al firmei, client = clientul extern.
"staff" "client" directionfrom_firm = un autor din personal, from_client = clientul extern.
"from_firm" "from_client" bodyMesajul în text simplu (<br> decodat în întreruperi de linie). Șir gol pentru un mesaj șters.
attachmentMetadatele atașamentului când mesajul are un document; descărcarea lui este în afara domeniului. Null când nu există niciunul.
Câmpurile attachment
portal_document_idfile_nameis_deleteddeleted_atcreated_atCând a fost postat mesajul, ISO 8601 în fusul biroului.
paginationobligatoriuCâmpurile pagination
limitobligatoriuoffsetobligatoriutotalobligatoriuNumărul total de înregistrări care se potrivesc.
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl 'https://www.flowyer.ro/api/agent/portals/57/messages?limit=25' \
-H 'Authorization: Bearer flw_...'
const response = await fetch("https://www.flowyer.ro/api/agent/portals/57/messages?limit=25", {
headers: {
"Authorization": "Bearer flw_...",
},
});
const result = await response.json();
import requests
response = requests.get(
"https://www.flowyer.ro/api/agent/portals/57/messages?limit=25",
headers={
"Authorization": "Bearer flw_...",
},
timeout=30,
)
print(response.status_code, response.json())
Exemple de răspuns
{
"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": "Portalul pentru clienți :id nu există sau nu este accesibil utilizatorului acestei chei API.",
"locale": "ro",
"details": {
"portal_id": 57
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}
Răspuns în portalul client
/api/agent/portals/{id}/messages
Postează un răspuns al personalului într-un fir de portal client. Clientul îl vede în portal și este notificat prin e-mail (o înștiințare cu magic-link semnat, nu textul); colegii primesc o înștiințare în aplicație. Text simplu, escapat la stocare. 404 când portalul nu este accesibil.
Parametri de cale
idobligatoriuId-ul portalului în care se răspunde (trebuie să fie accesibil).
57Parametri de antet
Idempotency-KeyRecomandat la fiecare creare. O valoare unică per operație logică (de exemplu un UUID). Aceeași valoare returnează aceeași înregistrare: reîncercarea cu ea returnează înregistrarea creată prima dată, în loc să creeze o a doua. Valori diferite creează întotdeauna înregistrări diferite. Clienții care nu pot trimite anteturi pot transmite aceeași valoare în câmpul de corp idempotency_key. Litere, cifre, _, -, : sau ., cel mult 128 de caractere.
^[A-Za-z0-9_\-:.]{1,128}$Corpul cererii application/json
bodyobligatoriuRăspunsul, text simplu. Parantezele unghiulare sunt acceptate și escapate la stocare. Cel mult 20000 de caractere.
"Tisztelt Ügyfelünk! A beadványt ma benyújtottuk."idempotency_keyAcelași rol ca antetul Idempotency-Key, pentru clienții care nu pot trimite anteturi personalizate. Litere, cifre, _, -, : sau ., cel mult 128 de caractere.
^[A-Za-z0-9_\-:.]{1,128}$"b8f1c2e0-6f7a-4d2e-9c1b-2a3d4e5f6a7b"Răspunsuri
201
Creat.
dataobligatoriuCâmpurile data
messageRăspunsul postat.
Câmpurile message
id8012authorUtilizatorul din personal care a postat răspunsul.
Câmpurile author
participant_idnamekindstaff = un coleg al firmei, client = clientul extern.
"staff" "client" directionÎntotdeauna "from_firm" pentru un răspuns postat prin acest API.
"from_firm" "from_client" bodyMesajul postat în text simplu.
created_atportalPortalul (firul) și dosarul său în care a fost postat răspunsul.
Câmpurile portal
idmatterCâmpurile matter
idcase_numbercreated_via_apiProveniența mesajului creat prin acest API.
Câmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduseratcreatedtrue
200
Reluare idempotentă: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică în interval de 120 de secunde) a creat deja înregistrarea; aceasta este returnată din nou, nu s-a creat nimic nou.
dataobligatoriuCâmpurile data
messageRăspunsul postat.
Câmpurile message
id8012authorUtilizatorul din personal care a postat răspunsul.
Câmpurile author
participant_idnamekindstaff = un coleg al firmei, client = clientul extern.
"staff" "client" directionÎntotdeauna "from_firm" pentru un răspuns postat prin acest API.
"from_firm" "from_client" bodyMesajul postat în text simplu.
created_atportalPortalul (firul) și dosarul său în care a fost postat răspunsul.
Câmpurile portal
idmatterCâmpurile matter
idcase_numbercreated_via_apiProveniența mesajului creat prin acest API.
Câmpurile created_via_api
kind"key": creat cu o cheie API statică; "oauth": creat de o aplicație conectată prin OAuth.
"key" "oauth" key_idId-ul cheii API (de tipul "key") sau al aplicației conectate (de tipul "oauth"); cele două sunt numerotate separat.
key_nameNumele pe care utilizatorul l-a dat cheii API, de exemplu "Grok integration", sau numele aplicației conectate pentru tipul "oauth", de exemplu "Claude".
user_iduseratcreatedfalseidempotent_replaytrue
400
Cerere malformată: corp JSON invalid, host greșit (folosiți hostul www.) sau o cerere care nu poate fi citită.
401
Cheia lipsește, este invalidă, revocată sau expirată, ori utilizatorul ei nu mai este activ.
403
Lipsește un scope (scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
scope_missing), lipsește o permisiune de modul Flowyer (module_forbidden), API-ul este dezactivat pentru birou, licența a expirat sau biroul este arhivat.
404
Endpoint necunoscut sau înregistrarea nu există / nu este vizibilă pentru utilizator. replay_not_visible: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică) a creat deja înregistrarea (details.record_id), dar aceasta a fost între timp ștearsă sau nu este vizibilă pentru utilizator; nu s-a creat nimic nou, nu o creați din nou.
replay_not_visible: acest Idempotency-Key (sau, în lipsa unei chei, o cerere identică) a creat deja înregistrarea (details.record_id), dar aceasta a fost între timp ștearsă sau nu este vizibilă pentru utilizator; nu s-a creat nimic nou, nu o creați din nou.
405
Metodă neoferită pe această cale (DELETE și PUT nu sunt niciodată oferite; PATCH doar acolo unde se oferă o actualizare).
409
Idempotency-Key a fost folosit pentru alt tip de resursă (idempotency_key_reused) sau, în lipsa unei chei, o cerere identică este procesată chiar acum (duplicate_in_progress; reîncercați în scurt timp).
idempotency_key_reused) sau, în lipsa unei chei, o cerere identică este procesată chiar acum (duplicate_in_progress; reîncercați în scurt timp).
413
Corpul cererii este prea mare (request_too_large).
request_too_large).
422
Validarea a eșuat sau câmp necunoscut; details.fields listează erorile de câmp.
details.fields listează erorile de câmp.
429
Limita de rată a fost depășită; Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
503
Biroul este temporar indisponibil (întreținere sau configurare în curs); Retry-After indică momentul reîncercării.
Retry-After indică momentul reîncercării.
default
Orice altă eroare, în același plic de răspuns.
Exemple de cerere
curl -X POST 'https://www.flowyer.ro/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.ro/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.ro/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."
}
Exemple de răspuns
{
"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": "Cererea nu este validă. Erorile pe câmpuri se găsesc în \"details.fields\".",
"locale": "ro",
"details": {
"fields": {
"body": [
"Câmpul body este obligatoriu."
]
}
},
"request_id": "3f0c8a5e-2b1d-4c7a-9e6f-5a4b3c2d1e0f"
}