Widgets API reference
Manage widget placement, visibility, responsive design options, and flow connections in the project draft.
Use widgets to choose how and where a flow appears. The API returns the stored design settings, not a rendered preview.
Authentication and widget operations
Paths below follow https://api.rightmessage.com/v1/{teamPid}. GET requires read or write; mutations require write. The * ability satisfies both. The shared request conventions cover bearer authentication, headers, project access, and rate limits.
| Method and path | Request | Success |
|---|---|---|
GET /widgets | No filters or pagination parameters | 200, {"data":[RESOURCE]} |
GET /widgets/{widget} | Resource ID from the list | 200, {"data":RESOURCE} |
POST /widgets | Create body below | 201, {"data":RESOURCE} |
PUT or PATCH /widgets/{widget} | Partial body below | 200, {"data":RESOURCE} |
DELETE /widgets/{widget} | No body | 204, empty body |
PUT and PATCH have the same partial-update behavior. An omitted top-level field retains its value. A collection with no resources returns {"data":[]}. Reads return the draft when one exists, otherwise the stable configuration.
Errors and draft effects
The shared error contract applies. Invalid request fields return 422 with message and field-keyed errors. Full-configuration validation can return 500 instead.
Mutations save a draft, not live changes. Publishing applies the whole project draft, including edits made elsewhere. The draft contract covers snapshots, dashboard updates, and save failures.
Widget request fields
Only name is required on create. All fields are optional on update.
| Field | Validation | Create default |
|---|---|---|
name | Nonempty string, maximum 255 | Required |
type | modal, bar, toaster, inline, or takeover | modal |
flow_id | Nullable string. Nonempty IDs must name an existing flow. | null |
is_enabled | Boolean | true |
frequency | startover, immediately, pageview, session, or none | session |
visibility | Object | Conditions null, trigger exitIntent, dismiss rule session |
visibility.conditions | Nullable logic object | null |
visibility.trigger | Nullable string at request validation. The stored schema requires a string. | exitIntent |
options | Design object below | Default plain design |
Visibility updates merge supplied keys. Design updates recursively replace supplied keys while preserving omitted nested keys. These are not whole-object replacements.
Visibility and inline placement
visibility also passes through these stored keys:
| Key | Contract |
|---|---|
areas | String naming embed areas. |
placements | Array of closed objects requiring nonblank string path, nonblank string selector, and position of inside, before, or after. Optional domain is a bare hostname, maximum 253 characters. No scheme, path, port, or wildcard. Stored lowercase. |
dismissRule | Object with type of session, duration, or forever; optional numeric duration; optional unit of minutes, hours, days, or weeks. Type defaults session. |
instantDismiss | Boolean, default false in the configuration schema. |
formSubmitSelector | Open stored value. No dedicated type rule. |
A new inline widget needs a nonblank areas string or at least one complete placement. Placements are valid only for inline widgets. To change an inline widget to another type, clear placements with [] in the same request. Invalid placements return 422.
The following legacy keys must be absent, even when false or empty: show_on_specific_pages, show_pages, hide_on_specific_pages, hide_pages, isWhitelistEnabled, whitelist, isBlacklistEnabled, and blacklist. They return 422 with guidance to use visibility.conditions.
Logic objects accept recursive and, or, and not. Answer conditions use the question condition contract.
The API's default trigger, exitIntent, does not match the visitor runtime, which expects exit. Scroll and time triggers also require a threshold, such as scroll_50pc or time_5s, rather than bare scroll or timed. Set a supported trigger explicitly for non-inline widgets. See the runtime trigger values. Publishing does not correct this API-default mismatch.
Design options
All options are optional. custom_css aliases customCss, and display_targets aliases displayTargets. An alias overrides its camelCase counterpart when both are supplied. Responses use camelCase. The overall options object permits additional keys, but declared fields still undergo schema validation.
| Top-level key | Type and contract |
|---|---|
theme, font, customCss, placement, backButtonLabel, backButtonEnabled, buttonAnimationTrigger | Open schema values; the validator does not enforce a type. |
headingFont | String or null |
darkMode | off or auto |
typeScale | s, m, l, or custom |
nextButtonLabel, skipButtonLabel | Strings, default Next and Skip |
palette, paletteDark | Color settings below; paletteDark accepts null |
fontSize, structure, look | Nested settings below |
headerInfo | Open values at isEnabled, style, imageUrl, title, and subtitle |
progressBar | Open values at isEnabled and baseColor |
displayTargets | Open values at phones, tablets, and desktop; each starts true |
style | Open shadowSize value |
overrides | Closed object accepting only phone and tablet device overrides |
Palette
palette starts with borderColor: "#e2e8f0", contrastColor: "#3b82f6", backgroundColor: "#ffffff", textOnContrastColor: "#ffffff", and textOnBackgroundColor: "#1e293b". Those five keys have open value schemas in the light palette and require strings in paletteDark.
Both palettes accept nullable strings for answerButtonColor, textOnAnswerButtonColor, formFieldColor, formFieldTextColor, formFieldBorderColor, placeholderColor, linkColor, backdropColor, backgroundGradientFrom, backgroundGradientTo, questionHeadingColor, questionTextColor, offerHeadingColor, offerTextColor, headerTitleColor, and headerSubtitleColor. backdropOpacity is a number from 0 through 1 or null.
Font sizes
fontSize has open values for lineHeight, headlineFontSize, formFieldFontSize, descriptionFontSize, answerButtonFontSize, and submitButtonFontSize.
headingFontWeight, bodyFontWeight, and buttonFontWeight are numbers from 400 through 900 or null. submitButtonFontWeight also accepts theme. headerTitleFontSize and headerSubtitleFontSize accept null or nonnegative pixel strings such as 18px or 18.5px.
Structure
Open values are formFieldSpacing, buttonBorderRadius, answerButtonSpacing, containerBorderWidth, containerBorderRadius, and widgetWidth.
Nullable nonnegative pixel strings are submitButtonBorderRadius, fieldBorderRadius, imageHeight, backdropBlur, containerPaddingY, containerPaddingX, titleSpacing, contentSpacing, submitSpacing, and headerSpacing. buttonLetterSpacing and submitButtonLetterSpacing accept null or signed em strings, such as 0.02em or -0.02em.
Look
| Key | Accepted values |
|---|---|
density | compact, comfortable, spacious, custom, null |
buttonStyle, submitButtonStyle | solid, outline, ghost, gradient, null |
buttonSize, submitButtonSize | s, m, l, null |
buttonFullWidth | Boolean or null |
submitButtonFullWidth | Boolean, theme, or null |
buttonUppercase | Boolean |
submitButtonUppercase | Boolean or null |
buttonHover | darken, lighten, lift, none, null |
submitButtonHover | theme, darken, lighten, lift, none, null |
fieldStyle | boxed, underlined, filled, null |
labelPosition | above, inside, hidden, null |
borderStyle | solid, dashed, dotted |
backgroundType | color, gradient, image |
backgroundGradientAngle | Number 0 through 360, or null |
backgroundImageUrl | String or null |
imagePosition | top, left, background, null |
entrance | none, fade, slide, scale, null |
entranceSpeed | slow, normal, fast |
stepTransition | slideLeft, slideUp, slideDown, crossfade, zoom, none, null |
stepTransitionFade | Boolean or null |
closeButtonStyle | icon, circle, text, null |
closeButtonPosition | left, right, null |
backButtonStyle | link, button, icon, null |
skipButtonStyle | link, button, null |
Device overrides
Each overrides.phone or overrides.tablet is closed and accepts only fontSize, structure, and look. Their child objects are also closed.
Device fontSize accepts the same keys listed above. Unlike the base object, lineHeight must be numeric. headlineFontSize, formFieldFontSize, descriptionFontSize, answerButtonFontSize, and submitButtonFontSize must be strings. Weight and header-size constraints remain unchanged.
Device structure accepts the same keys listed above. The formerly open values require strings, except widgetWidth, which also accepts null. Pixel and letter-spacing constraints remain unchanged.
Device look accepts only density, buttonSize, buttonFullWidth, submitButtonSize, and submitButtonFullWidth, with the same value constraints as the base object.
Invalid declared design values return 422 under errors.options before the full configuration save. This differs from malformed nested configuration elsewhere, which can reach a 500.
Widget responses and limitations
The response contains id, name, type, is_enabled, flow_id, frequency, visibility, and options. It serializes only conditions and trigger inside visibility. Placement, area, and dismissal settings are saved but are not echoed there. Do not use that reduced visibility response as proof that an inline widget has no placement.
New IDs use wdg_. The service starts with theme plain, empty customCss, and the palette above. Configuration repair then fills omitted typography, structure, header, progress-bar, and look values; it also supplies paletteDark: null, headingFont: null, and typeScale: "custom". These defaults can depend on widget type, so read the returned options rather than assuming the small create payload is the complete design. Deletion removes the widget only; its flow remains.
Illustrative requests and responses
These illustrative examples use the fictional WorkForge project. The same resource schema covers every CRUD response.
The PATCH example also works with PUT. The create, item-read, and update envelopes have this shape. This response is an excerpt: options also contains the repair-added settings described above. The list places resource objects in its data array. An update returns updated values. DELETE returns no JSON.