Auth flow recipes
OAuth2 client-credentials with refresh
"Connect to the Microsoft Graph API.
URL: https://graph.microsoft.com/v1.0/users
Auth: Bearer Token from OAuth2 client-credentials at
https://login.microsoftonline.com/{{tenant_id}}/oauth2/v2.0/token
with scope https://graph.microsoft.com/.default
Cache the token for its expires_in TTL minus 60 seconds.
On 401 response, force a token refresh and retry once."
API Key in header
"URL: https://api.crowdstrike.com/devices/queries/devices/v1
Auth: API Key in header. Header name: Authorization.
Value format: 'Bearer <key>'.
Encrypt the key via the lock icon."
API Key with separate ID + Secret (CrowdStrike style)
"Authenticate to CrowdStrike Falcon:
1. POST to https://api.crowdstrike.com/oauth2/token with body
client_id=<id>&client_secret=<secret>&grant_type=client_credentials
2. Extract access_token from the response and use it as
Bearer Token for subsequent requests.
3. Cache for response.expires_in seconds."
Basic Auth + API token (Atlassian style)
"URL: https://yourorg.atlassian.net/rest/api/3/issue
Auth: Basic Auth with:
- Username: <your-email>@yourorg.com
- Password: <Atlassian API token> (NOT account password)
The token is generated at https://id.atlassian.com/manage-profile/security/api-tokens."
AWS SigV4 (advanced)
"URL: https://api.us-east-1.amazonaws.com/...
Auth: AWS Signature v4 with our IAM role's access keys.
Service: ec2 (or s3, lambda, etc. as appropriate).
Region: us-east-1.
Composer adds the signing in the Authorization header
on each request."
Pagination recipes
Link header (GitHub style)
"Pagination: Next Page Link / Link header.
Parse the Link header for rel='next' and follow it.
Stop when no rel='next' link is present."
Cursor (Slack / Notion style)
"Pagination: Cursor.
Cursor JSONPath in response: response_metadata.next_cursor
Cursor param name in request: cursor
Stop when cursor is empty string or missing."
Page + size (Atlassian / SaaS style)
"Pagination: Page Number & Size.
Page param: pageStart (1-indexed)
Page size param: pageSize (default 50)
Stop when the response's records array is empty
or when response.total is reached."
Limit + offset (Elasticsearch / Jira style)
"Pagination: Limit/Offset.
Limit param: maxResults (default 100)
Offset param: startAt (default 0)
Stop when records < limit (last page) or when total reached."
Webhook Action recipes
Slack message with Block Kit
"Create a Webhook Action that posts to Slack.
URL: https://hooks.slack.com/services/<workspace>/<channel>/<token>
Method: POST
Inputs:
- channel (string)
- title (string)
- severity (string) — Critical / High / Medium / Low
- description (string)
- device_link (URL)
Body (Block Kit):
{
\"channel\": \"{{input.channel}}\",
\"blocks\": [
{ \"type\": \"header\", \"text\": { \"type\": \"plain_text\", \"text\": \"{{input.title}}\" } },
{ \"type\": \"section\", \"text\": { \"type\": \"mrkdwn\", \"text\": \"*Severity:* {{input.severity}}\\n{{input.description}}\" } },
{ \"type\": \"actions\", \"elements\": [
{ \"type\": \"button\", \"text\": { \"type\": \"plain_text\", \"text\": \"View device\" }, \"url\": \"{{input.device_link}}\" }
] }
]
}"
Microsoft Teams Adaptive Card
"Create a Webhook Action that posts to Microsoft Teams.
URL: <your Teams webhook URL>
Method: POST
Inputs:
- title (string)
- message (string)
- action_url (URL)
Body (Adaptive Card v1.4):
{
\"type\": \"message\",
\"attachments\": [{
\"contentType\": \"application/vnd.microsoft.card.adaptive\",
\"content\": {
\"\\$schema\": \"http://adaptivecards.io/schemas/adaptive-card.json\",
\"type\": \"AdaptiveCard\",
\"version\": \"1.4\",
\"body\": [
{ \"type\": \"TextBlock\", \"size\": \"Large\", \"weight\": \"Bolder\", \"text\": \"{{input.title}}\" },
{ \"type\": \"TextBlock\", \"wrap\": true, \"text\": \"{{input.message}}\" }
],
\"actions\": [
{ \"type\": \"Action.OpenUrl\", \"title\": \"Open\", \"url\": \"{{input.action_url}}\" }
]
}
}]
}"
Jira issue creation
"Create a Webhook Action that opens a Jira issue.
URL: https://<your-org>.atlassian.net/rest/api/3/issue
Method: POST
Auth: Basic (email + API token)
Inputs:
- project_key (string)
- summary (string)
- description (string)
- issue_type (string) — Bug / Task / Story
Body:
{
\"fields\": {
\"project\": { \"key\": \"{{input.project_key}}\" },
\"summary\": \"{{input.summary}}\",
\"description\": {
\"type\": \"doc\",
\"version\": 1,
\"content\": [{ \"type\": \"paragraph\", \"content\": [{ \"type\": \"text\", \"text\": \"{{input.description}}\" }] }]
},
\"issuetype\": { \"name\": \"{{input.issue_type}}\" }
}
}"
ServiceNow incident creation
"Create a Webhook Action that opens a ServiceNow incident.
URL: https://<your-org>.service-now.com/api/now/table/incident
Method: POST
Auth: Basic (or OAuth2)
Inputs:
- short_description (string)
- description (string)
- urgency (number) — 1 (High) / 2 (Medium) / 3 (Low)
- impact (number) — 1 / 2 / 3
Body:
{
\"short_description\": \"{{input.short_description}}\",
\"description\": \"{{input.description}}\",
\"urgency\": {{input.urgency}},
\"impact\": {{input.impact}}
}"
PagerDuty Events API v2
"Create a Webhook Action that pages the on-call via PagerDuty.
URL: https://events.pagerduty.com/v2/enqueue
Method: POST
Inputs:
- routing_key (string) — PagerDuty integration key
- summary (string)
- severity (string) — critical / error / warning / info
- source (string)
Body:
{
\"routing_key\": \"{{input.routing_key}}\",
\"event_action\": \"trigger\",
\"payload\": {
\"summary\": \"{{input.summary}}\",
\"severity\": \"{{input.severity}}\",
\"source\": \"{{input.source}}\"
}
}"
Email via SendGrid (for external recipients)
Email Actions in Dimension can only send to tenant users. For external recipients, use SendGrid (or Postmark, AWS SES, Mailgun, etc.):"Create a Webhook Action that sends email via SendGrid.
URL: https://api.sendgrid.com/v3/mail/send
Method: POST
Auth: Bearer Token (your SendGrid API key)
Inputs:
- to (string) — recipient email
- subject (string)
- body_html (string)
Body:
{
\"personalizations\": [{ \"to\": [{ \"email\": \"{{input.to}}\" }] }],
\"from\": { \"email\": \"noreply@yourorg.com\", \"name\": \"YourOrg\" },
\"subject\": \"{{input.subject}}\",
\"content\": [{ \"type\": \"text/html\", \"value\": \"{{input.body_html}}\" }]
}"
Studio UI compositions
KPI strip + chart + table
"Layout pattern:
- Top: 4 metric cards in a row (each with a value, label, and
24h delta arrow)
- Middle: full-width chart (line for trend, donut for distribution)
- Bottom: sortable / filterable table
Use the Card, MetricCard, LineChart, DonutChart, and
SortableTable component templates."
Master-detail (list + selected-row pane)
"Master-detail layout:
- Left 40%: filterable + sortable table of items
- Right 60%: detail pane that updates when a row is selected
- Title from the selected row's name
- Key facts as a 2-column definition list
- Edit and Delete buttons at the top right
- History / activity feed below
Clicking a row populates the detail pane without a navigation."
Form wizard (multi-step)
"Multi-step form wizard:
Step 1: Basic info (name, department, OS dropdown)
Step 2: Risk classification (toggles for handles-PII,
handles-finance, customer-facing)
Step 3: Review + submit
Persist partial state to the Key Value Store keyed by
session id so users can resume.
On submit, fire the [Action name] with the full form payload."
Filter bar that applies app-wide
"Add a global filter bar at the top of every page in this app:
- Date range picker (last 7 / 30 / 90 days / custom)
- Department dropdown (multi-select)
- Severity dropdown (multi-select)
The filter state lives in the Key Value Store under 'global-filters'.
Every page reads from it. Changing it updates all pages."
Auto-refresh + last-updated indicator
"Auto-refresh the entire app every 60 seconds.
Add a 'Last updated HH:MM:SS' indicator in the top-right of the header.
Use a 1-second timer on the indicator so it counts up between refreshes.
Allow the user to disable auto-refresh via a toggle in the header."
Empty states
"Every table and chart should have a styled empty state when
no data is available. Pattern:
- Centred illustration (use a brand-tinted icon)
- Heading: 'No <thing> found'
- Subheading: a short explainer
- Optional CTA button (e.g. 'Refresh data' or 'Add filter')
Apply across the app."
Distribution recipes
One-click PDF export
"Add a 'Generate PDF' button in the top-right of the header.
Click triggers the PDF export endpoint for A4 Landscape.
Disable the button briefly during generation (show a spinner)."
CSV download
"Add a 'Download CSV' button above each table.
Export the table's currently-filtered, currently-sorted rows
to a CSV file named '<table-name>-YYYY-MM-DD.csv'."
Permalink generator
"Add a 'Copy link to this view' button in the header.
The link should preserve the current filter and sort state
in URL query params, so the recipient lands on the same view.
Show a Toast 'Link copied!' on success."
State patterns
Persist filters across sessions
"Save the user's selected filters to the Key Value Store
under 'filters:<user-id>'. Restore them on app load.
Allow 'Reset filters' to clear the saved state."
Workflow state across pages
"Use the Key Value Store keyed by session id to store partial
form state. Allow users to navigate away and return without
losing what they've typed."
Notes per record
"On every device row, allow the user to add a free-text note.
Persist notes in the Key Value Store under 'notes:device:<device-id>'.
Show a note-count badge on rows that have notes."
Theming recipes
Brand the app
"Apply our brand:
- Primary colour: #16A34A
- Secondary colour: #07C983
- Background: white (light mode) / #0F1115 (dark mode)
- Logo URL: <our logo>
- Brand font: System / our font where supported
- Border radius: 8px on cards and buttons
Add the logo to the header. Use the primary colour for charts and
links. Use semantic colours for status (red/amber/green)."
Wall-display optimised
"Optimise this app for a 4K NOC wall display:
- Dark mode by default (high contrast)
- Larger fonts (16px → 24px on body, 24px → 40px on headings,
60px+ on metric numbers)
- High-contrast palette: bright red for critical, orange for
warnings, green for healthy, white for primary text
- Hide any keyboard-driven UI (filters, search) — wall is read-only
- Auto-refresh every 30 seconds"
See also
AI Composer
Composer toolbar, prompts, Inspect Component
Prompt Engineering
Patterns for writing good Composer prompts
JSON Path Reference
Worked examples for Data / ID / Capture paths
Actions
Full Action editor reference