Appearance
Form Submission Types
Type: Reference | Audience: Interface builder user and the backend developer your form talks to
A submit button's Form Type setting controls how form data leaves the browser. This page lists the three options and exactly how each one packages and delivers the data — useful both when you configure the button and when you hand off the details to whoever writes the endpoint.
Overview
| Form Type | HTTP request? | Files allowed? | Content-Type | Typical use |
|---|---|---|---|---|
| JSON (default) | Yes — POST | Yes (base64) | application/json | Standard JSON APIs. |
| Multipart/Form-Data | Yes — POST | Yes (binary) | multipart/form-data | File-storage endpoints and legacy APIs. |
| Open view with form data | No | No | n/a | Multi-step flows and filter panels inside the app. |
Pick one, then set the Submit URL (required for JSON and Multipart/Form-Data; ignored for Open view with form data).
JSON
Use when: the endpoint expects a JSON body.
How the request reaches the backend:
POSTrequest to the Submit URL.- Header:
Content-Type: application/json. - Body: one JSON object with two top-level keys,
dataandmeta. - Files are base64-encoded and embedded inside
data.
Body shape:
json
{
"data": {
"username": "john",
"email": "john@example.com",
"profilePhoto": {
"filename": "photo.jpg",
"mimetype": "image/jpeg",
"data": "base64encodedcontent..."
},
"attachments": [
{ "filename": "doc1.pdf", "mimetype": "application/pdf", "data": "..." },
{ "filename": "doc2.pdf", "mimetype": "application/pdf", "data": "..." }
]
},
"meta": {
"button_id": "btn-1",
"company_id": 6789,
"event_id": "abc123",
"interface_view_id": "view-1",
"resource": "deal",
"resource_id": 456,
"user_id": 12345
}
}data— every input in the form, keyed by its internal field name.- A single-file input is one object. A multi-file input — one with Allow multiple files turned on — is always an array, including when the person picked one file, so a receiving service never branches on the file count. See File Fields.
meta— where the submission came from (which view, which button, which Pipedrive resource, which user).company_id,resource_idanduser_idare numbers; the rest are strings.company_idanduser_idare added server-side from the authenticated session and overwrite any client-supplied values.- Any Query parameters you add to the submit button are appended to the URL.
Body shape from a floating window button: that run has no Pipedrive record, so resource and resource_id are sent as null. Both keys stay in place — the payload shape is the same on both kinds of button, and every other meta value is unchanged:
json
{
"data": {
"username": "john",
"email": "john@example.com"
},
"meta": {
"button_id": "btn-1",
"company_id": 6789,
"event_id": "abc123",
"interface_view_id": "view-1",
"resource": null,
"resource_id": null,
"user_id": 12345
}
}The values are never faked: a missing record is null, never 0 and never "".
With Omit oneclick metadata on: the body is just the inner data object — no meta, no outer wrapping. Use this for endpoints that reject unknown fields (for example Pipedrive API v2):
json
{
"username": "john",
"email": "john@example.com",
"profilePhoto": { "filename": "photo.jpg", "mimetype": "image/jpeg", "data": "..." }
}After submission: both Select view and Wait for response are available.
Multipart/Form-Data
Use when: the endpoint expects a multipart upload — file-storage APIs, legacy endpoints that cannot parse JSON, or anything that wants files as raw binary instead of base64.
How the request reaches the backend:
POSTrequest to the Submit URL.- Header:
Content-Type: multipart/form-data(the browser adds the correct boundary automatically). - Every form field is a separate part. The part name starts with
data_for form inputs andmeta_for context.
Parts:
meta_button_id: "btn-1"
meta_company_id: "6789"
meta_event_id: "abc123"
meta_interface_view_id: "view-1"
meta_resource: "deal"
meta_resource_id: "456"
meta_user_id: "12345"
data_username: "john"
data_email: "john@example.com"
data_profilePhoto: (binary, filename="photo.jpg")
data_attachments[0]: (binary, filename="doc1.pdf")
data_attachments[1]: (binary, filename="doc2.pdf")data_*— form input values, keyed by the input's internal field name.meta_*— the same context as themetaobject in JSON mode (company_idanduser_idare added server-side from the authenticated session). Multipart is a text transport, so every value arrives as a string.- Single-file inputs land at
data_<field>. Multi-file inputs — those with Allow multiple files turned on — are always indexed:data_<field>[0],data_<field>[1], and so on, including when the person picked one file. See File Fields.
Parts from a floating window button: multipart form data cannot carry null, and the string "null" would be a lie. So instead of a placeholder value, the two record parts are not sent at all — five meta_* parts arrive instead of seven:
meta_button_id: "btn-1"
meta_company_id: "6789"
meta_event_id: "abc123"
meta_interface_view_id: "view-1"
meta_user_id: "12345"
data_username: "john"
data_email: "john@example.com"Read the absence of the part as "there is no record". Nothing is sent as 0 or "".
With Omit oneclick metadata on: the meta_* parts are not sent and the data_ prefix on form inputs is dropped — every input goes through under its bare name. The Content-Type is still multipart/form-data:
username: "john"
email: "john@example.com"
profilePhoto: (binary, filename="photo.jpg")
attachments[0]: (binary, filename="doc1.pdf")
attachments[1]: (binary, filename="doc2.pdf")After submission: both Select view and Wait for response are available.
File Fields
Read this before you write the endpoint. What decides whether a file field arrives as an array is the input's Allow multiple files setting — never how many files the person happened to pick.
| The input | JSON | Multipart/Form-Data |
|---|---|---|
| Allow multiple files off | One object under <field> | One part named data_<field> |
| Allow multiple files on | Always an array under <field> | Always indexed parts data_<field>[0], data_<field>[1], … |
The two shapes below come from the same submission: a form with a single-file input named profilePhoto and a multi-file input named attachments, where the person picked one file into each.
json
{
"data": {
"profilePhoto": {
"filename": "photo.jpg",
"mimetype": "image/jpeg",
"data": "base64encodedcontent..."
},
"attachments": [
{ "filename": "doc1.pdf", "mimetype": "application/pdf", "data": "..." }
]
}
}data_profilePhoto: (binary, filename="photo.jpg")
data_attachments[0]: (binary, filename="doc1.pdf")attachments is an array of one, and stays an array when the person picks five. So the endpoint reads a multi-file field with one code path and never counts first.
An empty multi-file selection is not an empty array
A multi-file input the person never touched — or emptied again — arrives as the empty string, exactly as an empty single-file input always has. It never arrives as []. The field is still present, so testing for the key is not enough — check the value before you iterate.
json
{ "data": { "attachments": "" } }data_attachments: ""In multipart the field arrives as an ordinary text part with an empty value: no indexed parts, and no filename.
A form built before Allow multiple files existed forwards exactly the payload it always did — the setting is off by default, and an input with it off is untouched by this rule.
One exception — the redirect URL, not the payload. When After submission is Select view, every selected file also becomes a URL parameter carrying its file name, and those parameters are indexed for both kinds of input: attachments[0]=doc1.pdf. That was true before this rule existed and has not changed, so a view already reading attachments[0] keeps working.
File Size Limits
A submission that carries files is weighed against a byte budget before anything is forwarded. The budget belongs to the Form Type:
| Form Type | Budget for the files of one submission |
|---|---|
| JSON | 10 MB |
| Multipart/Form-Data | 100 MB |
- The budget is one cap per submission, across every file field together. Two file inputs in the same form share it, and so do the several files of one multi-file input. It is not a per-file limit and not a per-field limit.
- A submission over budget gets HTTP
413back and is never forwarded to the Submit URL. The message names both the budget and the size the submission carried, and the user sees it as an error toast. - A Multipart/Form-Data submission over 100 MB is stopped while the request is still being read, before the budget is ever weighed. It fails, but not with the
413above, and the error the user sees is not the clear message this section describes. 100 MB is the size limit on the whole request as well as the multipart budget. - MB means 1 048 576 bytes, the same unit the file input's own size display uses.
- JSON gets the smaller budget because it embeds each file as base64 — the payload the server has to build in memory ends up several times the size of the files themselves. Multipart holds the files in memory too, but roughly once and without the base64 inflation, so it can afford the larger number. A form that needs to move more than 10 MB belongs on Multipart/Form-Data.
- A file input's own Max File Size, Max Total Size and Max Number of Files settings are separate, browser-side checks. They can only narrow what a person is allowed to pick; none of them raises the budget above the numbers in the table, and the server puts no cap on the file count at all.
Open view with form data
Use when: the submit should not call an API at all, but instead jump the user to another view and carry the form values along as URL parameters. Useful for multi-step flows, search forms, and filter panels inside the interface.
How it works:
- No HTTP request is made. Any Submit URL is ignored.
- The user is navigated to the view picked in the View ID field of the After submission setting.
- Every form input value is appended as a URL search parameter on that navigation.
Restrictions:
- The File input type is not allowed — the submission cannot pass binary data through a URL.
- After submission must be Select view (since there is no server to wait for).
How values end up in the URL:
- Each input's internal name becomes the URL key, and the input's value becomes the URL value. Form input values are always included on the navigation — there is no opt-out at runtime for this form type.
- Any explicit Parameters you set on the submit button are merged on top.
- The Use input values as search params toggle on the submit button does not affect runtime URL building — input values are forwarded regardless. The toggle is a design-time hint that adds the form's inputs to the Expected Parameters from Views list in the target view's URL Configuration dialog, so you can recognise them when wiring up that view's data source.
Resulting URL example:
/interfaces/{viewId}?username=john&email=john@example.com&customParam=valueReading the parameters in the target view:
Open the Data Picker in the target view, switch to the Search Params tab, and pick the key you need. The placeholder resolves to the string value at runtime, for example username.
Forms Inside a Looping Area
When a form's input rows sit inside a looping Area, every iteration renders its own copy of each input. Two things change in the submission.
Field names get an iteration suffix. The first iteration keeps the original field names; every later iteration appends _loop_N (N starting at 1). A looped input name submits as name, name_loop_1, name_loop_2, and so on.
The payload gains an oc_loop array. One object per iteration, each grouping the looped fields' values under their base field names. The array is purely additive — the flat suffixed fields are always sent alongside it.
JSON mode — oc_loop is a genuine array inside data:
json
{
"data": {
"name": "ads",
"name_loop_1": "muu",
"oc_loop": [
{ "name": "ads" },
{ "name": "muu" }
]
},
"meta": { "...": "..." }
}Multipart/Form-Data mode — multipart is a flat transport, so the array travels as a JSON string in a data_oc_loop part:
data_name: "ads"
data_name_loop_1: "muu"
data_oc_loop: "[{\"name\":\"ads\"},{\"name\":\"muu\"}]"With Omit oneclick metadata on: oc_loop is form data, not metadata, so it stays — in JSON mode inside the flat body, in multipart mode under the bare oc_loop part name.
Rules:
- The key is present only when the submitted form contains looped fields. Zero iterations remove the looped rows entirely — no fields, no
oc_loopkey. - All loops in one form share the single
oc_looparray, grouped by iteration index. - File inputs are excluded from the array — files arrive as flat fields only.
- Disabled looped inputs contribute their default values like any other looped field.
oc_loopis a reserved name. A form input the admin namesoc_loopis overwritten by the generated array.- A field name that merely looks looped (an input manually named
something_loop_1) stays out of the array — only fields rendered by a loop participate. - Open view with form data is unaffected: the URL carries the flat suffixed fields only, never an
oc_loopparameter.
Comparison
| Aspect | JSON | Multipart/Form-Data | Open view with form data |
|---|---|---|---|
| HTTP request | POST | POST | None |
| Content-Type | application/json | multipart/form-data | — |
| Files | Base64 inside JSON | Binary parts | Not allowed |
| File budget per submission | 10 MB | 100 MB | — |
| Submit URL | Required | Required | Ignored |
| After submission | Both options | Both options | Select view only |
| Context data (default) | meta object | meta_* parts | Not sent |
| Input values (default) | data object | data_* parts | URL search params |
| Looped fields | data.oc_loop array + flat suffixed fields | data_oc_loop JSON string + flat suffixed parts | Flat suffixed URL params only |
With Omit oneclick metadata | Body is just the inner data object | No meta_* parts; data_ prefix dropped from input parts | n/a |
What the Backend Should Return
When the submission actually calls the server (JSON and Multipart/Form-Data), the response controls what the user sees next — a toast, an inline alert that replaces the form, or a navigation. See HTTP Response Format for the exact shapes.