Create Form POST
Create a hosted form. It is published immediately at https://frms.click/{tid}, and every submission becomes a message on your account — see Forms.
Endpoint
POST https://api.pocketalert.app/v1/formsAuthentication
Required
Include one of these headers in your request:
Request
Headers
| Header | Required | Description |
|---|---|---|
Token | ✅ | Your API key |
Authorization | ✅ | Bearer <jwt-token> |
Body Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | ✅ | Internal name, up to 191 characters. Also the default push title |
fields | array | ✅ | The form's fields, max 30. At least one must be something a visitor fills in |
settings | object | ❌ | Title, texts and design. Every key has a default |
application_tid | string | ❌ | Application the submissions belong to |
device_tid | string | ❌ | Target device TID, or all. Omit for every device |
default_level | int | ❌ | Priority level (-2..2) for submissions. See Message priority levels |
push_title | string | ❌ | Push title template with {Field label} tokens, up to 191 characters |
allowed_origins | array | ❌ | Hosts allowed to embed and submit the form, max 10. Empty means anywhere |
max_responses | int | ❌ | Close the form after this many responses. 0 (default) is unlimited |
closes_at | string | ❌ | Closing time, RFC 3339. Stored in UTC |
is_active | boolean | ❌ | false closes the form straight away. Defaults to true |
Fields
Each entry in fields:
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | ✅ | Unique within the form: letters, digits, _ and -, up to 40 characters |
type | string | ✅ | One of the types below |
label | string | ✅ | Shown above the input, up to 200 characters (2000 for paragraph) |
placeholder | string | ❌ | Text, textarea, email, phone, number, url and dropdown only |
required | boolean | ❌ | Ignored by layout fields |
options | array | ✅ for choice fields | Up to 50 entries for dropdown, radio and checkboxes |
param | string | ✅ for hidden | URL parameter the value is read from, e.g. utm_source |
| Group | Types | Submitted value |
|---|---|---|
| Text | text, textarea, email, phone, number, url, date | String. text is capped at 1000 characters, textarea at 5000 |
| Choice | dropdown, radio | One of options |
| Choice | checkboxes | Array of options |
| Choice | checkbox | Boolean, rendered as Yes / No |
| Rating | rating (1–5), nps (0–10) | Number |
| Layout | heading, paragraph, divider | Never submitted |
| Tracking | hidden | Taken from the page URL, not from the visitor |
Email, phone, number, URL and date values are validated on the server; the browser check is a convenience, not the guard.
Settings
All keys are optional — anything you leave out keeps its default.
| Parameter | Type | Default | Description |
|---|---|---|---|
title | string | "" | Heading above the form, up to 200 characters |
top_text | string | "" | Intro text, up to 2000 characters. Plain text; links become clickable |
bottom_text | string | "" | Text under the button, up to 2000 characters |
success_message | string | Thanks! Your response has been sent. | Shown after a submission, up to 500 characters |
closed_message | string | This form is no longer accepting responses. | Shown when the form is closed |
background_color | string | #f5f5f4 | Page background, #rrggbb |
card_color | string | #ffffff | Form background |
text_color | string | #1c1917 | Text |
primary_color | string | #3f5cad | Accent and, unless overridden, the button |
font_family | string | Inter | A Google Font by name |
font_size | int | 16 | 12–24 |
font_weight | int | 400 | 300, 400, 500, 600 or 700 |
border_radius | int | 10 | 0–48 |
hide_branding | boolean | false | Hides the "Powered by Pocket Alert" link. Paid plans only — on the free plan the API resets it to false |
submit | object | — | { "text": "Submit", "color": "", "size": "md" }. size is sm, md or lg; an empty color follows primary_color |
Push Title Template
push_title builds the notification title from the answers:
New lead: {Name} ({Email})Tokens reference fields by label, case-insensitive, plus {form} for the form name. Tokens with no answer drop out; if nothing is left, the title falls back to Form: {name}. The template is never exposed on the public page.
Allowed Origins
A form id travels in its public link, so by default anyone holding it can embed the form. allowed_origins closes that: only the listed hosts may frame the form, and a submission whose Origin (or Referer) is not on the list is rejected with 403.
Write hosts, not URLs: example.com, app.example.com, *.example.com for every subdomain, localhost:3000 while developing. www. is ignored.
Example Request
curl -X POST "https://api.pocketalert.app/v1/forms" \
-H "Token: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"name": "Contact form",
"push_title": "New lead: {Name}",
"fields": [
{ "id": "name", "type": "text", "label": "Name", "required": true },
{ "id": "email", "type": "email", "label": "Email", "required": true },
{ "id": "message", "type": "textarea", "label": "Message" },
{ "id": "src", "type": "hidden", "label": "Source", "param": "utm_source" }
],
"settings": {
"title": "Get in touch",
"top_text": "We reply within one business day.",
"primary_color": "#3f5cad"
}
}'const response = await fetch('https://api.pocketalert.app/v1/forms', {
method: 'POST',
headers: {
'Token': 'your-api-key',
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'Contact form',
push_title: 'New lead: {Name}',
fields: [
{ id: 'name', type: 'text', label: 'Name', required: true },
{ id: 'email', type: 'email', label: 'Email', required: true },
{ id: 'message', type: 'textarea', label: 'Message' }
],
settings: { title: 'Get in touch' }
})
});
const form = await response.json();
console.log('Form link:', `https://frms.click/${form.tid}`);import requests
response = requests.post(
'https://api.pocketalert.app/v1/forms',
headers={'Token': 'your-api-key'},
json={
'name': 'Contact form',
'push_title': 'New lead: {Name}',
'fields': [
{'id': 'name', 'type': 'text', 'label': 'Name', 'required': True},
{'id': 'email', 'type': 'email', 'label': 'Email', 'required': True},
{'id': 'message', 'type': 'textarea', 'label': 'Message'},
],
'settings': {'title': 'Get in touch'},
}
)
form = response.json()
print(f"Form link: https://frms.click/{form['tid']}")$form = Http::withHeaders([
'Token' => 'your-api-key',
])->post('https://api.pocketalert.app/v1/forms', [
'name' => 'Contact form',
'push_title' => 'New lead: {Name}',
'fields' => [
['id' => 'name', 'type' => 'text', 'label' => 'Name', 'required' => true],
['id' => 'email', 'type' => 'email', 'label' => 'Email', 'required' => true],
['id' => 'message', 'type' => 'textarea', 'label' => 'Message'],
],
'settings' => ['title' => 'Get in touch'],
])->json();
echo 'Form link: https://frms.click/'.$form['tid'];Response
Success Response
201 Created
The form is live. Share https://frms.click/{tid}, or embed it — see Forms.
The body is the same shape as one entry from Get All Forms.
{
"tid": "vml19aihrga216gt8apc5e3m9",
"name": "Contact form",
"fields": [
{ "id": "name", "type": "text", "label": "Name", "required": true },
{ "id": "email", "type": "email", "label": "Email", "required": true },
{ "id": "message", "type": "textarea", "label": "Message" },
{ "id": "src", "type": "hidden", "label": "Source", "param": "utm_source" }
],
"settings": {
"title": "Get in touch",
"top_text": "We reply within one business day.",
"success_message": "Thanks! Your response has been sent.",
"closed_message": "This form is no longer accepting responses.",
"background_color": "#f5f5f4",
"card_color": "#ffffff",
"text_color": "#1c1917",
"primary_color": "#3f5cad",
"font_family": "Inter",
"font_size": 16,
"font_weight": 400,
"border_radius": 10,
"hide_branding": false,
"submit": { "text": "Submit", "color": "", "size": "md" }
},
"application_tid": "",
"device_tid": "",
"default_level": null,
"push_title": "New lead: {Name}",
"allowed_origins": [],
"max_responses": 0,
"closes_at": null,
"closed": false,
"is_active": true,
"submissions_count": 0,
"last_submission_at": "",
"created_at": "23.09.2026 11:40:02"
}Error Responses
| Status | Description |
|---|---|
400 | Validation error — the error field says which field or setting is wrong |
401 | Unauthorized — Invalid or missing token |
403 | You have reached the number of forms your plan allows |
500 | Failed to create form |
