---
title: "Create a form"
method: POST
path: "/v1/forms"
tags: ["forms"]
---

# Create a form

`POST /v1/forms`

## Request

- Base URL: `https://postbag.dev`
- URL: `https://postbag.dev/v1/forms`
- Auth: HTTP bearer

Pass `from_template` (a stream id) to attach the new form to that stream with a schema copied 1:1 from it, so the mapping is trivially complete. Pass `if_exists: "return"` to make this call safe to re-run.

## Request body

- object
  - `name` string
  - `slug` string
  - `project` string
  - `tags` string[]
  - `status` 'active' | 'paused'
  - `schema_mode` 'observe' | 'enforce' | 'managed'
  - `settings` object
    - `allowed_origins` string[]
    - `redirect_url` string, uri, nullable
    - `honeypot_field` string
    - `turnstile` object
      - `secret` string
      - `enabled` boolean
    - `rate_limit` object
      - `per_minute` integer
      - `burst` integer
    - `reply_to_field` string, nullable
  - `schema` object
    - `json_schema` object, required: JSON Schema draft 2020-12 describing the submission data. `required` drives drift detection and mapping completeness.
    - `ui` object: Per-field rendering hints keyed by field name (label, placeholder, widget, options, order) — used to render embed snippets.
    - `changelog` string: A short human note on what changed in this version, shown in the version history.
  - `from_template` string
  - `if_exists` 'error' | 'return'

## Response `201`

created

- FormCreated
  - `id` string, required
  - `project_id` string, required
  - `slug` string, required
  - `name` string, required
  - `tags` string[], required
  - `status` 'active' | 'paused', required
  - `schema_mode` 'observe' | 'enforce' | 'managed', required
  - `current_schema_version` integer, nullable, required
  - `settings` object, required
  - `submit_url` string, required
  - `streams` object[], required
    - `id` string, required
    - `slug` string, required
    - `mapping_status` 'valid' | 'incomplete', required
  - `counts` object, required
    - `submissions` integer, required
    - `last_submission_at` string, nullable, required
  - `created_at` string, required
  - `embed` Embed
    - `html` string, required
    - `fetch` string, required
    - `react` string, required
    - `astro` string, required
    - `nextjs_action` string, required
  - `verify` Verify
    - `curl` string, required
    - `then` string, required
  - `next` object[]
    - `why` string
    - `method` string
    - `path` string
    - `body` object

## Other responses

- `400`: Error
- `401`: Error
- `403`: Error
- `404`: Not found
- `409`: Error
- `422`: Error

---

[API](https://skmtc.dev/postbag/apis/postbag-api.md) · [All operations](https://skmtc.dev/postbag/apis/postbag-api/llms.txt) · [OpenAPI document](https://skmtc.dev/postbag/apis/postbag-api/revisions/3da976524695?raw)
