Skip to content

Utilities

This page documents top-level helper utilities shipped with slackblocks.

Block Kit Builder URL

block_kit_builder_url(payload, team_id=None) builds a Slack Block Kit Builder URL containing the supplied payload, so you can preview a message, view, or block list in the browser.

Accepted payload shapes:

For a team_id-specific Builder URL (e.g. https://app.slack.com/block-kit-builder/T0123#…), pass team_id="T0123ABCD".

Utilities for working with Slack's Block Kit Builder.

The Builder accepts a URL of the form https://app.slack.com/block-kit-builder/#<JSON> where <JSON> is a URL-encoded JSON payload (typically {"blocks": [...]}). block_kit_builder_url constructs such a URL from any of the shapes the rest of this library renders.

block_kit_builder_url

block_kit_builder_url(payload, team_id=None)

Build a URL that opens payload in Slack's Block Kit Builder.

Use this to preview a message, view, or list of blocks in the browser without manually copying JSON into the Builder.

Parameters:

Name Type Description Default
payload Block | list[Block] | Resolvable | dict[str, Any]

any of:

  • A single Block -- wrapped in {"blocks": [block]}.
  • A list of Block -- wrapped in {"blocks": [...]}.
  • Anything with a _resolve method (Message, WebhookMessage, MessageResponse, View, ModalView, HomeTabView, etc.) -- used as-is.
  • A raw dict -- used as-is. This is the escape hatch for callers building payloads outside the type hierarchy.
required
team_id str | None

optional Slack team ID. When supplied, produces a workspace-specific Builder URL of the form https://app.slack.com/block-kit-builder/T0123#<JSON>. When None (the default), produces the generic URL.

None

Returns:

Type Description
str

A fully-formed Block Kit Builder URL.

Examples:

Single block::

from slackblocks import SectionBlock, block_kit_builder_url

url = block_kit_builder_url(SectionBlock("Hi"))

Multiple blocks::

url = block_kit_builder_url([
    SectionBlock("Heading"),
    DividerBlock(),
])

Existing message::

url = block_kit_builder_url(my_message)

Targeting a specific workspace::

url = block_kit_builder_url(my_message, team_id="T0123ABCD")
Source code in slackblocks/builder.py
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
def block_kit_builder_url(
    payload: Block | list[Block] | Resolvable | dict[str, Any],
    team_id: str | None = None,
) -> str:
    """Build a URL that opens ``payload`` in Slack's Block Kit Builder.

    Use this to preview a message, view, or list of blocks in the browser
    without manually copying JSON into the Builder.

    Args:
        payload: any of:

            - A single ``Block`` -- wrapped in ``{"blocks": [block]}``.
            - A list of ``Block`` -- wrapped in ``{"blocks": [...]}``.
            - Anything with a ``_resolve`` method (``Message``,
              ``WebhookMessage``, ``MessageResponse``, ``View``,
              ``ModalView``, ``HomeTabView``, etc.) -- used as-is.
            - A raw ``dict`` -- used as-is. This is the escape hatch for
              callers building payloads outside the type hierarchy.

        team_id: optional Slack team ID. When supplied, produces a
            workspace-specific Builder URL of the form
            ``https://app.slack.com/block-kit-builder/T0123#<JSON>``.
            When ``None`` (the default), produces the generic URL.

    Returns:
        A fully-formed Block Kit Builder URL.

    Examples:
        Single block::

            from slackblocks import SectionBlock, block_kit_builder_url

            url = block_kit_builder_url(SectionBlock("Hi"))

        Multiple blocks::

            url = block_kit_builder_url([
                SectionBlock("Heading"),
                DividerBlock(),
            ])

        Existing message::

            url = block_kit_builder_url(my_message)

        Targeting a specific workspace::

            url = block_kit_builder_url(my_message, team_id="T0123ABCD")
    """
    body: dict[str, Any]
    if isinstance(payload, Block):
        body = {"blocks": [resolve(payload)]}
    elif isinstance(payload, list):
        body = {"blocks": [resolve(item) for item in payload]}
    elif isinstance(payload, dict):
        body = payload
    else:
        # Anything else with a _resolve() method (Message, View, etc.).
        # resolve() raises TypeError downstream if the object is unsupported.
        resolved = resolve(payload)
        if not isinstance(resolved, dict):
            raise TypeError(
                f"block_kit_builder_url payload must resolve to a dict; got {type(resolved)}."
            )
        body = resolved

    encoded = quote(dumps(body, separators=(",", ":")), safe="")
    prefix = f"{_BUILDER_URL_PREFIX}{team_id}" if team_id else _BUILDER_URL_PREFIX
    return f"{prefix}#{encoded}"

Validation helpers

Lower-level helper functions used across slackblocks for validation and coercion. Most users won't need to call these directly, but they're documented here for completeness and for anyone extending slackblocks with custom block or element types.

This module collects various utility functions used for validating the input to Messages, Blocks, Elements and Objects.

coerce_to_list

coerce_to_list(
    object_or_objects,
    class_,
    allow_none=False,
    min_size=None,
    max_size=None,
)

Takes and object or list of objects and validates its contents, ensuring that the resulting object is a list.

Parameters:

Name Type Description Default
object_or_objects T | list[T] | None

the Python object or objects to validate and convert to a list.

required
class_ Any | list[Any]

the Python type (or class) of objects expected in the list.

required
allow_none bool

whether or not None is a valid input (and thus output) option.

False
min_size int | None

if provided, the length of object_or_objects cannot be smaller than this.

None
max_size int | None

if provided, the length of object_or_objects cannot be larger than this.

None

Returns:

Type Description
list[T] | None

object_or_objects if it was a valid list, [object_or_objects] if it was a valid object, or None if provided and allowed.

Throws

InvalidUsageError: if any of the validation checks fail.

Source code in slackblocks/utils.py
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
def coerce_to_list(
    object_or_objects: T | list[T] | None,
    class_: Any | list[Any],
    allow_none: bool = False,
    min_size: int | None = None,
    max_size: int | None = None,
) -> list[T] | None:
    """
    Takes and object or list of objects and validates its contents, ensuring that the
    resulting object is a list.

    Args:
        object_or_objects: the Python object or objects to validate and convert to a list.
        class_: the Python type (or class) of objects expected in the list.
        allow_none: whether or not None is a valid input (and thus output) option.
        min_size: if provided, the length of `object_or_objects` cannot be smaller than this.
        max_size: if provided, the length of `object_or_objects` cannot be larger than this.

    Returns:
        `object_or_objects` if it was a valid list, `[object_or_objects]` if it was a valid
            object, or `None` if provided and allowed.

    Throws:
        InvalidUsageError: if any of the validation checks fail.
    """
    if object_or_objects is None:
        if allow_none:
            return None
        raise TypeMismatchError(
            f"Type of {object_or_objects} ({type(object_or_objects)})) is "
            f"None should be type `{class_}`."
        )

    return coerce_to_list_nonnull(object_or_objects, class_, min_size, max_size)

coerce_to_list_nonnull

coerce_to_list_nonnull(
    object_or_objects, class_, min_size=None, max_size=None
)

Takes an object or list of objects and validates its contents, ensuring that the resulting object is a list. This version does not handle None values.

Parameters:

Name Type Description Default
object_or_objects T | list[T]

the Python object or objects to validate and convert to a list.

required
class_ Any | list[Any]

the Python type (or class) of objects expected in the list.

required
min_size int | None

if provided, the length of object_or_objects cannot be smaller than this.

None
max_size int | None

if provided, the length of object_or_objects cannot be larger than this.

None

Returns:

Type Description
list[T]

object_or_objects if it was a valid list, [object_or_objects] if it was a valid object.

Throws

InvalidUsageError: if any of the validation checks fail.

Source code in slackblocks/utils.py
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
def coerce_to_list_nonnull(
    object_or_objects: T | list[T],
    class_: Any | list[Any],
    min_size: int | None = None,
    max_size: int | None = None,
) -> list[T]:
    """
    Takes an object or list of objects and validates its contents, ensuring that the
    resulting object is a list. This version does not handle None values.

    Args:
        object_or_objects: the Python object or objects to validate and convert to a list.
        class_: the Python type (or class) of objects expected in the list.
        min_size: if provided, the length of `object_or_objects` cannot be smaller than this.
        max_size: if provided, the length of `object_or_objects` cannot be larger than this.

    Returns:
        `object_or_objects` if it was a valid list, `[object_or_objects]` if it was a valid object.

    Throws:
        InvalidUsageError: if any of the validation checks fail.
    """
    if isinstance(object_or_objects, list):
        items = object_or_objects
    else:
        items = [object_or_objects]

    for item in items:
        if not isinstance(class_, tuple):
            class_ = (class_,)
        if not isinstance(item, class_):
            raise TypeMismatchError(
                f"Type of {item} ({type(item)})) inconsistent with expected type {class_}."
            )

    length = len(items)
    if min_size is not None and length < min_size:
        raise LengthError(
            f"Size ({length}) of list of {type(class_)} is less than `min_size` ({min_size})"
        )

    if max_size is not None and length > max_size:
        raise LengthError(
            f"Size ({length}) of list of {type(class_)} exceeds `max_size` ({max_size})"
        )

    return items

is_hex

is_hex(string)

Determines whether a given string is a valid hexadecimal number.

Parameters:

Name Type Description Default
string str

the string to examine for hex characters.

required

Returns:

Type Description
bool

True if the string is a valid hexadecimal number, otherwise False.

Source code in slackblocks/utils.py
106
107
108
109
110
111
112
113
114
115
116
def is_hex(string: str) -> bool:
    """
    Determines whether a given string is a valid hexadecimal number.

    Args:
        string: the string to examine for hex characters.

    Returns:
        `True` if the string is a valid hexadecimal number, otherwise `False`.
    """
    return all(char in hexdigits for char in string)

validate_action_id

validate_action_id(action_id, allow_none=False)

Action IDs are used in the handing of user interactivity within Slack blocks. This function checks that a given action_id is valid as per the requirements imposed by the Slack API.

See: https://api.slack.com/interactivity/handling

Parameters:

Name Type Description Default
action_id str | None

the action_id string to validate for correctness as per the Slack API.

required
allow_none bool

whether to accept None as a valid value for action_id.

False

Returns:

Type Description
str | None

The original value action_id if all validation checks pass.

Throws

InvalidUsageError if any of the validation checks fail.

Source code in slackblocks/utils.py
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
def validate_action_id(action_id: str | None, allow_none: bool = False) -> str | None:
    """
    Action IDs are used in the handing of user interactivity within Slack blocks.
    This function checks that a given `action_id` is valid as per the requirements
    imposed by the Slack API.

    See: <https://api.slack.com/interactivity/handling>

    Args:
        action_id: the action_id string to validate for correctness as per the Slack API.
        allow_none: whether to accept `None` as a valid value for `action_id`.

    Returns:
        The original value `action_id` if all validation checks pass.

    Throws:
        InvalidUsageError if any of the validation checks fail.
    """
    if action_id is None:
        if not allow_none:
            raise MissingRequiredError("`action_id` cannot be None.")
    else:
        length = len(action_id)
        if length < 1:
            raise LengthError("`action_id` cannot be empty.")
        if length > 255:
            raise LengthError(
                f"`action_id` length ({length}) exceeds limit of 255 characters (id: {action_id})."
            )
    return action_id

validate_int

validate_int(
    num, min_value=None, max_value=None, allow_none=False
)

Performs basic validation checks against a given integer.

Parameters:

Name Type Description Default
num int | None

the number to validate.

required
min_value int | None

if num is less than this value, an error will be thrown.

None
max_value int | None

if num is greater than this value, an error will be thrown.

None
allow_none bool

whether None is a valid value for num. If num is None allow_none is False, an error will be thrown.

False

Returns:

Type Description
int | None

The original value of num if it passes all validation checks.

Throws

InvalidUsageError: if any of the validation checks fail.

Source code in slackblocks/utils.py
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
def validate_int(
    num: int | None,
    min_value: int | None = None,
    max_value: int | None = None,
    allow_none: bool = False,
) -> int | None:
    """
    Performs basic validation checks against a given integer.

    Args:
        num: the number to validate.
        min_value: if `num` is less than this value, an error will be thrown.
        max_value: if `num` is greater than this value, an error will be thrown.
        allow_none: whether `None` is a valid value for `num`. If `num` is `None`
            `allow_none` is `False`, an error will be thrown.

    Returns:
        The original value of `num` if it passes all validation checks.

    Throws:
        InvalidUsageError: if any of the validation checks fail.
    """
    if num is None and not allow_none:
        raise MissingRequiredError("`num` is None, which is disallowed.")
    if num is not None:
        if min_value is not None and num < min_value:
            raise RangeError(f"{num} is less than the minimum {min_value}")
        if max_value is not None and num > max_value:
            raise RangeError(f"{num} exceeds the maximum {max_value}")
    return num

validate_string

validate_string(
    string,
    field_name,
    max_length=None,
    min_length=None,
    allow_none=False,
)

Performs basic validation actions (e.g. length checking) on a given string based on the provided criteria.

Parameters:

Name Type Description Default
string str | None

the string to validate

required
field_name str

the name of the field the string belongs to (for error reporting purposes).

required
min_length int | None

if the string is less than this length, an error will be raised.

None
max_length int | None

if the string is greated than this length, an error will be raised.

None
allow_none bool

whether None is a valid value for the string being validated.

False

Returns:

Type Description
str | None

The original string if it deemed to be valid (i.e. no errors are thrown).

Throws

InvalidUsageError: if any of the validation checks (length, None) fail.

Source code in slackblocks/utils.py
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
def validate_string(
    string: str | None,
    field_name: str,
    max_length: int | None = None,
    min_length: int | None = None,
    allow_none: bool = False,
) -> str | None:
    """
    Performs basic validation actions (e.g. length checking) on a given string
    based on the provided criteria.

    Args:
        string: the string to validate
        field_name: the name of the field the string belongs to (for error reporting purposes).
        min_length: if the string is less than this length, an error will be raised.
        max_length: if the string is greated than this length, an error will be raised.
        allow_none: whether `None` is a valid value for the string being validated.

    Returns:
        The original string if it deemed to be valid (i.e. no errors are thrown).

    Throws:
        InvalidUsageError: if any of the validation checks (length, `None`) fail.
    """
    if string is None:
        if not allow_none:
            raise MissingRequiredError(
                f"Expecting string for field `{field_name}`, cannot be None."
            )
        return None
    return validate_string_nonnull(
        string, field_name=field_name, max_length=max_length, min_length=min_length
    )