Con l'API propform puoi gestire i tuoi moduli, gli invii, le statistiche, i modelli PDF, le carte intestate, i collaboratori e le impostazioni dell’account da applicazioni esterne, ad esempio dai tuoi strumenti, script o piattaforme di automazione come Zapier, Make o n8n.
> URL di base: https://propform.io/api/v1
>
> Tutte le richieste e le risposte sono in formato JSON (Content-Type: application/json). I timestamp sono in formato ISO-8601 (ad es. 2026-07-07T08:30:00+00:00).
Creare una chiave API: Vai su Impostazioni → Chiavi API, clicca su Crea chiave API e copia la chiave visualizzata (formato pf_live_…). Per motivi di sicurezza, ti verrà mostrata solo questa volta.
Verifica la connessione: sostituisci pf_live_DEIN_KEY e accedi a:
curl https://propform.io/api/v1/me \
-H "Authorization: Bearer pf_live_DEIN_KEY"
Risposta:
{ "data": { "id": 42, "name": "Max Makler", "email": "max@makler.de" } }
Prima richiesta effettiva – elenca i tuoi moduli:
curl https://propform.io/api/v1/forms \
-H "Authorization: Bearer pf_live_DEIN_KEY"
L’API utilizza le chiavi API come token bearer. Ogni richiesta richiede la chiave nell’intestazione Authorization (Authorization: Bearer pf_live_…). In assenza di chiave o in caso di chiave non valida, l’API risponde con 401.
In caso di superamento del limite, l’API risponde con 429 Too Many Requests e un’intestazione Retry-After (secondi che mancano al prossimo tentativo consentito). Inserisci una breve pausa nelle automazioni quando visualizzi questo stato.
Le risposte andate a buon fine forniscono i dati nel campo data.
Gli elenchi sono impaginati. Gestiscili tramite per_page (impostazione predefinita 25, max. 100) e page. La risposta contiene inoltre links e meta:
{
"data": [ { "id": 14, "internal_title": "Kontaktformular", "active": true } ],
"links": { "first": "...", "last": "...", "prev": null, "next": "...?page=2" },
"meta": { "current_page": 1, "per_page": 25, "total": 63, "last_page": 3 }
}
Gli errori hanno sempre un campo message; in caso di errori di convalida (422), i dettagli per ciascun campo sono riportati in errors:
{
"message": "The url field is required.",
"errors": { "url": ["The url field is required."] }
}
| Stato | Significato |
|---|---|
200 / 201 |
Operazione riuscita (201 = nuovo record creato) |
204 |
Operazione riuscita, nessun dato di risposta (ad es. cancellazione) |
401 |
Chiave API assente o non valida |
403 |
Il record non appartiene al tuo account (o funzione non inclusa nel piano tariffario) |
404 |
Il record non esiste |
409 |
Azione attualmente non possibile (ad es. onOffice non connesso) |
422 |
Errore di convalida – Dettagli nel campo errors |
429 |
Limite di rate raggiunto – Vedi Retry-After |
| Metodo | Endpoint | Descrizione |
|---|---|---|
GET |
/forms |
Elenca i propri moduli. Filtri: active (0/1), template (0/1), updated_since (data), folder (ID cartella o none), per_page, page |
POST |
/forms |
Crea un nuovo modulo – è necessario solo internal_title, si avvia inattivo |
GET |
/forms/{id} |
Leggi il modulo per intero (compresi i campi, l’e-mail e la configurazione di ChatGPT) |
PATCH |
/forms/{id} |
Configurare il modulo – vengono modificati solo i campi inviati |
POST |
/forms/{id}/copy |
Copia del modulo (compresi campi, regole, configurazione e-mail); la copia si avvia inattiva |
Il modulo è una risorsa nell’API: puoi leggere e modificare le impostazioni relative all’invio delle e-mail e all’integrazione con ChatGPT direttamente sul modulo. I nomi dei campi corrispondono esattamente alle impostazioni nell’editor del modulo.
curl -X PATCH https://propform.io/api/v1/forms/123 \
-H "Authorization: Bearer pf_live_DEIN_KEY" \
-H "Content-Type: application/json" \
-d '{"title": "Neuer Titel", "active": true}'
Caratteristiche importanti:
"active": true) funziona solo finché non viene raggiunto il limite del tuo piano relativo ai moduli attivi (altrimenti 422). La disattivazione è sempre possibile.slug, i contatori e i flag dei modelli. Le password (ad es. la password del modulo) sono modificabili, ma non compaiono mai nelle risposte.form_template indica questa condivisione; con il filtro template=0/1 puoi filtrare in base ad essa.url pubblico del modulo.Un modulo dispone di oltre 100 impostazioni (tutte quelle offerte anche dall’editor). Le più importanti:
| Campo | Significato |
|---|---|
internal_title |
Nome interno (visibile solo nella dashboard) |
title |
Titolo pubblico del modulo |
custom_slug |
Parte descrittiva dell’URL (deve essere univoca nel tuo account) |
active |
Modulo online (true) o offline (false) |
description |
Testo introduttivo sopra il modulo |
submit_button_label |
Etichetta del pulsante di invio |
thankyou_headline / thankyou_text |
Titolo e testo della pagina di ringraziamento |
redirect |
URL di reindirizzamento dopo l’invio (al posto della pagina di ringraziamento) |
background_color / accent_color |
Colori di design (esadecimali, ad es. #0d6efd) |
subject / body / receiver |
Oggetto, testo e destinatario dell’e-mail di conferma |
send_email_via_onoffice |
Invia l’e-mail di conferma tramite onOffice |
Puoi visualizzare l’oggetto completo in qualsiasi momento tramite GET /forms/{id}.
👉 Trovi l'elenco completo di tutti i campi e formati nella referenza dei campi API.
| Metodo | Endpoint | Descrizione |
|---|---|---|
GET |
/forms/{id}/fields |
Campi di un modulo (ordinati per posizione) |
POST |
/forms/{id}/fields |
Crea campo – onoffice_module è obbligatorio, la posizione viene aggiunta automaticamente alla fine |
GET |
/fields/{id} |
Leggere un singolo campo |
PATCH |
/fields/{id} |
Modificare un campo (solo proprietà inviate) |
DELETE |
/fields/{id} |
Elimina campo |
PATCH |
/forms/{id}/fields/reorder |
Riordinare i campi – field_ids deve contenere tutti gli ID dei campi del modulo nell'ordine desiderato |
curl -X POST https://propform.io/api/v1/forms/123/fields \
-H "Authorization: Bearer pf_live_DEIN_KEY" \
-H "Content-Type: application/json" \
-d '{"onoffice_module": "address", "onoffice_field_name": "Vorname", "label": "Vorname", "required": true}'
| Campo | Significato |
|---|---|
onoffice_module |
Modulo di destinazione: address, estate, task, calendar, agentsLog – oppure relationlist per il Campo di collegamento (obbligatorio al momento della creazione) |
onoffice_field_name |
Nome del campo di destinazione in onOffice (vedi Configurazione dei campi onOffice) |
label |
Etichetta del campo nel modulo |
hint / placeholder |
Testo di aiuto o segnaposto nel campo di immissione |
required |
Campo obbligatorio (true/false) |
hidden / disabled / read_only |
Nascosto / disattivato / di sola lettura |
default_value |
Valore predefinito |
half_size |
Visualizza il campo a mezza larghezza sugli schermi di grandi dimensioni |
datalist |
Valori di selezione come elenco separato da punti e virgola (Rot;Grün;Blau) |
display_variant |
Variante di visualizzazione del campo (vedi sotto) |
select_option_meta |
Dati aggiuntivi per chiave di selezione per le visualizzazioni a schede/icone/immagini (stringa JSON, vedi sotto) |
Con display_variant controlli come un campo viene visualizzato nel modulo — il valore salvato e il collegamento a onOffice restano identici. null o vuoto = visualizzazione standard. Valori validi per tipo di campo:
| Tipo di campo onOffice | Valori |
|---|---|
singleselect / user |
radio, buttons, cards, icons, images, likert |
multiselect |
checkboxes, chips, icons, images |
boolean |
checkbox, yesno |
integer |
slider, stars, nps |
float |
slider, stars, nps |
date |
calendar |
Criterio di ricerca da/a (integer/float nel modulo searchcriteria) |
rangeslider |
I valori sconosciuti o non adatti al tipo di campo vengono ignorati durante il rendering (visualizzazione standard). Per cards, icons e images, select_option_meta fornisce i dati aggiuntivi per ogni valore chiave onOffice — una stringa JSON della forma:
{"haus": {"icon": "home", "description": "Indipendente o a schiera"}, "wohnung": {"image": "https://…/wohnung.jpg"}}
icon è il nome di un'icona del set integrato Tabler Icons (solo minuscole/cifre/trattini, ad es. home, building-estate, currency-euro), image un URL di immagine http(s) (idealmente dalla libreria multimediale), description un testo sotto il titolo dell'opzione (schede, riquadri con icone e immagini). Le icone compaiono sui riquadri con icone, davanti all'etichetta dell'opzione nel gruppo di pulsanti e sopra i pulsanti della scala Likert. Le voci vuote o sconosciute vengono ignorate. Per il cursore, valore minimo/massimo e intervallo provengono da min_value/max_value/step (anche per il rangeslider da/a); per la valutazione, max_value determina il numero di livelli (2–10, predefinito 5).
Opzioni di impostazione per visualizzazione (tutte opzionali; i valori non adatti vengono ignorati durante il rendering):
| Proprietà | Vale per | Significato |
|---|---|---|
variant_axis_labels |
slider |
Etichette personalizzate sotto il cursore, separate da punto e virgola (ad es. economico;medio;caro); ha priorità su datalist |
slider_allow_input |
slider, rangeslider |
true = il valore può anche essere digitato in un campo numerico |
range_default_von / range_default_bis |
rangeslider + da/a standard |
Preimposta «da» e «a» separatamente (ha priorità su default_value, che riempie entrambi i lati allo stesso modo); sul cursore i valori preimpostati — a differenza delle manopole non toccate — vengono inviati |
scale_label_left / scale_label_right |
stars, nps, likert |
Etichette degli estremi della scala |
rating_symbol |
stars |
stars (predefinito), hearts, smileys (scala dell'umore, 2–5 livelli; oltre, fallback sulle stelle) o custom (icona personalizzata tramite rating_custom_icon) |
rating_custom_icon |
stars |
Nome di icona Tabler per rating_symbol: "custom" (non valido/vuoto ⇒ stelle) |
variant_tile_size |
cards, icons, images |
compact o large (vuoto = normale) |
variant_image_ratio |
images |
square o 16x9 (vuoto = 4:3) |
variant_image_fit |
images |
contain = adattare l'immagine intera (vuoto = riempire/ritagliare) |
multiselect_min_selected / multiselect_max_selected |
visualizzazioni a selezione multipla | Numero minimo/massimo di opzioni selezionabili (imposto lato browser) |
calendar_date_mode |
calendar |
future (solo da oggi) o past (solo fino a oggi) |
calendar_min_date / calendar_max_date |
calendar |
Data minima/massima fissa (YYYY-MM-DD); ha priorità su calendar_date_mode |
calendar_disable_weekends |
calendar |
true = bloccare i fine settimana |
yesno_yes_label / yesno_no_label |
yesno |
Etichette personalizzate dei pulsanti (vuoto = «Sì»/«No» nella lingua dell'account) |
yesno_icons |
yesno |
true = icone sui pulsanti (predefinito spunta/croce) |
yesno_yes_icon / yesno_no_icon |
yesno |
Icone Tabler personalizzate al posto di spunta/croce (hanno effetto solo con yesno_icons: true) |
variant_columns |
radio, checkboxes |
Colonne dell'elenco: 1–3 (su mobile sempre una sola colonna) |
variant_centered |
pulsanti/riquadri/chips/yesno/stars/nps/calendar/cursori |
true = centrato invece che allineato a sinistra (nei cursori, il campo di inserimento) |
variant_icon_color |
icons, yesno, buttons, likert |
Colore icona personalizzato in esadecimale (#RRGGBB); vuoto = eredita il colore del testo |
Nota selezione multipla: Le visualizzazioni a riquadri/elenchi mostrano le opzioni in modo piatto; lì non esiste l'automatismo padre-figlio. Il
multiselect_modesalvato non viene modificato quando imposti una variante di visualizzazione e torna ad avere effetto non appena ripristini la visualizzazione standard.
Nota cursore: Il cursore semplice — come il cursore da/a — invia un valore solo dopo un'interazione; un cursore non toccato si comporta come un campo vuoto.
Nota: Il range-slider precedente tramite
special_field: "range"continua a funzionare invariato (legacy). Per i nuovi cursori consigliamodisplay_variant: "slider"— se un campo ha entrambi impostati, vincedisplay_variant.
Il Campo di collegamento (visualizzare, collegare, creare, modificare e scollegare i record onOffice collegati) si crea con onoffice_module: "relationlist". Il tipo di relazione è composto da relation_type (ad es. estate:address:owner) più relation_anchor_module (estate o address – quale lato è il record caricato nel modulo); a questi si aggiungono gli interruttori relation_show_existing, relation_allow_search, relation_allow_create, relation_allow_edit, relation_allow_remove, il controllo dei duplicati (relation_duplicate_check + relation_duplicate_check_fields) e l'elenco degli elementi del mini-modulo relation_subform_elements (array di {type: "field", name, required, half} oppure elementi di layout {type: "headline"|"description"|"dividingline"|"collapsible", text}). Per la creazione ci sono inoltre relation_advisor_mode (anchor = usa il referente del record caricato, fixed = utente fisso da relation_advisor_user_id) e relation_auto_open_create (apri automaticamente il mini-modulo quando non sono visualizzati collegamenti). Tutti i valori e i limiti sono riportati nella referenza dei campi.
curl -X POST https://propform.io/api/v1/forms/123/fields \
-H "Authorization: Bearer pf_live_DEIN_KEY" \
-H "Content-Type: application/json" \
-d '{
"onoffice_module": "relationlist",
"relation_type": "estate:address:owner",
"relation_anchor_module": "estate",
"label": "Proprietario",
"relation_show_existing": true,
"relation_allow_create": true,
"relation_subform_elements": [
{"type": "field", "name": "Vorname", "half": true},
{"type": "field", "name": "Name", "required": true, "half": true},
{"type": "field", "name": "Email", "required": true}
]
}'
Ordinamento: nel caso di reorder, l’ordine nell’array field_ids determina la nuova posizione. L'array deve contenere esattamente tutti gli ID dei campi del modulo (se ne manca uno o ne è presente uno estraneo → 422):
curl -X PATCH https://propform.io/api/v1/forms/123/fields/reorder \
-H "Authorization: Bearer pf_live_DEIN_KEY" \
-H "Content-Type: application/json" \
-d '{"field_ids": [4712, 4711, 4713]}'
GET /onoffice/fields fornisce la configurazione dei campi del tuo account onOffice – per ogni modulo (address, estate, task, calendar, agentsLog, file, project) tutti i campi con etichetta, tipo, lunghezza e valori consentiti. In questo modo puoi trovare i valori validi per onoffice_field_name. Con ?module=address puoi filtrare per un modulo.
{
"data": {
"address": {
"Vorname": { "label": "Vorname", "type": "varchar", "length": 50, "default": null, "permittedvalues": null },
"Anrede": { "label": "Anrede", "type": "singleselect", "length": null, "default": null,
"permittedvalues": { "HERR": "Herr", "FRAU": "Frau" } }
}
}
}
> È necessario che la connessione all’API di onOffice funzioni correttamente; in caso contrario, l’endpoint risponde con 409.
POST /onoffice/fields/refresh ricarica la configurazione dei campi da onOffice, ad esempio dopo aver creato un campo o modificato i valori consentiti in onOffice. L'aggiornamento viene eseguito in background: la risposta è 202 con data.status = pending; pochi secondi dopo, GET /onoffice/fields restituisce il nuovo stato. Entrambi gli endpoint restituiscono un oggetto meta con la data dell'ultima generazione (updated_at), la lingua delle etichette dei campi (locale) e refresh_pending (true finché è ancora in corso un aggiornamento avviato tramite l'API). Senza questa chiamata, propform aggiorna la configurazione una volta al giorno e ogni volta che viene aperta la panoramica dei moduli. Limite: 120 chiamate all'ora.
{
"message": "…",
"data": { "status": "pending", "already_pending": false },
"meta": { "updated_at": "2026-09-08T06:12:41+02:00", "locale": "de", "refresh_pending": true, "last_refresh_failed": false }
}
| Metodo | Endpoint | Descrizione |
|---|---|---|
GET |
/forms/{id}/rules |
Regole di un modulo (ordinate per priorità) |
PUT |
/forms/{id}/rules |
Sostituisci tutte le regole del modulo (array vuoto = elimina tutte) |
L'endpoint di scrittura funziona come l'editor delle condizioni nella dashboard: tutte le regole vengono sempre salvate in una volta sola (non è possibile aggiungerne una singola alla volta). Quindi, leggi prima con GET, modifica l’elenco e invialo per intero tramite PUT. Una regola è costituita da clauses (condizioni «Se», collegate a mode = all/any) e actions (azioni "allora"):
curl -X PUT https://propform.io/api/v1/forms/123/rules \
-H "Authorization: Bearer pf_live_DEIN_KEY" \
-H "Content-Type: application/json" \
-d '{"rules": [{
"title": "Zusatzfeld einblenden",
"mode": "all", "priority": 10, "is_enabled": 1, "run_on_init": 1,
"clauses": [{"when_field_id": "4711", "operator": "equals", "value": "Ja"}],
"actions": [{"order": 10, "action": "show", "target_field_id": "4712"}]
}]}'
equals, not_equals, empty, not_empty, starts_with, not_starts_with, contains, not_containsshow, hide, enable, disable, require, optional, hide_option, unhide_option, set_value, set_label, make_readonly, unmake_readonly, enable_rules_by_tag, disable_rules_by_tag__form_title, __form_description, __submit, __submit_spinner, __multistep_back, __multistep_next (in questo caso solo set_label, show, hide; per lo spinner solo set_label).403).Per i dettagli sul funzionamento delle regole, consulta Condizioni, regole e calcoli.
| Metodo | Endpoint | Descrizione |
|---|---|---|
GET |
/forms/{id}/submissions |
Invii di un modulo. Filtro: created_after, created_before, sort (asc/desc), per_page |
GET |
/submissions/{id} |
Invio singolo |
GET |
/forms/{id}/stats |
Visualizzazioni, invii e tasso di conversione; opzionale from/to (data) |
Il contenuto di un invio (content) è raggruppato in base ai moduli di onOffice:
{
"data": {
"id": 456, "form_id": 123, "index": 42,
"content": { "address": { "Vorname": "Max", "Name": "Mustermann" }, "estate": { "Id": "131" } },
"ip_address": "203.0.113.7",
"created_at": "2026-07-07T08:30:00+00:00"
}
}
Se nelle impostazioni sulla privacy hai disattivato il salvataggio dei dati degli invii, content è sempre null – l’invio viene comunque conteggiato nelle statistiche. La risposta stats contiene views, submissions e conversion_rate.
Invece di interrogare regolarmente gli invii, puoi ricevere notifiche tramite webhook: propform invia immediatamente un POST al tuo URL ogni volta che viene effettuato un nuovo invio.
💡 Puoi gestire i webhook anche nel frontend, senza chiave API: nelle impostazioni alla voce «Webhooks» (per tutti i moduli) oppure direttamente nell'editor dei moduli alla voce «Webhook (Zapier, n8n, Make …)».
| Metodo | Endpoint | Descrizione |
|---|---|---|
GET |
/webhooks |
Elenca i tuoi abbonamenti ai webhook |
POST |
/webhooks |
Crea un abbonamento: url (obbligatorio), form_id (facoltativo – se non specificato, l’abbonamento si applica a tutti i tuoi moduli), payload_template (facoltativo – vedi sotto), message_key (facoltativo – nome del campo del messaggio risolto, predefinito text) |
DELETE |
/webhooks/{id} |
Elimina abbonamento |
Requisiti per l’URL: deve essere accessibile pubblicamente e utilizzare http:// o https://. Gli indirizzi interni o locali (ad es. localhost, 127.0.0.1, IP di reti private) vengono rifiutati per motivi di sicurezza (422). Poiché i dati inviati vengono trasmessi, utilizza se possibile https://.
La risposta generata al momento della creazione contiene l’secret, con cui viene firmata ogni consegna (puoi recuperarlo in qualsiasi momento tramite GET /webhooks):
{
"data": {
"id": 7, "event": "submission.created",
"url": "https://example.com/hook", "form_id": 123,
"secret": "a1b2c3…", "payload_template": null, "message_key": "text", "is_active": true,
"failure_count": 0, "last_success_at": null, "last_failure_at": null,
"created_at": "2026-07-07T08:30:00+00:00"
}
}
Ogni consegna contiene due intestazioni:
X-Propform-Event – il tipo di evento (attualmente sempre submission.created)X-Propform-Signature – sha256=<HMAC-SHA256 des Request-Bodys mit deinem secret>Esempio di payload:
{
"event": "submission.created",
"created_at": "2026-07-07T08:30:00+00:00",
"form": { "id": 123, "slug": "aB3x…", "custom_slug": "kontakt", "title": "…", "internal_title": "…" },
"submission": { "id": 456, "index": 42, "content": { "address": { "Vorname": "Max" } } },
"onoffice_ids": { "address": { "ID": "789" } }
}
payload_template)Facoltativamente, puoi salvare un modello di testo libero per ogni abbonamento. Dopo ogni invio del modulo, propform vi risolve le macro onOffice (sui record creati o modificati dall'invio) e include il risultato nel payload come campo di messaggio dedicato: ideale come messaggio pronto per Slack e simili, senza dover assemblare nulla nel flusso di lavoro ricevente. Il nome del campo è text per impostazione predefinita (vedi sotto).
Esempio di modello:
Nuova richiesta di _Vorname _Name per _objekttitel → _getEstateLink
nel payload diventa:
"text": "Nuova richiesta di Max Mustermann per Traumwohnung am Stadtpark → https://smart.onoffice.de/…"
Nome del campo del messaggio (message_key): Per impostazione predefinita il campo si chiama text: così Slack, Microsoft Teams e Google Chat interpretano il payload direttamente come messaggio. Discord si aspetta content. Per Zapier/n8n/Make il nome è libero. Puoi modificarlo per ogni webhook tramite il parametro message_key (nel frontend alla voce «Nome del campo del messaggio»).
Da tenere presente:
_getAddressLink, _getEstateLink, …)._objekttitel richiede un immobile collegato). Senza contesto, la macro resta non risolta nel testo.Verifica la firma per assicurarti che la richiesta provenga effettivamente da propform. Calcola l’HMAC sul corpo della richiesta grezzo (non sul JSON analizzato) e confrontalo in tempo reale.
PHP:
$secret = 'DEIN_WEBHOOK_SECRET';
$body = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_PROPFORM_SIGNATURE'] ?? '';
$expected = 'sha256=' . hash_hmac('sha256', $body, $secret);
if (!hash_equals($expected, $signature)) {
http_response_code(403);
exit('Ungültige Signatur');
}
// ab hier: $body ist echt – json_decode($body, true) verarbeiten
Node.js (Express):
const crypto = require('crypto');
// WICHTIG: express.raw() nutzen, damit der Body unverändert bleibt
app.post('/hook', express.raw({ type: 'application/json' }), (req, res) => {
const secret = process.env.PROPFORM_WEBHOOK_SECRET;
const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(req.body).digest('hex');
const got = req.header('X-Propform-Signature') || '';
if (expected.length !== got.length ||
!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(got))) {
return res.status(403).send('Ungültige Signatur');
}
const payload = JSON.parse(req.body.toString());
res.sendStatus(200);
});
2xx. In caso di errori, propform tenta la consegna fino a 3 volte (con un intervallo di attesa).is_active: false, visibile tramite GET /webhooks). A quel punto basta ricrearlo.Le cartelle strutturano la panoramica dei moduli nella dashboard. Ogni modulo si trova al massimo in una cartella (form_folder_id, null = "Senza cartella"). Le cartelle possono avere un sottolivello (parent_id, al massimo due livelli). Da non confondere con i gruppi di moduli, che controllano l'autorizzazione alla copia.
| Metodo | Endpoint | Descrizione |
|---|---|---|
GET |
/form-folders |
Le tue cartelle con ID e numero di moduli |
POST |
/form-folders |
Crea una cartella – è necessario name (max. 100 caratteri), opzionale parent_id (ID di una cartella principale → crea una sottocartella) |
PATCH |
/form-folders/{id} |
Rinomina una cartella (name) e/o spostala (parent_id: ID di una cartella principale o null = cartella principale) |
DELETE |
/form-folders/{id} |
Elimina una cartella – i moduli vengono conservati e tornano in "Senza cartella", le sottocartelle diventano cartelle principali |
L'assegnazione si imposta nel PATCH del modulo tramite form_folder_id (ID di una propria cartella o null). Nell'elenco dei moduli puoi filtrare con ?folder=<id> o ?folder=none.
| Metodo | Endpoint | Descrizione |
|---|---|---|
GET |
/form-groups |
I tuoi gruppi con ID, flag copy e numero di moduli |
POST |
/form-groups |
Crea un gruppo – è necessario solo name |
PATCH |
/form-groups/{id} |
Modifica name e/o copy (possibilità di copiare i moduli di questo gruppo) |
DELETE |
/form-groups/{id} |
Elimina un gruppo – i moduli restano e perdono solo l’assegnazione al gruppo |
Puoi assegnare gli ID dei gruppi nel PATCH del modulo come form_groups (array).
propform può creare un proprio PDF da ogni invio (vedi Generatore PDF). Il modello di un modulo – elenco dei blocchi, design e impostazioni – lo leggi e lo scrivi completamente tramite l’API:
| Metodo | Endpoint | Descrizione |
|---|---|---|
GET |
/forms/{id}/pdf-template |
Leggi il modello (enabled, name, blocks, design, settings); se non ne esiste ancora uno, viene proposto automaticamente a partire dai campi del modulo |
PATCH |
/forms/{id}/pdf-template |
Aggiornamento parziale – vengono modificate solo le parti inviate |
POST |
/forms/{id}/pdf-template/regenerate |
Rigenera l’elenco dei blocchi dai campi attuali del modulo (design, impostazioni e stato attivo restano invariati) |
GET |
/forms/{id}/pdf-template/preview |
Anteprima PDF reale con dati di esempio (application/pdf; max 10 richieste/minuto) |
GET |
/account/pdf-design |
Leggi il preset di design valido per tutto l’account (design + settings) |
PATCH |
/account/pdf-design |
Modifica il preset di design – i nuovi modelli dei moduli lo ereditano come punto di partenza |
curl -X PATCH https://propform.io/api/v1/forms/123/pdf-template \
-H "Authorization: Bearer pf_live_DEIN_KEY" \
-H "Content-Type: application/json" \
-d '{"enabled": true, "design": {"accent_color": "#0d6efd"}}'
Caratteristiche importanti:
regenerate (sostituisce le tue personalizzazioni dei blocchi!) oppure integra i blocchi in modo mirato tramite PATCH.settings.document_signing.enabled, propform provvede automaticamente a un blocco firma del documento nel modello (se non ne è già presente uno).blocks è un array di blocchi. Ogni blocco ha type, un id assegnato automaticamente e proprietà specifiche del tipo (max. 300 blocchi per modello):
| Tipo | Proprietà |
|---|---|
heading |
text (max. 500 caratteri), level (1, 2 o 3) |
paragraph |
text (max. 5.000 caratteri) |
field |
Singolo campo con valore: field_id (campo di questo modulo) oppure onoffice (riferimento, vedi sotto), label facoltativo |
fieldlist |
Elenco etichetta-valore: field_ids = array di ID di campi e/o riferimenti onOffice |
columns |
Due colonne: left e right sono ciascuno array di blocchi (un solo livello di profondità) |
image |
url (http/https), width_percent (10–100), align (left/center/right), caption |
divider |
style: line (linea) o space (spazio) |
pagebreak |
Interruzione di pagina, nessuna proprietà |
signature |
field_id = campo firma del modulo oppure null = firma del documento dopo l’invio; label; required (solo per la firma del documento) |
Riferimenti onOffice: in field/fieldlist puoi riportare, al posto di un ID di campo, anche un campo del record onOffice collegato: {"module": "address", "name": "Telefon1", "label": "Telefono"} (moduli address ed estate; il campo deve esistere nella tua configurazione dei campi onOffice).
Esempio:
{
"blocks": [
{"type": "heading", "text": "Autocertificazione dell'inquilino", "level": 1},
{"type": "paragraph", "text": "Dati dell'interessato:"},
{"type": "fieldlist", "field_ids": [4711, 4712, {"module": "estate", "name": "objekttitel", "label": "Immobile"}]},
{"type": "pagebreak"},
{"type": "signature", "field_id": null, "label": "Luogo, data, firma", "required": true}
]
}
Chiavi di design (design): font, heading_font, font_size (7–14), text_color/heading_color/accent_color (esadecimali), logo_url, logo_position (left/center/right), logo_width_mm (10–90), label_column_width (20–60), header_text, footer_text, show_page_numbers, letterhead_id (vedi Carte intestate) e letterhead_margin_top/right/bottom/left (0–100 mm, null = margini della carta intestata).
Chiavi delle impostazioni (settings): empty_fields (hide/dash/blank), embed_uploaded_images, attach_uploaded_pdfs, embed_existing_files, embedded_image_size (small/column/full), document_signing.enabled.
La tua carta intestata (PDF o immagine) viene posta come sfondo sotto ogni pagina del PDF generato – facoltativamente con un foglio successivo dedicato a partire dalla pagina 2:
| Metodo | Endpoint | Descrizione |
|---|---|---|
GET |
/letterheads |
Le tue carte intestate; con ?form_id= esattamente quelle selezionabili in questo modulo |
POST |
/letterheads |
Carica (multipart/form-data, vedi sotto) |
PATCH |
/letterheads/{id} |
Modifica letterhead_name e i margini |
DELETE |
/letterheads/{id} |
Elimina – i modelli che la utilizzano tornano poi al layout standard |
Parametri di caricamento (POST, multipart): letterhead_name (obbligatorio), letterhead_first (obbligatorio, PDF/PNG/JPG fino a 10 MB – il primo foglio), letterhead_continuation (facoltativo – il foglio successivo, stesso tipo di file), letterhead_margin_top/right/bottom/left (facoltativi, mm), form_id (facoltativo – in questo modo la carta intestata diventa privata del modulo; senza, finisce nella libreria dell’account).
curl -X POST https://propform.io/api/v1/letterheads \
-H "Authorization: Bearer pf_live_DEIN_KEY" \
-F "letterhead_name=Carta intestata aziendale" \
-F "letterhead_first=@briefbogen.pdf" \
-F "letterhead_continuation=@folgebogen.pdf"
422. Le immagini a bassa risoluzione vengono accettate, ma in tal caso la risposta contiene un avviso nel campo warning.design.letterhead_id nel PATCH del modello PDF (le carte intestate dell’account ovunque, quelle private del modulo solo nel rispettivo modulo).| Metodo | Endpoint | Descrizione |
|---|---|---|
GET |
/account |
Leggi le impostazioni dell’account raggruppate |
PATCH |
/account |
Aggiornamento parziale – vengono modificati solo i gruppi/campi inviati |
La risposta è raggruppata secondo le sezioni delle impostazioni della dashboard:
| Gruppo | Contenuto | Modificabile |
|---|---|---|
profile |
name (nome del profilo/dell’azienda) |
✅ |
styling |
Tutti i valori predefiniti di design default_* per i nuovi moduli (colori, font, logo, aspetto delle schede …) |
✅ |
imprint |
Note legali standard: default_privacypolicy_url, default_imprint_url, default_homepage_url, da default_imprint_line_1 a _5 |
✅ |
notifications |
Fino a 3 destinatari delle notifiche tecniche (notification_email_1–3) + notification_self |
✅ |
statistics |
save_submission_data, save_ips (privacy) |
✅ |
domain |
username (sottodominio), externaldomain, externaldomain_active |
❌ solo lettura |
staff_area |
enabled, session_days (1–90), seat_limit + active_members (solo lettura) |
parzialmente |
curl -X PATCH https://propform.io/api/v1/account \
-H "Authorization: Bearer pf_live_DEIN_KEY" \
-H "Content-Type: application/json" \
-d '{"styling": {"default_accent_color": "#0d6efd"}, "statistics": {"save_ips": false}}'
domain è di sola lettura per scelta: un cambio di sottodominio o dominio romperebbe tutti i link ai moduli già incorporati – questa operazione è possibile solo nella dashboard.staff_area.enabled può essere attivato solo se il tuo piano include posti collaboratore (seat_limit > 0, altrimenti 422). seat_limit stesso deriva dal piano e non è modificabile.notifications vengono salvati come elenco compatto: dopo il salvataggio le posizioni vuote vengono compattate.| Metodo | Endpoint | Descrizione |
|---|---|---|
GET |
/account/onoffice |
Stato della connessione e impostazioni dell’integrazione onOffice |
PATCH |
/account/onoffice |
Modifica le impostazioni (max. 5 richieste/minuto) |
La risposta contiene tra l’altro api_type (normal/marketplace_api), connection_ok, credentials_set, email_onoffice_api_user (+ _is_functional), field_config_locale e reason_cancellation. Per motivi di sicurezza, il token e il secret dell’API non compaiono in nessuna risposta.
Modificabili tramite PATCH:
| Campo | Significato |
|---|---|
api_type |
normal (credenziali API onOffice proprie) oppure marketplace_api (integrazione Marketplace; richiede un utente Marketplace collegato) |
email_onoffice_api_user |
Identità e-mail dell’utente API come array (max 10) – ogni indirizzo viene verificato con un invio di prova |
email_onoffice_marketplace_api_user |
idem per l’integrazione Marketplace |
field_config_locale |
Lingua delle etichette dei campi onOffice (de, en, …) – la cache della configurazione dei campi viene poi ricostruita in background |
reason_cancellation |
Motivi di rifiuto personalizzati come array (max. 50 voci, 40 caratteri ciascuno; vuoto = elenco standard) |
I moduli con la protezione di accesso per collaboratori attivata sono raggiungibili solo dopo il login tramite magic link. I collaboratori e i gruppi alla base li gestisci tramite API:
| Metodo | Endpoint | Descrizione |
|---|---|---|
GET |
/staff-members |
Collaboratori inclusa l’assegnazione ai gruppi, source (onoffice/manual) e is_active |
POST |
/staff-members |
Crea un collaboratore esterno: name, email, facoltativo groups (array di ID di gruppi) |
PATCH |
/staff-members/{id} |
Aggiornamento parziale: name, email (solo per quelli manuali), groups, is_active |
DELETE |
/staff-members/{id} |
Elimina un collaboratore (termina anche le sessioni in corso) |
POST |
/staff-members/import-onoffice |
Importa utenti onOffice: onoffice_user_ids (array, facoltativo – se non specificato, tutti quelli importabili). Risposta: created, updated |
GET |
/staff-groups |
Gruppi incluso il numero di membri (onoffice_group_id impostato = replicato da onOffice) |
POST |
/staff-groups |
Crea un gruppo locale (name) |
DELETE |
/staff-groups/{id} |
Elimina un gruppo |
staff_area.seat_limit in /account) viene applicato rigorosamente alla creazione, all’attivazione e all’importazione (422). Solo i collaboratori attivi occupano un posto.is_active: false) termina immediatamente tutte le sessioni in corso del collaboratore.staff_only_enabled, staff_allowed_member_ids e staff_allowed_group_ids nel PATCH del modulo; gli interruttori a livello di account (staff_area.enabled, session_days) si trovano in /account.GET /forms/{id}/submissions?sort=desc e del valore più alto già elaborato id.GET /me.GET /forms?updated_since=….429 inserire una breve attesa e rispettare l’intestazione Retry-After.La versione attuale è v1 ed è fissata nel percorso (/api/v1). Aggiungiamo nuovi campi ed endpoint in modo retrocompatibile senza modificare la versione; pertanto, il tuo client dovrebbe semplicemente ignorare i campi sconosciuti presenti nelle risposte. Modifiche fondamentali e non retrocompatibili verrebbero pubblicate con una nuova versione (/api/v2).