Skip to content

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/forms

Authentication

Required

Include one of these headers in your request:

  • Token: <your-api-key> — Get it from API Keys
  • Authorization: Bearer <jwt-token> — From Login

Request

Headers

HeaderRequiredDescription
TokenYour API key
AuthorizationBearer <jwt-token>

Body Parameters

ParameterTypeRequiredDescription
namestringInternal name, up to 191 characters. Also the default push title
fieldsarrayThe form's fields, max 30. At least one must be something a visitor fills in
settingsobjectTitle, texts and design. Every key has a default
application_tidstringApplication the submissions belong to
device_tidstringTarget device TID, or all. Omit for every device
default_levelintPriority level (-2..2) for submissions. See Message priority levels
push_titlestringPush title template with {Field label} tokens, up to 191 characters
allowed_originsarrayHosts allowed to embed and submit the form, max 10. Empty means anywhere
max_responsesintClose the form after this many responses. 0 (default) is unlimited
closes_atstringClosing time, RFC 3339. Stored in UTC
is_activebooleanfalse closes the form straight away. Defaults to true

Fields

Each entry in fields:

ParameterTypeRequiredDescription
idstringUnique within the form: letters, digits, _ and -, up to 40 characters
typestringOne of the types below
labelstringShown above the input, up to 200 characters (2000 for paragraph)
placeholderstringText, textarea, email, phone, number, url and dropdown only
requiredbooleanIgnored by layout fields
optionsarray✅ for choice fieldsUp to 50 entries for dropdown, radio and checkboxes
paramstring✅ for hiddenURL parameter the value is read from, e.g. utm_source
GroupTypesSubmitted value
Texttext, textarea, email, phone, number, url, dateString. text is capped at 1000 characters, textarea at 5000
Choicedropdown, radioOne of options
ChoicecheckboxesArray of options
ChoicecheckboxBoolean, rendered as Yes / No
Ratingrating (1–5), nps (0–10)Number
Layoutheading, paragraph, dividerNever submitted
TrackinghiddenTaken 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.

ParameterTypeDefaultDescription
titlestring""Heading above the form, up to 200 characters
top_textstring""Intro text, up to 2000 characters. Plain text; links become clickable
bottom_textstring""Text under the button, up to 2000 characters
success_messagestringThanks! Your response has been sent.Shown after a submission, up to 500 characters
closed_messagestringThis form is no longer accepting responses.Shown when the form is closed
background_colorstring#f5f5f4Page background, #rrggbb
card_colorstring#ffffffForm background
text_colorstring#1c1917Text
primary_colorstring#3f5cadAccent and, unless overridden, the button
font_familystringInterA Google Font by name
font_sizeint1612–24
font_weightint400300, 400, 500, 600 or 700
border_radiusint100–48
hide_brandingbooleanfalseHides the "Powered by Pocket Alert" link. Paid plans only — on the free plan the API resets it to false
submitobject{ "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

bash
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"
    }
  }'
javascript
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}`);
python
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']}")
php
$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.

json
{
  "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

StatusDescription
400Validation error — the error field says which field or setting is wrong
401Unauthorized — Invalid or missing token
403You have reached the number of forms your plan allows
500Failed to create form

Pocket Alert Documentation