External API
The Deformity External API lets you create, edit, fetch, and delete forms from your own app, scripts, or automation tools. It is completely free for all users.
Setup
- Go to Account - API Keys and create a key in the Deformity External API section.
- Copy the key immediately. It is only shown once.
- Use
Authorization: Bearer df_your_api_keyon every form API request. - Find a workspace ID from this page, the dashboard URL, or the workspace endpoint.
- Find a form ID from Settings - Integrations - Developer inside a form, or from the list forms endpoint.
Find your workspace ID
workspaceId is required when creating a form. If you are logged in, your active organization workspaces appear below. You can also callGET /api/v1/workspaces with your API key to list workspaces programmatically.
Endpoints
| Method | Path | Purpose |
|---|---|---|
| GET | /api/v1/forms | List active forms. |
| GET | /api/v1/workspaces | List workspaces available to the API key. |
| POST | /api/v1/forms | Create an AI or static form. |
| GET | /api/v1/forms/{formId} | Fetch one form with settings and points. |
| PATCH | /api/v1/forms/{formId} | Edit metadata, settings, form type, or points. |
| DELETE | /api/v1/forms/{formId} | Soft-delete a form. |
Status codes and responses
Successful requests return a data value. Errors return anerror object with a stable code and human-readable message. Delete requests return confirmation JSON instead of an empty response.
{
"data": {
"id": "form_123"
}
}{
"error": {
"code": "invalid_request",
"message": "Request body is invalid"
}
}| Status | Meaning |
|---|---|
| 200 | Request succeeded. Delete requests return confirmation data. |
| 201 | Resource was created. |
| 400 | Invalid request, missing required fields, malformed JSON, or missing organization context. |
| 401 | Missing or invalid API key, or missing logged-in session for API key management. |
| 404 | Workspace, form, or API key was not found in the authenticated organization. |
| 429 | Rate limit exceeded. Check Retry-After and X-RateLimit headers. |
| 500 | Unexpected server error. |
AI vs static forms
Send formType on create. Use ai for conversational forms andstatic for one-question-at-a-time static forms. You can also sendformType in PATCH to switch a form.
{
"workspaceId": "workspace_123",
"formType": "ai",
"name": "Customer intake"
}Create a form
curl -X POST https://deformity.ai/api/v1/forms \
-H 'Authorization: Bearer df_your_api_key' \
-H 'Content-Type: application/json' \
-d '{
"workspaceId": "workspace_123",
"formType": "ai",
"name": "Customer intake",
"purpose": "Collect onboarding details and ask helpful follow-ups.",
"points": [
{
"pointType": "welcome_screen",
"body": {
"point": "Welcome to onboarding",
"description": "We will ask a few quick questions.",
"buttonText": "Start",
"active": true
}
},
{
"pointType": "freeform",
"required": true,
"body": {
"point": "What should we know before kickoff?",
"sampleQuestion": "Tell us about your goals"
}
}
],
"settings": {
"saveResponses": true,
"emailResponses": true
}
}'Edit a form
PATCH accepts partial form updates. If you send points, the API replaces the form's ordered points with the array you provide.
curl -X PATCH https://deformity.ai/api/v1/forms/form_123 \
-H 'Authorization: Bearer df_your_api_key' \
-H 'Content-Type: application/json' \
-d '{
"name": "Customer onboarding intake",
"formType": "static",
"settings": {
"completionRedirect": "https://example.com/thanks"
}
}'Form properties
| Property | Type | Usage |
|---|---|---|
| workspaceId | string | Required on create. Workspace where the form will be created. |
| formType | ai or static | Required on create. Use ai for conversational forms or static for non-AI forms. |
| name | string | Form name shown in the dashboard. |
| purpose | string or null | AI instruction describing what the form should accomplish. |
| personalityId | string or null | Optional AI personality to use for AI forms. |
| snippets | array of strings | Training snippets or extra instructions used by the AI. |
| url | string or null | Reference website URL for the form. |
| files | array of file objects | File references attached to the form. Shape shown below. |
| colors | array of strings | Theme colors used by the renderer, for example ["#000000", "#ffffff"]. |
| buttons | button style object or null | Button style configuration. Shape shown below. |
| font | string or null | Font family name. |
| settings | settings object | Form behavior settings. See settings reference below. |
| points | array of point objects | Ordered form elements. If sent in PATCH, replaces all points. |
Settings properties
| Property | Type | Usage |
|---|---|---|
| submissionPeriod | submission period object or null | startDate, endDate, and customMessage for opening or closing submissions by date. |
| limit | submission limit object or null | maxSubmissions and customMessage for response limits. |
| instantResponses | boolean | Enable instant AI responses when available. |
| saveResponses | boolean | Store responses in Deformity. |
| completionRedirect | string or null | URL to redirect respondents after completion. |
| collectPartials | boolean | Store partial responses. |
| multilingual | boolean | Allow multilingual behavior. |
| emailResponses | boolean | Send response notification emails. |
| completionEmail | completion email object or null | Completion email settings. Shape shown below. |
| customLogo | string or null | Custom logo URL. |
| customBranding | branding object or null | Custom logo and logo position. Shape shown below. |
| removeDeformityBranding | boolean | Hide Deformity branding when the plan allows it. |
| removeProgress | boolean | Hide progress UI. |
| allowIndexing | boolean | Allow search engine indexing. |
| formNavigation | boolean | Show form navigation controls. |
| responsePathCapture | boolean | Capture response-path data when enabled for the organization. |
| metadata | metadata object or null | Share metadata. Shape shown below. |
Settings object shapes
{
"submissionPeriod": {
"startDate": "2026-06-01T00:00:00.000Z",
"endDate": "2026-06-30T23:59:59.999Z",
"customMessage": "This form is closed."
},
"limit": {
"maxSubmissions": "100",
"customMessage": "This form has reached its response limit."
},
"completionEmail": {
"active": true,
"email": "team@example.com"
},
"customBranding": {
"logo": "https://example.com/logo.png",
"position": "bottomRight"
},
"metadata": {
"title": "Customer intake",
"description": "Tell us about your project.",
"favicon": "https://example.com/favicon.ico",
"shareImage": "https://example.com/share.png"
}
}Point properties
| Property | Type | Usage |
|---|---|---|
| id | string | Returned by the API. Optional in requests; replacement updates create new point IDs. |
| pointType | string | Required for each point. See supported point types below. |
| order | number | Optional 1-based position. Array order is used when omitted. |
| required | boolean or null | Require an answer before continuing. |
| layout | string or null | Visual layout value used by the renderer. |
| background | background object or null | Background image/color/video configuration. Shape shown below. |
| color | string or null | Text or theme color for this point. |
| opacity | number or null | Background opacity. |
| body | point body object | Question-type-specific fields. Unknown top-level point fields are also folded into body. |
Visual object shapes
Visual objects are intentionally flexible because the builder may add renderer-specific keys over time. These are the common shapes to start with.
{
"buttons": {
"backgroundColor": "#000000",
"textColor": "#ffffff",
"borderRadius": 8
},
"background": {
"type": "image",
"url": "https://example.com/background.jpg",
"position": "center",
"size": "cover"
},
"files": [
{
"id": "file_123",
"name": "Brief.pdf",
"url": "https://example.com/brief.pdf",
"type": "application/pdf"
}
]
}Point body properties
Put question-specific values inside body. For convenience, unknown top-level fields on a point are folded into body, but using body directly is clearer for integrations.
| Property | Type | Usage |
|---|---|---|
| point | string | Main prompt or screen text. |
| sampleQuestion | string | Placeholder/sample text shown to respondents. |
| description | string | Supporting text below the prompt. |
| options | array of strings or option objects | Choices for multiple choice, checkboxes, dropdown, and ranking. Shapes shown below. |
| buttonText | string | Button label for screens, embeds, statements, payments, and similar elements. |
| buttonLink | string | Link target for supported button-style elements. |
| minRating | number | Lowest rating value. |
| maxRating | number | Highest rating value. |
| ratingType | stars, hearts, numbers, smileys, or thumbs | Visual rating style. |
| showOther | boolean | Show an Other choice for choice-based questions. |
| embedLink | string | URL for embed points. |
| disclosure | string | Small disclosure text, commonly used on welcome screens. |
| defaultCountry | string | Default country code for phone/address inputs. |
| active | boolean | Used by welcome/end screens to show or hide them. |
| logic | string | Legacy/manual logic text. |
| logicImplementation | string | Executable logic implementation used by the builder/runtime. |
| isManualLogic | boolean | Marks logic as manually configured. |
| selectMultiple | boolean | Allow multiple selections for supported choice fields. |
| signatureType | pad, typing, or both | Signature input mode. |
| dateType | time, date, or date_time | Date/time input mode. |
| weekStart | number | First day of week for date inputs. |
| matrixRows | array of strings | Rows for matrix questions. |
| matrixColumns | array of strings | Columns for matrix questions. |
| amount | number | Payment amount. |
| currency | string | Payment currency code, such as USD. |
| collectName | boolean | Collect payer name for payment points. |
| collectEmail | boolean | Collect payer email for payment points. |
Choice option shapes
For simple choices, send strings. For choices that need stable IDs or metadata, send objects.
{
"options": ["Free", "Pro", "Enterprise"]
}
{
"options": [
{ "id": "free", "label": "Free", "value": "free" },
{ "id": "pro", "label": "Pro", "value": "pro" }
]
}Common body shapes by point type
{
"freeform": {
"point": "What should we know?",
"description": "Share as much detail as you want.",
"sampleQuestion": "Tell us about your goals"
},
"multiple_choice": {
"point": "Pick one",
"options": ["A", "B", "C"],
"showOther": true
},
"dropdown": {
"point": "Choose a department",
"options": ["Sales", "Support", "Product"],
"selectMultiple": false
},
"rating": {
"point": "Rate your experience",
"minRating": 1,
"maxRating": 5,
"ratingType": "stars"
},
"signature": {
"point": "Sign here",
"signatureType": "both"
},
"date_time": {
"point": "Pick a time",
"dateType": "date_time",
"weekStart": 1
},
"matrix": {
"point": "Rate each area",
"matrixRows": ["Support", "Pricing"],
"matrixColumns": ["Poor", "Okay", "Great"]
},
"payment": {
"point": "Pay your deposit",
"buttonText": "Pay now",
"amount": 5000,
"currency": "USD",
"collectName": true,
"collectEmail": true
},
"embed": {
"point": "Watch this first",
"embedLink": "https://www.youtube.com/watch?v=example",
"buttonText": "Continue"
}
}Supported point types
| pointType | Usage |
|---|---|
| welcome_screen | Opening screen with optional button and disclosure. |
| end_screen | Final completion screen. |
| freeform | Open text response. |
| Email address input. | |
| url | URL input. |
| number | Number input. |
| address | Address input. |
| phone_number | Phone number input. |
| multiple_choice | Single-choice selection. |
| multiple_select | Multiple-choice selection. |
| checkboxes | Checkbox list. |
| dropdown | Dropdown selection. |
| confirmation_statement | Statement with an acknowledgement button. |
| rating | Rating input. |
| signature | Signature input. |
| file_upload | File upload input. |
| embed | Embedded URL/content point. |
| ranking | Ranked choice input. |
| matrix | Matrix/grid question. |
| payment | Stripe payment point. |
| logic | Logic-oriented text point. |
Common point examples
[
{
"pointType": "multiple_choice",
"required": true,
"body": {
"point": "Which plan are you interested in?",
"options": ["Free", "Pro", "Enterprise"],
"showOther": true
}
},
{
"pointType": "rating",
"body": {
"point": "How urgent is this?",
"minRating": 1,
"maxRating": 5,
"ratingType": "stars"
}
},
{
"pointType": "date_time",
"body": {
"point": "When should we follow up?",
"dateType": "date_time",
"weekStart": 1
}
},
{
"pointType": "matrix",
"body": {
"point": "Rate each area",
"matrixRows": ["Support", "Pricing", "Features"],
"matrixColumns": ["Poor", "Okay", "Great"]
}
},
{
"pointType": "payment",
"body": {
"point": "Pay your deposit",
"buttonText": "Pay now",
"amount": 5000,
"currency": "USD",
"collectName": true,
"collectEmail": true
}
}
]Response shape
Successful create, fetch, and update responses return { "data": form }. Form objects include id, formType, form metadata,settings, ordered points, timestamps, andnumberOfSubmissions.
Errors
{
"error": {
"code": "invalid_request",
"message": "Request body is invalid"
}
}API keys are rate limited to 120 requests per minute by default. A rate limited request returns HTTP 429 with Retry-After, X-RateLimit-Limit,X-RateLimit-Remaining, and X-RateLimit-Reset headers.