Le altre tre guide seguono dei percorsi; questa raccoglie le regole che si applicano a ogni chiamata, da tenere a portata di mano mentre scrivete il vostro client.
BASE=https://<deployment>.convex.site/api/v1
KEY=ba_...1. La busta data
Ogni risposta riuscita avvolge il suo contenuto in data:
{ "data": [ ... ] }Due eccezioni senza corpo: 204 No Content sulle eliminazioni, e 302 sui download di PDF, giustificativi e loghi, da seguire con -L.
2. Paginazione
Le liste delle risorse di società sono paginate, dalla più recente alla più vecchia:
{ "data": [ ... ], "nextCursor": "..." }Tre liste non sono paginate e rispondono con un array semplice sotto data: GET /companies, GET /mandates e GET /companies/{companyId}/invoice-templates.
3. Date e identificativi
Le date sono accettate in millisecondi epoch o in YYYY-MM-DD, e restituite in millisecondi epoch. I filtri from/to delimitano la data di emissione, estremi inclusi. Un'eccezione: le assenze memorizzano e restituiscono stringhe YYYY-MM-DD, perché è il loro ordine di ordinamento.
Gli identificativi sono stringhe opache. Un identificativo sconosciuto, uno malformato e uno di un'altra società rispondono tutti 404 NOT_FOUND: i tre casi sono volutamente indistinguibili, perché nessun identificativo di un altro account trapeli.
4. Corpi stretti
- I corpi delle rotte account, società, cliente, fattura, preventivo, ricorrenza e modello sono stretti: ogni chiave sconosciuta è rifiutata.
- Un corpo è sempre richiesto su
POSTePATCH({}è una patch vuota valida; un corpo vuoto èINVALID_JSON), salvo sulle azioni senza corpo comePOST …/default;DELETEnon ne prende. - Oltre 1 MB, il corpo è rifiutato:
413 PAYLOAD_TOO_LARGE. - Cinque rotte prendono byte grezzi anziché JSON: il giustificativo di una spesa, l'estrazione IA e l'allegato IA (PDF, PNG, JPEG o WebP, 10 MB), più
PUT …/logosu una società e su un modello di fattura (solo PNG o JPEG, 2 MB). IlContent-Typedichiara il formato e il corpo è il file; tutto il resto viaggia nella query. - Una chiave di query sconosciuta è un
400 VALIDATION_ERRORsu ogni rotta che dichiara un contratto di query;GET /meeGET /companiesignorano il resto, senza che sia una promessa. PUTsu un'assenza è una sostituzione completa: i campi facoltativi omessi vengono cancellati.
Un errore di validazione elenca ogni campo errato sotto issues, in percorsi puntati, indici di array compresi:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid request body",
"issues": [
{ "path": "subtotal", "message": "Unrecognized key \"subtotal\"" },
{ "path": "vatRates.0.rate", "message": "Too big: expected number to be <=100" }
]
}
}5. Errori
Gli errori portano un codice stabile, leggibile da una macchina:
{ "error": { "code": "PAYSLIP_ALREADY_EXISTS" } }Solo VALIDATION_ERROR (con issues) e INVALID_TRANSITION aggiungono un message; ogni altro codice risponde da solo. Diramate su error.code, mai sulla prosa. Questa busta vale su ogni percorso sotto /api/v1/, compreso un percorso sconosciuto (404 NOT_FOUND) e un metodo non supportato (405 METHOD_NOT_ALLOWED, con un header Allow).
I controlli girano in quest'ordine: chiave e proprietario (401), visibilità della società (404), poi società archiviatapianomodulopermesso (403). Una società di cui il titolare della chiave non è membro è indistinguibile da una inesistente.
401 INVALID_API_KEY: chiave assente, malformata, sconosciuta o revocata; proprietario bannato o eliminato.403 PLAN_NOT_ALLOWED,403 COMPANY_ARCHIVED,403 ACCESS_DENIED: piano, archiviazione, permesso o ruolo mancanti.403 INVOICING_MODULE_DISABLED,403 PAYROLL_MODULE_DISABLED,403 EXPENSES_MODULE_DISABLED,403 FINANCIAL_STATEMENTS_MODULE_DISABLED: modulo disattivato sulla società.403 *_LIMIT_REACHED: quota del piano raggiunta (clienti, fatture, ricorrenze, dipendenti, buste, spese).400 BATCH_SIZE_INVALID: lotto fuori da 1 a 100 elementi.409 INVALID_TRANSITION,409 PAYSLIP_ALREADY_EXISTS,409 ABSENCE_OVERLAPS_EXISTING,409 QUOTE_NOT_EDITABLE: conflitto con lo stato attuale.422 MODIFICATION_REASON_REQUIRED,422 CLIENT_EMAIL_MISSING,422 PERIOD_FISCAL_YEAR_MISMATCH: richiesta valida ma inammissibile in questo contesto.503 PDF_UNAVAILABLE,502 EMAIL_SEND_FAILED,500 INTERNAL_ERROR: riprovate.
La lista completa dei codici è l'enumerazione pubblicata nella Swagger UI e in openapi.json del vostro deployment.
6. Limiti e utilizzo
Non c'è ancora alcuna limitazione di frequenza. Le chiamate sono contate, non frenate: un contatore per chiave, endpoint, società interessata e giorno UTC, visibile in AccountChiavi APIUtilizzo. Le richieste respinte dall'autenticazione non sono contate; un 400 su una chiamata autorizzata sì.
Siate comunque un buon vicino: scorrete le liste invece di interrogarle in loop, e arretrate su 500 o 503. I due lotti non si comportano allo stesso modo: POST …/payslips/batch non è atomico e restituisce un risultato per elemento, POST …/bank-transactions/batch è atomico, tutto o niente.
7. Sandbox e reset
Il sandbox non scrive mai in produzione. E-mail, Stripe e inviti Clerk vi sono inerti, la registrazione è chiusa, i loghi non vengono copiati. Tutto il resto gira, compresi i job pianificati: le fatture ricorrenti vengono generate e le buste paga calcolate sui dati copiati.
Ritorno ai percorsi: Iniziare con l'API, Fatturare con l'API, Paghe, spese e contabilità con l'API. Ogni campo, ogni risposta e l'enumerazione completa dei codici sono nella Swagger UI del vostro deployment (…/api/docs).