---
title: "Add a node"
method: POST
path: "/forms/{formId}/nodes"
tags: ["Nodes"]
---

# Add a node

`POST /forms/{formId}/nodes`

## Request

- Base URL: `https://api.clipform.io/v1`
- URL: `https://api.clipform.io/v1/forms/{formId}/nodes`
- Auth: HTTP bearer

Adds a node to a form.

## Path parameters

- `formId` string, uuid, required

## Request body

- object
  - `node` NodeInput, required
    - `id` string, uuid: Optional client-generated node id (RF-style stable identity). When provided the node is inserted with this id so the builder's optimistic node needs no temp-id swap. Omit to let the server generate one.
    - `type` 'choice' | 'open' | 'button' | 'details' | 'payment' | 'file_download' | 'redirect' | 'end_screen', required
    - `prompt` string, required: The text shown to the respondent
    - `label` string: Internal short label used in exports and reports (defaults to prompt)
    - `required` boolean
    - `config` object: Type-specific configuration. Key options by type: - choice: { choice, selection_mode, allow_text_response, randomise_options, show_option_count, option_display, content_media_type } - open: { formats, content_media_type, max_recording_seconds } - button: { button_text, button_style } - details: { title, fields, description, consent_items } - payment: { amount, currency, provider, workspace_integration_id, title, description } - file_download: { files, button_text, description } - redirect: { url, auto_redirect } - end_screen: { title, message, show_score, icon, show_share_button, cta_type, cta_text, cta_url, score_ranges, scoring_results }
    - `options` object[]: Answer options for choice/button nodes
      - `id` string, uuid: Client-generated option id (optional). When provided it's used as the row id so the builder's optimistic option is the persisted row (no temp id swap). Omit to let the server generate one.
      - `content` string, required
      - `score` integer, nullable: Points awarded when this option is selected. Use `scores` instead to score across multiple named categories.
      - `scores` object, nullable: Per-category scoring map. Keys are category names, values are points. -1 = knockout.
  - `after_node_id` string, uuid: Insert after this node. Omit to append before end screen. Ignored when auto_arrange is false.
  - `auto_arrange` boolean: When true (default), the new node is wired into the linear logic chain and the canvas is flagged for auto-layout. Set false for manual builder creates so the node lands orphaned (unconnected) and the caller controls its position.

## Response `201`

Node added

- object
  - `node_id` string, uuid
  - `warnings` string[]: Advisory notices, returned only when present - e.g. inserting a terminal node (end_screen/redirect/link_list/ shopping) via after_node_id truncated the flow there, orphaning whatever was previously downstream.

## Other responses

- `429`: Rate limit exceeded.

---

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