Skip to main content

App Options

App Options are the settings an organization fills in when installing your app โ€” API URLs, feature toggles, credentials. You declare them once, at the top level of the manifest, and every part of your app reads from the same set of values: components, functions, the API Proxy and Portal Extension hooks.

Options used to live on components

Earlier app versions declared options per component. That model is retired: all existing component options were migrated to app level, and the platform transparently keeps serving them to consumers that still read options from components. Declare new options only at the top level โ€” deploys that declare an option on a component with the same key as an app-level option are rejected.

Declaring optionsโ€‹

Add a top-level options array to your manifest.json:

manifest.json
{
"name": "My Integration",
"options": [
{ "key": "api_base_url", "label": "API Base URL", "type": "text", "required": true },
{ "key": "sync_enabled", "label": "Enable sync", "type": "boolean" },
{ "key": "api_key", "label": "API Key", "type": "secret", "required": true },
{ "key": "internal_hint", "label": "Routing hint", "type": "text", "sensitive": true }
],
"components": [ ... ]
}
FieldRequiredDescription
keyโœ“Unique identifier across the whole app. This is what you reference everywhere ({{Options.api_key}}, input.app_options.api_key, proxy auth) โ€” treat it as a public contract
typeโœ“text, number, boolean, secret or object
labelโ€”Human-readable label shown to the installing organization
descriptionโ€”Help text shown below the input
requiredโ€”The app installs, but is marked partially successful and stays unusable until all required options are filled
sensitiveโ€”Write-only, server-side only โ€” see below. Always true for type: secret
repeatableโ€”The value becomes a list of entries (each gets a stable server-assigned id)
fieldsobject typeDeclares the sub-fields of an object option โ€” primitives only, no nesting

The installing organization sees all app options in a single App settings card on the app's configuration page.

Sensitive vs. non-sensitiveโ€‹

Every option is one of two kinds โ€” the same model most hosting platforms use for environment variables:

  • Non-sensitive (default) โ€” readable wherever the app runs, including the end-customer's browser: journey blocks, portal blocks, capabilities. Use for URLs, labels, toggles, IDs.
  • Sensitive โ€” write-only and server-side only. The value is never returned by any read API. The installer sees Configured โœ“ and when the value was last changed, and can replace it โ€” but never read it back. Sensitive values only ever surface in server-side channels: API Proxy credential injection, Portal Extension / External Product Catalog hook templates, and function runs.

Options of type: secret are stored encrypted and are always sensitive. Set sensitive: true on a non-secret type for values that aren't credentials but still must not reach a browser (internal endpoints, routing hints).

Rule of thumb: if you would put it in a secret environment variable โ€” API keys, tokens, client secrets โ€” make it type: secret. If in doubt, mark it sensitive; you can't loosen a leaked value after the fact.

Required optionsโ€‹

Marking an option required: true doesn't block the installation itself โ€” the app installs, but is flagged as partially successful and cannot be used until the organization fills in all required values.

Partial installation

Consuming optionsโ€‹

Where the configured values show up, by surface:

SurfaceHow you access optionsSensitive values?
API ProxyReference option keys in the auth configuration โ€” credentials are injected server-sideโœ“
Portal Extension / External Product Catalog hooks{{Options.api_key}} template variables โ€” resolved server-side when the hook firesโœ“
Functionsinput.app_options contains all option values โ€” functions always run server-sideโœ“
Custom Journey Block, Custom Capability, Custom Page, Custom Portal Block (browser code)Options are passed into your component per its surface contractNon-sensitive only

Anything that executes in a browser only ever receives non-sensitive options. There is no way to read a sensitive value from frontend code โ€” route those calls through the API Proxy instead, which attaches the credentials server-side.