# Custom form Custom forms provide a flexible, integrated way to manage app setup and configuration during the authorization process. The information in the `custom_form` section of the manifest JSON represents the values on the **[Custom Form](/docs/build-flow/custom-form/)** page of the app build flow. ## Manifest JSON ```json { "features": { // ......, "custom_form": { "enable": true, "pre_auth": { "app_level": [ { "action_id": "api_key_field", "type": "plain_text_input", "widgets": "{\"text\":\"API Key\",\"placeholder\":\"Enter your API key\",\"description\":\"Your application API key\",\"data_type\":\"String\",\"setting_level\":\"appLevel\"}" }, { "action_id": "api_endpoint", "type": "plain_text_input", "widgets": "{\"text\":\"API Endpoint\",\"placeholder\":\"https://api.example.com\",\"description\":\"Your API endpoint URL\",\"data_type\":\"String\",\"required\":true,\"setting_level\":\"appLevel\"}" }, { "action_id": "max_retries", "type": "plain_text_input", "widgets": "{\"text\":\"Max Retries\",\"placeholder\":\"3\",\"description\":\"Maximum number of retry attempts\",\"data_type\":\"Number\",\"required\":true,\"multiple\":false,\"setting_level\":\"appLevel\"}" }, { "action_id": "region", "type": "select", "widgets": "{\"text\":\"Region\",\"description\":\"Select your deployment region\",\"dependent_fields\":[],\"setting_level\":\"appLevel\",\"dynamic_widget_populate\":null,\"options\":[{\"value\":\"us-east-1\",\"label\":\"US East\"},{\"value\":\"eu-west-1\",\"label\":\"EU West\"},{\"value\":\"ap-south-1\",\"label\":\"Asia Pacific\"}],\"data_type\":\"String\"}" }, { "action_id": "features", "type": "checkboxes", "widgets": "{\"text\":\"Enabled Features\",\"description\":\"Select features to enable\",\"setting_level\":\"appLevel\",\"dynamic_widget_populate\":null,\"options\":[{\"value\":\"1\",\"label\":\"Feature A\"},{\"value\":\"2\",\"label\":\"Feature B\"},{\"value\":\"3\",\"label\":\"Feature C\"}],\"data_type\":\"Integer\"}" } ], "connection_level": [ { "action_id": "connection_name", "type": "plain_text_input", "widgets": "{\"text\":\"Connection Name\",\"placeholder\":\"My Connection\",\"description\":\"Friendly name for this connection\",\"data_type\":\"String\",\"setting_level\":\"connectionLevel\"}" }, { "action_id": "auth_token", "type": "plain_text_input", "widgets": "{\"text\":\"Authentication Token\",\"placeholder\":\"Enter your auth token\",\"description\":\"User-specific authentication token\",\"data_type\":\"String\",\"required\":true,\"setting_level\":\"connectionLevel\"}" }, { "action_id": "timeout", "type": "select", "widgets": "{\"text\":\"Request Timeout\",\"description\":\"Maximum request timeout in seconds\",\"dependent_fields\":[],\"setting_level\":\"connectionLevel\",\"dynamic_widget_populate\":null,\"options\":[{\"value\":\"30\",\"label\":\"30 seconds\"},{\"value\":\"60\",\"label\":\"1 minute\"},{\"value\":\"120\",\"label\":\"2 minutes\"}],\"data_type\":\"Number\"}" }, { "action_id": "enable_logging", "type": "radio_buttons", "widgets": "{\"text\":\"Enable Logging\",\"description\":\"Enable detailed request logging\",\"setting_level\":\"connectionLevel\",\"dynamic_widget_populate\":null,\"options\":[{\"value\":\"true\",\"label\":\"Enabled\"},{\"value\":\"false\",\"label\":\"Disabled\"}],\"data_type\":\"Boolean\"}" } ] } } // ...... } } ``` ## Field Description | Field | Description | Required | | :-------------------------------------- | :------------------------------------------------------------------------------- | :-------------------------- | | `custom_form` | Root object containing all custom field configurations | No | | `enable` | To mark the usage of custom fields in app manifest creation. Defaulted to false. | No | | `custom_form.pre_auth` | Pre-authentication custom fields (configured before user connects) | Yes (if custom_form exists) | | `custom_form.pre_auth.app_level` | Array of app-level fields (configured once per app, applies to all users) | No | | `custom_form.pre_auth.connection_level` | Array of connection-level fields (configured per user connection) | No | | `action_id` | Unique identifier for the field | Yes | | `type` | Widget type: `plain_text_input`, `select`, `checkboxes`, `radio_buttons` | Yes | | `widgets` | JSON string with field configuration (label, validation, options, etc.) | Yes | | `new_action_id` | Used when renaming a field to preserve data (contains old action_id) | No | | `widgets.text` | Label displayed to user (e.g., "API Key", "Region") | Yes | | `widgets.description` | Help text explaining the field purpose | No | | `widgets.data_type` | Data type: `String`, `Number`, `Integer`, `Boolean`, `Password` | Yes | | `widgets.setting_level` | Must match array level: `appLevel` or `connectionLevel` | Yes | | `widgets.required` | Whether field is mandatory (default: false) | No | | `widgets.placeholder` | Placeholder text for plain_text_input (e.g., "Enter your API key") | No | | `widgets.multiple` | Allow multiple values for plain_text_input (default: false) | No | | `widgets.options` | Array of {`value, label`} for select / checkboxes / radio_buttons | Yes (for select types) |