/api/templates nell’app control-plane (apps/app) per gestire la libreria di template WhatsApp del workspace. Tutte le route richiedono un operatore autenticato con accesso alle impostazioni (owner, admin o developer); la route di seed richiede inoltre owner o admin.
Le richieste sono limitate al workspace attivo del chiamante — non è possibile vedere o modificare i template di un altro workspace. Gli errori di autenticazione restituiscono 401 unauthenticated o 403 forbidden.
Riepilogo
GET /api/templates
Elenca ogni template per il workspace attivo, ordinato per data di aggiornamento più recente. Risposta 200401 unauthenticated, 403 forbidden, 500 internal_error.
POST /api/templates
Crea una nuova bozza di template. Il template viene memorizzato constatus = "draft" e non viene inviato a Meta. Usa POST /api/templates/{id}/submit dopo che la bozza è pronta.
Corpo della richiesta
name(stringa, obbligatorio) — i caratteri minuscoli e non corrispondenti vengono ridotti a_. Vedi name-regex.language(stringa, default"en_US") — codice locale Meta, ad es."it","en_US","pt_BR".category("MARKETING" | "UTILITY" | "AUTHENTICATION", default"UTILITY").parameterFormat("POSITIONAL" | "NAMED", default"POSITIONAL").components(array) — la struttura dei componenti secondo lo schema di Meta.
400 create_failed con message che descrive l’errore del DB o di validazione, oltre agli errori di autenticazione.
GET /api/templates/
Recupera un singolo template per id. Restituisce404 not_found se l’id non esiste nel workspace del chiamante.
Risposta 200 — stessa struttura di una voce dell’elenco.
PUT /api/templates/
Aggiorna uno o più campi di un template in bozza. I campi inviati vengono applicati come patch; i campi non inviati rimangono inalterati. Corpo della richiesta (tutti i campi opzionali)400 update_failed, errori di autenticazione.
DELETE /api/templates/
Elimina un template in bozza. Solo i template constatus = "draft" possono essere eliminati — una volta inviati, i template vengono conservati per l’audit. Un template non in bozza restituisce 409 conflict.
Risposta 200
404 not_found, 409 conflict con "Only draft templates can be deleted", errori di autenticazione.
POST /api/templates//submit
Invia un template in bozza all’endpointPOST /{waba_id}/message_templates di Meta. Switchbord esegue prima l’intero validatore lato client (le stesse regole documentate in Regole dei template); se un controllo fallisce, non viene effettuata alcuna chiamata a Meta e viene restituito un 400 validation_failed con l’array dei problemi riscontrati.
In caso di successo, la riga del template viene aggiornata con meta_template_id, status = "pending_approval" e rejection_reason = null.
In caso di rifiuto da parte di Meta (HTTP 4xx con un corpo error), la riga viene aggiornata con status = "rejected" e rejection_reason impostato sul messaggio leggibile di Meta, e viene restituito al chiamante un 400 meta_submit_failed con il payload di errore completo di Meta.
Risposta 200
400 validation_failed— il validatore lato client ha rifiutato la bozza.issuesè l’array di problemi Zod.400 meta_submit_failed— Meta ha restituito un errore.metaè l’oggettoerrorgrezzo di Meta (code, subcode,error_user_msg,error_data.details).400 no_waba— nessun WhatsApp Business Account configurato per il workspace.400 no_access_token— nessun token di accesso Meta nel vault del workspace.404 not_found, errori di autenticazione.
POST /api/templates/seed-starter-pack
Seeder one-shot riservato agli admin che invia lo starter pack GB Viaggi (8UTILITY + 5 MARKETING, italiano + inglese dove applicabile) a Meta e inserisce/aggiorna le righe corrispondenti nella tabella locale templates. È sicuro rieseguirlo — la chiave di upsert è (workspace_id, name, locale).
Ruolo richiesto: owner o admin.
Corpo della richiesta — vuoto.
Risposta 200
status per ogni voce:
submitted— accettato da Meta, riga memorizzata comepending_approval.error— errore di Meta o del DB, riga memorizzata comerejectedcon il messaggio di Meta.skipped— riservato; attualmente non viene emesso.
400 no_waba— nessun WhatsApp Business Account configurato.400 no_access_token— segreto del vaultmeta-access-tokenmancante.500 internal_error— errore non gestito.401 unauthenticated,403 forbidden— il chiamante non possiede il ruolo owner/admin.
Endpoint interni correlati
Esistono due route interne, non pubbliche, inapps/api per i flussi di sincronizzazione machine-to-machine:
POST /internal/templates— upsert del template dal worker verso l’API dopo un evento webhook.POST /internal/templates/sync— ri-sincronizzazione completa della libreria da Meta verso Switchbord.
OpenAPI
La struttura leggibile dalla macchina per questi endpoint verrà generata inapps/docs/api-reference/openapi.json da pnpm openapi:generate. Esegui il generatore dopo aver modificato una route per mantenere la specifica sincronizzata.