Skip to main content
A button in a template can do things when clicked: post a payload to a webhook destination, update the message in place, or open a modal. In the app you configure this with the actions planner. Over the API, the same configuration travels on the button as action_config, and the API checks it before anything is stored.

What a button can carry

Buttons can sit in an actions block, as a section accessory, in context_actions, on a card, or on a carousel card. Where a button sits decides which update strategies make sense:

Payload variables

Dynamic carousel actions automatically retain the selected item. Use {{rowData.id}} in webhook payloads and rowData.id in modal data bindings; context.* continues to refer to the complete message data. This context survives modal submission and replace_card updates. Submitted inputs are under submission.values.*, while resolved modal bindings are under modal.*. this and item are selected-item aliases. Put business IDs in button values or payload fields: generated carousel action IDs include a suffix used for routing. Re-send older messages to use this behavior. GET /v1/templates/block-schema returns this whole contract as data under interactivity, so an assistant can read it rather than remember it.

What the API checks

POST /v1/templates/validate, POST /v1/templates and POST /v1/templates/{id}/versions all check every configured button and refuse, or report, when:
  • the action_config has the wrong shape (an unknown strategy, replace_block without target_block_id, a route without a destination, a message update without idempotency);
  • a destination_id is not an active destination in your organization, or a modal_definition_id is not one of your active modals;
  • a strategy is not available for the button’s position;
  • the complete message metadata cannot fit 4,000 bytes, including wrapper and log references, even after lossless gzip/base64 compression, or exceeds the 65,536-byte decoded safety limit. Action configs travel inside each sent message with its original data, preserving the behavior configured when sent. Existing uncompressed messages remain supported. validate reports raw interactivity.metadata_bytes and adds metadata_transport with the selected encoding, wire_bytes, and budgeted_bytes including reserved logging IDs.
Gzip/base64 compression and metadata_transport diagnostics are an unreleased prototype. Production retains the 3,800-byte event-payload budget until live Slack acceptance and deployment.
Validation answers with valid: false and one error per problem naming the action_id; create and version answer 400 with code: "invalid_data" and the same list under issues. Nothing is stored until every check passes. Use validation errors to fix the configured action before sending.

Complete the workflow

  1. Create a destination and keep its returned ID.
  2. If collecting input, create and activate a modal.
  3. Add the button to a template, validate, save a version, and activate it.
  4. Send to a test channel and trigger the action.
  5. Inspect interaction history and the receiver’s records.
Template, destination and modal creation, template and modal version creation and activation, and destination tests support Idempotency-Key. Reuse the key and identical body only for retries of the same intended operation. In-progress or uncertain outcomes need reconciliation; do not rotate the key to force execution. Action configuration and send data travel with the posted message. Editing a template does not retrofit old Slack messages. Deleted or inactive destinations and modals can make their old buttons fail. MCP clients expose these operations using the same permissions. Read and validate before requesting a write, and preserve idempotency keys for retries.

Supported replacement blocks

Every update strategy accepts concrete blocks with value placeholders. Concrete cards, static carousels (elements), tables, and other concrete message blocks use the shared message compiler. Both clicks and modal submissions use the same replacement logic as the editor preview. Button action_config templates remain deferred until that button’s next click; metadata is generated from the final compiled message before Slack-only sanitization. Dynamic arrayPath blocks, cardTemplate, tasksArrayPath/taskTemplate, directive containers, inline conditional/loop directives, and index arithmetic are unsupported in all update strategies. The editor and API report unsupported_update_construct; runtime rejects these configurations before contacting Slack. Supply concrete replacement blocks, or send a new message using the normal template compiler. Initial sends still support dynamic carousels and directives. {{@index}} is a direct value binding; compute derived indices in your data. Missing and ambiguous targets fail with missing_update_target or ambiguous_update_target. They do not silently append replacements. The preview requires a selected click target for strategies that depend on it.

Older messages and selected-item diagnostics

Deploying handlers or editing a template does not change metadata already attached to a Slack message. Compatibility depends on what the original message retained: An action-ID suffix alone cannot identify an item. Never parse business data from generated action IDs. Put it in a button value or an explicit payload field instead. No deployment can reconstruct item data that an old message never carried. A requested rowData, item, this, or @index binding with no corresponding context fails with missing_item_context. A field absent from an available item reports missing_binding. The same checks apply to webhook payloads/headers, modal data bindings, and replacement blocks. They preserve explicit null, false, and zero values. Required modal bindings and all replacement-block bindings must resolve. Optional legacy root bindings in webhook payloads and modal mappings retain their existing unresolved-placeholder behavior; this compatibility exception does not apply to selected-item bindings. The editor shows these diagnostics in mapping/update previews. Runtime update failures are attached to the original interaction in message update history; modal and webhook mapping failures appear in interaction history. An unresolvable action configuration is reported to the person clicking the button.

Re-send procedure

  1. Open the affected template and inspect the old message’s interaction history. Determine whether the action or selected-item reference is missing; do not choose a row by its position or a duplicated business ID.
  2. Correct and activate the template version. Use explicit business values/payload fields and concrete update blocks. Validate it with representative send data.
  3. Use the normal send workflow with complete current data and the intended workspace/channel. This is a deliberate new send. Use a new idempotency key for this new operation and reuse it only for retries of that operation.
  4. Check the second card’s webhook/modal mapping, its concrete replacement, and the next click. Inspect interaction history for the new message.
  5. Direct users to the new message and retire the old message through your normal channel process. Already-open modals and old message links retain their old context.
LithoBlocks does not automatically repost customer messages or backfill unknowable item data.