# POST Create a form

Adds a form to the customiser, at the end of the current presentation order. `name` and `form_type` are required; every other property has a documented default (no receivers, `save_customer_details` false, `post_submission_action` default, and no fields). `fields` is the form's field document. Each field names the input it renders as, and only the properties that input reads: a `min` on a text field, or `options` on anything but a dropdown or multiple-choice field, is a 422 `field_not_used_by_input_type` on the offending property. Identities (`field_id`, `option_id`) are generated when omitted; send them back unchanged to keep a field's existing submissions attached to it. Requires `customisers:write` and an `Idempotency-Key`. The write clears the customiser's cached storefront configuration and runs the advisory language sync, which is what translates the form's copy into the customiser's other languages. It never regenerates Shopify products, product images, or the product cache, so live listings are untouched. Option writes also spend one unit of a separate per-key option-write budget; exhausting it returns a 429 with `retry_after`.

- Source URL: https://www.signcustomiser.com/help/api/v3-post-create-a-form/
- Markdown URL: https://www.signcustomiser.com/help/api/v3-post-create-a-form.md
- Group: Customiser forms
- Method: POST
- Path: /api/v3/customisers/{customiser_id}/forms
- Auth: Bearer token
- Required scopes: `customisers:write`

## Path parameters

- customiser_id (string, required): The customiser id. Example: 1

## Body parameters

- form_type (string, optional): No description provided.
- post_submission_action (string, optional): No description provided.
- fields (array, optional): No description provided.
- name (string, optional): No description provided.
- description (string, optional): No description provided.
- button_label (string, optional): No description provided.
- subject (string, optional): No description provided.
- recipient_emails (array, optional): No description provided.
- save_customer_details (boolean, optional): No description provided.
- redirect_url (string, optional): No description provided.

## Request body example

```json
{
  "form_type": "quote",
  "post_submission_action": "default",
  "fields": [
    {
      "name": "Email",
      "input_type": "email",
      "customer_field": "email",
      "required": true,
      "reply_to": true,
      "options": [
        {
          "label": null,
          "value": null
        }
      ]
    }
  ],
  "name": "Request a quote",
  "description": "Tell us about your project",
  "button_label": "Send",
  "subject": "New quote request",
  "recipient_emails": [
    "sales@example.com"
  ],
  "save_customer_details": true,
  "redirect_url": "https://example.com/thank-you"
}
```

## cURL example

```bash
curl https://web.signcustomiser.com/api/v3/customisers/1/forms \
  --request POST \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer YOUR_API_TOKEN' \
  --header 'Content-Type: application/json' \
  --data '{
  "form_type": "quote",
  "post_submission_action": "default",
  "fields": [
    {
      "name": "Email",
      "input_type": "email",
      "customer_field": "email",
      "required": true,
      "reply_to": true,
      "options": [
        {
          "label": null,
          "value": null
        }
      ]
    }
  ],
  "name": "Request a quote",
  "description": "Tell us about your project",
  "button_label": "Send",
  "subject": "New quote request",
  "recipient_emails": [
    "sales@example.com"
  ],
  "save_customer_details": true,
  "redirect_url": "https://example.com/thank-you"
}'
```

## Response examples

### 201 POST 201 example 1

```json
{
  "data": {
    "object": "form",
    "id": 7,
    "customiser_id": 42,
    "name": "Request a quote",
    "description": null,
    "form_type": "quote",
    "button_label": null,
    "subject": null,
    "recipient_emails": [],
    "save_customer_details": false,
    "post_submission_action": "default",
    "redirect_url": null,
    "emails_enabled": true,
    "suppressed_emails": [],
    "fields": [],
    "sort_order": 1,
    "created_at": "2026-08-14T00:00:00Z",
    "updated_at": "2026-08-14T00:00:00Z"
  },
  "links": {
    "self": "https://web.signcustomiser.com/api/v3/customisers/42/forms/7",
    "documentation": "https://www.signcustomiser.com/help/api/"
  },
  "meta": {
    "api_version": "v3",
    "request_id": "req_01jz9x2k7c8f3m5n6p7q8r9s0t"
  }
}
```

### 400 Missing idempotency key

```json
{
  "type": "https://www.signcustomiser.com/help/api/problems/missing_idempotency_key",
  "title": "Missing idempotency key",
  "status": 400,
  "code": "missing_idempotency_key",
  "detail": "Provide an Idempotency-Key header for this write.",
  "request_id": "req_01jz9x2k7c8f3m5n6p7q8r9s0t"
}
```

### 401 Missing API key

```json
{
  "type": "https://www.signcustomiser.com/help/api/problems/missing_api_key",
  "title": "Missing API key",
  "status": 401,
  "code": "missing_api_key",
  "detail": "Provide a store API key as a bearer token.",
  "request_id": "req_01jz9x2k7c8f3m5n6p7q8r9s0t"
}
```

### 403 Insufficient scope

```json
{
  "type": "https://www.signcustomiser.com/help/api/problems/insufficient_scope",
  "title": "Insufficient scope",
  "status": 403,
  "code": "insufficient_scope",
  "detail": "This operation requires the customisers:write scope.",
  "required_scopes": [
    "customisers:write"
  ],
  "granted_scopes": [
    "customisers:read"
  ],
  "request_id": "req_01jz9x2k7c8f3m5n6p7q8r9s0t"
}
```

### 404 Unknown customiser

```json
{
  "type": "https://www.signcustomiser.com/help/api/problems/resource_not_found",
  "title": "Resource not found",
  "status": 404,
  "code": "resource_not_found",
  "detail": "The requested resource does not exist or does not belong to the authenticated store.",
  "request_id": "req_01jz9x2k7c8f3m5n6p7q8r9s0t"
}
```

### 409 Idempotency conflict

```json
{
  "type": "https://www.signcustomiser.com/help/api/problems/idempotency_key_conflict",
  "title": "Idempotency key conflict",
  "status": 409,
  "code": "idempotency_key_conflict",
  "detail": "This Idempotency-Key was already used for a different request body on this operation.",
  "request_id": "req_01jz9x2k7c8f3m5n6p7q8r9s0t"
}
```

### 413 Request body too large

```json
{
  "type": "https://www.signcustomiser.com/help/api/problems/request_too_large",
  "title": "Request too large",
  "status": 413,
  "code": "request_too_large",
  "detail": "The request body must not exceed 2 MiB.",
  "request_id": "req_01jz9x2k7c8f3m5n6p7q8r9s0t"
}
```

### 422 Property the input type does not read

```json
{
  "type": "https://www.signcustomiser.com/help/api/problems/field_not_used_by_input_type",
  "title": "Field property not used by this input type",
  "status": 422,
  "code": "field_not_used_by_input_type",
  "detail": "A text field never reads min, so storing it would put a value where nothing looks.",
  "errors": [
    {
      "pointer": "/fields/0/min",
      "code": "field_not_used_by_input_type",
      "detail": "A text field does not use min."
    }
  ],
  "request_id": "req_01jz9x2k7c8f3m5n6p7q8r9s0t"
}
```

### 429 Option write budget exhausted

```json
{
  "type": "https://www.signcustomiser.com/help/api/problems/rate_limited",
  "title": "Too many requests",
  "status": 429,
  "code": "rate_limited",
  "detail": "You have exceeded the request limit for this API key.",
  "retry_after": 37,
  "request_id": "req_01jz9x2k7c8f3m5n6p7q8r9s0t"
}
```
