Dokumentacja API do tworzenia formularzy przez HTTP.
Autoryzacja: Wszystkie requesty wymagają Authorization: Bearer TOKEN
API Endpoints
Forms (Formularze)
| Metoda | Ścieżka | Opis |
|---|---|---|
| GET | /form/forms.json |
Lista formularzy |
| GET | /form/forms/:id.json |
Szczegóły formularza |
| POST | /form/forms.json |
Utworzenie formularza |
| PATCH | /form/forms/:id.json |
Aktualizacja formularza |
| DELETE | /form/forms/:id.json |
Usunięcie formularza |
Results (Wyniki / Zgłoszenia)
| Metoda | Ścieżka | Opis |
|---|---|---|
| GET | /form/results.json |
Lista wyników |
| POST | /form/results/save |
Zapisanie wyniku (publiczne, bez auth) |
| POST | /form/results/:id/close |
Zamknięcie zgłoszenia (open otwiera z powrotem) |
| POST | /form/results/change_bulk_option_multiple |
Akcja masowa na paczce: ids[] + close=true/open=true albo client_id/department_id/project_id
|
Pola modeli
Form
| Pole | Typ | Wymagane | Opis |
|---|---|---|---|
name |
string | tak | Nazwa formularza |
description |
string | nie | Opis |
lang |
string | nie | Język (pl, en) |
date_from |
date | nie | Formularz aktywny od |
date_to |
date | nie | Formularz aktywny do |
team_id |
integer | nie | ID zespołu |
department_id |
integer | nie | ID działu |
mapping |
string | nie | Mapowanie wyniku na obiekt: client, task, deal, email
|
mapping_options |
object | nie | Opcje mapowania (JSON) |
mapping_mailbox_id |
integer | nie | ID skrzynki, w której powstaje e-mail (wymagane przy mapping: "email"; zapisywane w fields) |
fields |
object | nie | Konfiguracja formularza (JSON) |
Pola w fields:
| Klucz | Typ | Opis |
|---|---|---|
submit_text |
string | Tekst przycisku submit (domyślnie: “Wyślij”) |
form_response |
string | Tekst po wysłaniu formularza |
form_redirect |
string | URL przekierowania po wysłaniu |
form_style |
string | Dodatkowe style CSS |
form_class |
string | Klasa CSS formularza |
button_class |
string | Klasa CSS przycisku |
form_anonymous |
integer |
1 = wypełnienie zapisuje się bez adresu IP, przeglądarki i adresu strony, z której przyszło (ip, agent, referrer zostają puste). Nie ma związku z logowaniem - zapis wyniku jest publiczny niezależnie od tej opcji |
use_mailbox_department |
integer |
1 = mail o nowym wypełnieniu formularza bierze nazwę, adres strony, logo i kolor z danych firmy działu przypiętego do skrzynki, z której wychodzi (confirmation_mailbox_id), z zejściem na główny dział konta. Czego dział nie ma, tego w mailu nie ma - marki produktu wtedy nie podstawiamy. Domyślnie 0 - mail wygląda jak marka produktu. W UI ustawiane w edycji formularza, karta pokazuje tylko stan. |
brand_client_email |
integer |
1 = tą samą marką opakowane jest też potwierdzenie dla wypełniającego (nagłówek z logo i stopka wokół treści z confirmation_body, sama treść zostaje nietknięta). Działa tylko razem z use_mailbox_department. Osobna opcja, bo treść tego maila pisze użytkownik i może już mieć własną oprawę. Treści będącej gotowym dokumentem (<html>/<body>, w tym template:Nazwa) nie opakowujemy nigdy. Domyślnie 0. |
mapping_mailbox_id |
integer | ID skrzynki, w której powstaje e-mail przy mapping: "email" (wymagane dla tego mapowania). Można przesłać też jako atrybut mapping_mailbox_id obok mapping - zapisze się w fields. |
FormField (Pole formularza)
Pola formularza dodaje się przy aktualizacji formularza przez form_fields_attributes:
| Pole | Typ | Wymagane | Opis |
|---|---|---|---|
name |
string | tak | Nazwa/etykieta pola |
kind |
string | tak | Typ pola (patrz niżej) |
required |
boolean | nie | Czy pole jest wymagane |
priority |
integer | nie | Kolejność (0 = pierwsze) |
description |
string | nie | Opis/podpowiedź |
regex |
string | nie | Walidacja: email, digits, alphanum
|
map_to |
string | nie | Mapowanie na pole w CRM |
fields |
object | nie | Dodatkowa konfiguracja (JSON) |
_destroy |
boolean | nie |
true aby usunąć pole |
Typy pól (kind):
| Typ | Opis |
|---|---|
string |
Pole tekstowe (jednoliniowe) |
text |
Pole tekstowe (wieloliniowe) |
select |
Lista rozwijana |
radio |
Przyciski radio |
checkbox |
Pola checkbox |
title |
Nagłówek sekcji (bez inputa) |
placeholder |
Tekst opisowy (bez inputa) |
attachment |
Pole do wgrania pliku |
Pola w fields dla FormField:
| Klucz | Typ | Opis |
|---|---|---|
input_placeholder |
string | Placeholder w polu input |
options |
string | Opcje dla select/radio/checkbox (rozdzielone \r\n) |
Tworzenie formularza
Tworzenie formularza odbywa się w 2 krokach:
1. Utwórz formularz (POST)
POST /form/forms.json
Content-Type: application/json
{
"form": {
"name": "Formularz kontaktowy",
"lang": "pl",
"fields": {
"submit_text": "Wyślij",
"form_response": "Dziękujemy za wiadomość!"
}
}
}
Odpowiedź: Zwraca obiekt formularza z id i token.
2. Dodaj pola (PATCH)
PATCH /form/forms/:id.json
Content-Type: application/json
{
"form": {
"form_fields_attributes": [
{
"kind": "string",
"name": "Imię i nazwisko",
"required": true,
"priority": 0,
"fields": { "input_placeholder": "Jan Kowalski" }
},
{
"kind": "string",
"name": "Email",
"required": true,
"priority": 1,
"regex": "email",
"fields": { "input_placeholder": "[email protected]" }
},
{
"kind": "text",
"name": "Wiadomość",
"required": true,
"priority": 2,
"fields": { "input_placeholder": "Twoja wiadomość..." }
}
]
}
}
Osadzanie formularza na stronie
Po utworzeniu formularza, w odpowiedzi API dostępny jest token. Formularz osadza się na stronie za pomocą kodu JS:
<script src="https://widgets.intum.net/widgets/app/intum-forms-widget-1.1.js"></script>
<!-- Intum Form Start -->
<div data-form="TOKEN_FORMULARZA"></div>
<!-- Intum Form End -->
Widget automatycznie:
- Pobiera konfigurację formularza po tokenie
- Renderuje formularz na stronie
- Obsługuje walidację pól
- Wysyła dane przez POST do
/form/results/save - Wyświetla komunikat po wysłaniu lub przekierowuje
Przykład: formularz z select i checkbox
PATCH /form/forms/:id.json
{
"form": {
"form_fields_attributes": [
{
"kind": "select",
"name": "Temat",
"required": true,
"priority": 0,
"fields": { "options": "Pytanie ogólne\r\nWspółpraca\r\nReklamacja" }
},
{
"kind": "checkbox",
"name": "Zgody",
"priority": 1,
"fields": { "options": "Akceptuję regulamin\r\nChcę otrzymywać newsletter" }
}
]
}
}
Mapowanie wyniku
Po wysłaniu formularz może automatycznie utworzyć obiekt. Ustaw mapping na jeden z: client (klient CRM), task (zadanie), deal (szansa sprzedaży), email (wiadomość odebrana). Mapowanie uruchomi się tylko gdy mapping_options.auto_mapping = 1 - bez tego wynik nie tworzy żadnego obiektu:
POST /form/forms.json
{
"form": {
"name": "Lead form",
"mapping": "client",
"mapping_options": {
"auto_mapping": 1
}
}
}
Klucze mapping_options:
| Klucz | Opis |
|---|---|
auto_mapping |
1 włącza mapowanie (wymagane, inaczej nic się nie utworzy) |
client_force_update |
(mapping client) 1 = nadpisuj też wypełnione pola istniejącego klienta (domyślnie uzupełniamy tylko puste) |
client_sensitive_data |
(mapping client) 1 = oznacz klienta jako dane wrażliwe |
Następnie w polach formularza użyj map_to, aby przypisać odpowiedź do atrybutu obiektu:
{
"kind": "string",
"name": "Imię",
"map_to": "name"
}
Dla mapping: "email" trzeba dodatkowo wskazać skrzynkę mapowania (mapping_mailbox_id, trafia do fields) - patrz wymagania niżej.
Wymagania mapowania (inaczej API zwróci 422)
Niekompletne mapowanie jest odrzucane przy zapisie formularza - niezależnie od auto_mapping. Odpowiedź 422 zawiera błąd na atrybucie mapping. Wymagania:
-
mappingtylko z listy:client,task,deal,email. -
auto_mapping: 1bez ustawionegomapping- błąd. - Wybrany
mappingwymaga co najmniej jednego pola zmap_to. - Każde
map_tomusi należeć do wybranego typu (lista pól różni się per typ) i nie może się powtarzać w obrębie formularza. -
mapping: "email"wymaga: skrzynki mapowania (mapping_mailbox_id), nadawcy (pole zmap_to: "from"alboclient_email_field_id) oraz pola zmap_to: "subject". -
mapping: "client"wymaga pola identyfikującego klienta:name,first_name,last_name,email,tax_no,register_numberlubexternal_id.
Formularz można utworzyć jednym requestem razem z polami (form_fields_attributes) - wtedy walidacja widzi już pola. Osobno tworzony formularz bez pól przechodzi (pola dodaje się kolejnym requestem), ale ten request musi już spełniać powyższe wymagania.
Pola referencyjne (podawane po nazwie, nie po ID)
Osoba wypełniająca formularz nie zna wewnętrznych ID, więc pola wskazujące na inny rekord rozwiązujemy po czytelnej wartości. Kolejność prób: surowe ID → numer biznesowy → nazwa (bez rozróżniania wielkości liter).
map_to |
Dotyczy (mapping) |
Rozwiązywane po |
|---|---|---|
client_id |
task, deal, email | ID, external_id, NIP, REGON lub email klienta |
status_id |
client, task, deal, email | nazwie statusu (tylko statusy dozwolone w danym module) |
project_id |
task, client, deal, email | ID, numerze projektu (np. 1/02/2026) lub nazwie |
department_id |
task, deal, client, email | nazwie działu |
team_id |
task | nazwie zespołu |
folder_id |
nazwie folderu poczty |
Pozostałe pola *_id przypisywane są wprost - trzeba podać gotowe ID.
Pozostałe zasady mapowania
-
Pola dodatkowe (custom fields) -
map_tomoże wskazywać na klucz pola dodatkowego; wartość trafi wtedy dofieldsobiektu. -
tag_names- dokłada tagi, ale tylko do nowo utworzonych rekordów (istniejącemu klientowi tagów nie zmienia). - Odpowiedzi wielokrotnego wyboru - łączone w tekst rozdzielony przecinkami.
-
Opiekun - nie ustawia się przez mapowanie; przypisz go regułą automatyzacji (
Automation::Rule) z triggerem na wyniku formularza. -
Istniejący klient - przy
mapping: "client"szukamy klienta po unikalnych identyfikatorach i uzupełniamy tylko puste pola (chyba żemapping_options.client_force_update = 1- wtedy nadpisujemy też wypełnione).
Zabezpieczenia antyspamowe
Widget formularza automatycznie dodaje:
-
Honeypot — ukryte pole
_fax_number(boty je wypełniają, ludzie nie) - Elapsed time — odrzuca wypełnienia wysłane szybciej niż 3 sekundy
Stylowanie formularza (CSS)
Formularz można stylować przez pole fields.form_style. CSS jest wstrzykiwany jako <style> wewnątrz formularza.
Identyfikator formularza: Użyj ~intum_form_id~ w CSS — zostanie zamieniony na ID formularza (np. .intum_form_123).
PATCH /form/forms/:id.json
{
"form": {
"fields": {
"form_style": ".intum_form_~intum_form_id~ input { border: 2px solid #3b82f6; border-radius: 8px; padding: 10px; }\n.intum_form_~intum_form_id~ label { font-weight: 600; color: #1f2937; }\n.intum_form_~intum_form_id~ .intum_button_~intum_form_id~ { background: #2563eb; color: white; padding: 12px 24px; border-radius: 8px; border: none; cursor: pointer; }"
}
}
}
Dostępne selektory CSS:
| Selektor | Element |
|---|---|
.intum_form_~intum_form_id~ |
Kontener formularza |
.intum_form_~intum_form_id~ label |
Etykiety pól |
.intum_form_~intum_form_id~ input |
Pola tekstowe |
.intum_form_~intum_form_id~ textarea |
Pola wieloliniowe |
.intum_form_~intum_form_id~ select |
Listy rozwijane |
.intum_button_~intum_form_id~ |
Przycisk submit |
.intum_form_~intum_form_id~ .form_field |
Kontener pojedynczego pola |
Inne pola konfiguracyjne:
Klucz w fields
|
Opis |
|---|---|
form_class |
Dodatkowa klasa CSS na kontenerze (domyślnie: intum_form_{id}) |
button_class |
Klasa CSS przycisku submit (domyślnie: intum_button_{id}) |
submit_text |
Tekst przycisku submit |
form_response |
Tekst wyświetlany po wysłaniu (obsługuje Liquid) |
form_redirect |
URL przekierowania po wysłaniu |
custom_js |
Własny JavaScript wykonywany po załadowaniu formularza |
Wskazówki
-
Token — po utworzeniu formularza,
tokenjest generowany automatycznie i służy do osadzania -
Kolejność pól — ustalana przez
priority(0 = pierwsze) -
Walidacja email — użyj
regex: "email"na polu -
Opcje select/radio/checkbox — rozdzielaj przez
\r\nw polufields.options -
Usuwanie pól — wyślij
_destroy: truezidpola wform_fields_attributes -
Anonimowy formularz —
fields.form_anonymous: 1sprawia, że przy wypełnieniu nie zapisujemy IP, przeglądarki ani adresu strony (przydatne przy ankietach z obietnicą anonimowości) -
CSS — styluj przez
fields.form_style, używaj~intum_form_id~jako placeholder ID -
PATCH fields — merge nadpisuje! — wysyłając
{"form": {"fields": {"custom_js": "..."}}}Rails merge’uje na poziomie klucza, ale inne klucze (np.form_style) zostaną wyzerowane. Zawsze: (1) GET aktualny formularz, (2) zmodyfikuj potrzebne klucze wfields, (3) wyślij PEŁNY obiektfieldsw PATCH -
form_style vs custom_css —
fields.form_styleto jedyne pole CSS trafiające do widgetu.fields.custom_cssjest nigdzie nie używane — nie wysyłaj go -
Wygląd maila o nowym wypełnieniu formularza — domyślnie marka produktu. Formularz z
fields.use_mailbox_department: 1bierze ją z danych firmy działu przypiętego do skrzynki nadawczej (confirmation_mailbox_id), a gdy skrzynka nie ma działu — z głównego działu konta. Przy włączonej opcji puste pole działu zostaje puste, zamiast schodzić na wartość produktu: dział bez logo daje nagłówek z samą nazwą, a dział bez nazwy nie dostaje ani nagłówka, ani stopki, ani podpisu. Wyjątek:brand_color(tło przycisku) schodzi na kolor produktu. Samej marki nie ustawia się na formularzu: nazwa tocompany_namedziału, adrescompany_website, logocompany_logo, a kolor przycisku tobrand_colorw JSONBfieldsdziału (nie ma własnej kolumny). Logotyp jest skalowany do wysokości 36px z zachowaniem proporcji. -
Podgląd maili — karta formularza (
/form/forms/:id) ma odnośniki do podglądu obu maili, każdy na osobnej stronie:GET /form/forms/:id/notification_email_preview(powiadomienie dla obsługi) iGET /form/forms/:id/client_email_preview(potwierdzenie dla wypełniającego). HTML to gotowa strona z wiadomością,.jsonzwraca{ html }. Zawsze stoją na odpowiedziach na pokaz, zbudowanych z pól formularza - nigdy na prawdziwym wypełnieniu, bo w treści maila widać dane osoby, która formularz wysłała. Nic nie zapisują i nic nie wysyłają. Pusta treść oznacza, że dany mail i tak by nie poszedł: brak skrzynek albo niewypełnione potwierdzenie.
Powiązane
- common_api — wspólne zasady API (format, autoryzacja, odpowiedzi)