A form is a hosted sign-up, contact or waitlist form that creates or updates contacts and records the consent they give. Forms share a public link and can be embedded in your site; a submission returns 409 FORM_CLOSED once the form is closed by hand, by date or by its limit.
Endpoints
| Endpoint | Request |
|---|---|
| List forms | GET /v1/forms |
| Create a form | POST /v1/forms |
| Retrieve a form | GET /v1/forms/{id} |
| Update a form | PATCH /v1/forms/{id} |
| Delete a form | DELETE /v1/forms/{id} |
| List a form's submissions | GET /v1/forms/{id}/submissions |
| Submit a form | POST /v1/forms/{id}/submissions |
| Publish a form | POST /v1/forms/{id}/publish |
| Unpublish a form | POST /v1/forms/{id}/unpublish |
| Archive a form | POST /v1/forms/{id}/archive |
| Unarchive a form | POST /v1/forms/{id}/unarchive |
| Retrieve a form's metrics | GET /v1/forms/{id}/metrics |
The Form object
{
"id": "0192f3e1-2b3c-7d4e-9f50-6b7c8d9e0f1a",
"publicId": "frm7k2m9q4x1c8v3b6n5t0za",
"slug": "acme-newsletter",
"name": "Newsletter signup",
"heading": "Join the Acme Shop newsletter",
"intro": "New arrivals and offers, once a week.",
"location": "website-footer",
"url": "https://forms.kirora.io/f/acme-newsletter",
"status": "published",
"listId": "0192f3a2-1b3c-7e5d-8a21-4f6a7b8c9d0e",
"fields": [
{
"key": "email",
"type": "email",
"label": "Email address",
"placeholder": "[email protected]",
"required": true
},
{
"key": "firstName",
"type": "text",
"label": "First name",
"required": false
}
],
"hiddenFields": {
"signup_campaign": {
"source": "link",
"param": "utm_campaign"
}
},
"share": {
"title": "Get the Acme Shop newsletter"
},
"acceptingSubmissions": true,
"closesAt": null,
"maxSubmissions": null,
"closedMessage": null,
"submissionCount": 1240,
"allowedOrigins": [
"https://acme-shop.com"
],
"refusedOrigins": [],
"doubleOptIn": true,
"notifyUserIds": [],
"theme": {
"accentColor": "#b4461f",
"fontFamily": "sans",
"buttonLabel": "Subscribe"
},
"display": {
"mode": "inline"
},
"captcha": null,
"consent": {
"required": true,
"label": "I agree to receive emails from Acme Shop and can unsubscribe at any time."
},
"success": {
"type": "message",
"message": "Thanks. Check your inbox to confirm."
},
"archivedAt": null,
"createdAt": "2026-10-01T09:30:00.000Z",
"updatedAt": "2026-10-02T14:05:00.000Z"
}idstringrequireduuid
publicIdstringrequiredThe id the public embed and hosted page use.
pattern
^[a-z0-9]{24}$slugstring | nullrequiredThe readable part of the form's link;
nullusespublicIdalone.namestringrequiredheadingstring | nullrequiredWhat visitors see above the fields;
nullshows none.introstring | nullrequiredA line or two under the heading;
nullshows none.locationstringrequiredWhere the form sits on your site, a label you choose (
website-footer,checkout-page). Recorded on each submission, asproperties.locationon itscontact.form_submittedevent and on theform.submittedwebhook, which is how a segment or journey uses it.urlstringrequiredThe hosted form's link, by its
slugwhen it has one, else itspublicId. It serves once the form is published.uri
statusstringrequiredWhether the form accepts submissions:
publishedoncePOST /v1/forms/{id}/publishputs it live,draftuntil then or after unpublishing.one of
draft,publishedlistIdstring | nullrequiredThe list every submitter is added to.
uuid
fieldsobject[]requiredThe fields, top to bottom.
6 child attributes
keystringrequiredWhere the response goes, such as
emailorattributes.plan.typestringrequiredThe input the visitor sees.
one of
email,text,textarea,select,checkbox,date,phonelabelstringrequiredThe text shown beside the field.
placeholderstringoptionalHint text shown inside the empty field.
requiredbooleanrequiredWhether the visitor must fill it in.
optionsobject[]optionalThe choices of a
selectorcheckboxfield.2 child attributes
valuestringrequiredlabelstringrequired
hiddenFieldsmap<string, object>requiredValues saved on each submitter with no field shown: fixed, or taken from the link.
at most 50 keys · keys: pattern
^[\p{L}\p{N}\p{M}_.-]{1,64}$One of 2 shapes
- With value
2 child attributes
source"fixed"requiredvaluestringrequiredSaved as it is on every submitter.
up to 1,000 characters
- With param
2 child attributes
source"link"requiredparamstringrequiredThe link parameter it takes its value from, such as
utm_campaign; left unset when the link has none.pattern
^[A-Za-z0-9_.-]{1,64}$
shareobject | nullrequiredHow the form's link previews, as set;
nullfalls back entirely.3 child attributes
titlestringoptionaldescriptionstringoptionalimageUrlstringoptionaluri
acceptingSubmissionsbooleanrequiredfalse: closed by hand, whatever its closing time and limit.closesAtstring | nullrequiredWhen the form closes, if ever.
date-time
maxSubmissionsinteger | nullrequiredThe submissions it closes at, if any.
closedMessagestring | nullrequiredWhat a closed form shows;
nullshows the default wording.submissionCountintegerrequiredSubmissions taken so far (honeypot catches aside), counted for the limit.
min 0
allowedOriginsstring[]requiredSite origins the embed may load from.
refusedOriginsobject[]requiredOrigins an embed was refused from lately, newest first, not counting any since added to
allowedOrigins; add one there to approve it.2 child attributes
originstringrequiredThe origin that was refused.
lastRefusedAtstringrequiredWhen it was last refused.
date-time
doubleOptInbooleanrequiredWhether submitters must confirm by email before they are subscribed.
notifyUserIdsstring[]requiredUsers of this workspace told about each submission.
themeFormThemerequired12 child attributes
modestringoptionalLight or dark defaults for every colour left unset; light when unset.
one of
light,darkaccentColorstringoptionalColour of the button and focus outlines, as
#RRGGBB.pattern
^#[0-9a-fA-F]{6}$backgroundColorstring | nulloptionalThe page and form background, as
#RRGGBB; unset ornullfor the mode's default.pattern
^#[0-9a-fA-F]{6}$textColorstring | nulloptionalHeadings, labels and text, as
#RRGGBB; unset ornullfor the mode's default.pattern
^#[0-9a-fA-F]{6}$buttonColorstring | nulloptionalThe button's fill; unset, the accent colour, as
#RRGGBB; unset ornullfor the mode's default.pattern
^#[0-9a-fA-F]{6}$buttonTextColorstring | nulloptionalThe button's text, as
#RRGGBB; unset ornullfor the mode's default.pattern
^#[0-9a-fA-F]{6}$fontFamilystringoptionalThe font's id: a generic style (
system,sans,serif,mono) or a named font the forms host serves itself. A font emails also offer has the same id there (EmailFont).one of
system,sans,serif,mono,inter,roboto,open-sans,lato,montserrat,poppins,source-sans-3,nunito,raleway,work-sans,dm-sans,manrope,ibm-plex-sans,noto-sans,rubik,karla,merriweather,lora,playfair-display,libre-baskerville,source-serif-4,eb-garamond,ibm-plex-mono,jetbrains-monoborderRadiusintegeroptionalCorner rounding of inputs and the button, in px, where
inputs.borderRadiusorbutton.borderRadiusdoes not set its own.min 0 · max 24
buttonLabelstringoptionalText on the submit button.
1–40 characters
inputsobjectoptionalHow fields look; each part optional.
9 child attributes
widthstringoptionalfit(unset): a short answer's field is 320px and a long one fills the form;full: every field fills the form;fixed: every fieldwidthPxwide at most.one of
fit,full,fixedwidthPxintegeroptionalWith
widthfixed: the width, in px.min 200 · max 720
heightintegeroptionalIn px.
min 28 · max 64
backgroundColorstring | nulloptionalThe field background, as
#RRGGBB; unset ornullfor the mode's default.pattern
^#[0-9a-fA-F]{6}$placeholderColorstring | nulloptionalPlaceholder text, as
#RRGGBB; unset ornullfor the mode's default.pattern
^#[0-9a-fA-F]{6}$borderColorstring | nulloptionalThe field border, as
#RRGGBB; unset ornullfor the mode's default.pattern
^#[0-9a-fA-F]{6}$borderWidthintegeroptionalIn px.
min 0 · max 4
borderRadiusintegeroptionalIn px; unset, the top-level
borderRadius.min 0 · max 32
spacingintegeroptionalThe gap below each field, in px.
min 0 · max 48
buttonobjectoptionalHow the submit button looks; each part optional.
5 child attributes
widthstringoptionalFit its label, or the form width.
one of
auto,fullheightintegeroptionalIn px.
min 28 · max 64
alignstringoptionalone of
start,center,endfontSizeintegeroptionalIn px.
min 12 · max 24
borderRadiusintegeroptionalIn px; unset, the top-level
borderRadius.min 0 · max 32
layoutobjectoptional2 child attributes
pageWidthintegeroptionalThe form's widest, in px.
min 360 · max 960
baseFontSizeintegeroptionalBody text size, in px.
min 12 · max 20
displayobjectrequiredOne of 2 shapes
- Inline
1 child attribute
mode"inline"required
- Popup
7 child attributes
mode"popup"requireddelayDurationOrZerooptionalHow long after the page loads it opens, at most 10 minutes. Defaults to 5 seconds.
2 child attributes
valueintegerrequiredmin 0
unitstringrequiredone of
seconds,minutes,hours,days
scrollPercentintegeroptionalOpens once the visitor has scrolled this far down the page.
min 1 · max 100
exitIntentbooleanoptionalOpens when the visitor moves to leave the page (desktop only).
urlMatchobjectoptionalLimits which pages the popup opens on.
2 child attributes
containsstring[]optionalShow only on pages whose URL contains one of these.
at most 20 items
excludesstring[]optionalNever show on pages whose URL contains one of these.
at most 20 items
hideForDurationOrZerooptionalHow long it stays away once closed, at most 365 days. Defaults to 7 days.
2 child attributes
valueintegerrequiredmin 0
unitstringrequiredone of
seconds,minutes,hours,days
hideAfterSubmitbooleanoptionalWhether it stays away after a signup. Defaults to true.
captchaobject | nullrequiredWhere the CAPTCHA comes from;
nullwhile it is off. Secrets never show.One of 2 shapes
- KiroraCaptchaSetting
1 child attribute
mode"kirora"required
- OwnCaptchaSetting
2 child attributes
mode"own"requiredsiteKeystringrequired
consentobjectrequired2 child attributes
requiredtruerequiredAlways
true: the visitor must tick the consent box.labelstringrequiredThe consent text shown beside the box.
successobjectrequiredOne of 2 shapes
- Show a message
2 child attributes
type"message"requiredmessagestringrequiredShown in place of the form.
- Redirect
2 child attributes
type"redirect"requiredredirectUrlstringrequiredAn http(s) address the visitor is sent to.
uri
archivedAtstring | nullrequiredWhen it was archived; an archived form is left out of the list and stops serving.
date-time
createdAtstringrequireddate-time
updatedAtstringrequireddate-time