@tightknitai/slack-block-kit-validator 0.1.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +186 -0
  3. package/dist/helpers/check-card-actions-max.d.ts +16 -0
  4. package/dist/helpers/check-card-actions-max.d.ts.map +1 -0
  5. package/dist/helpers/check-card-actions-max.js +25 -0
  6. package/dist/helpers/check-card-actions-max.js.map +1 -0
  7. package/dist/helpers/check-cumulative-markdown-length.d.ts +12 -0
  8. package/dist/helpers/check-cumulative-markdown-length.d.ts.map +1 -0
  9. package/dist/helpers/check-cumulative-markdown-length.js +23 -0
  10. package/dist/helpers/check-cumulative-markdown-length.js.map +1 -0
  11. package/dist/helpers/check-focus-on-load-uniqueness.d.ts +12 -0
  12. package/dist/helpers/check-focus-on-load-uniqueness.d.ts.map +1 -0
  13. package/dist/helpers/check-focus-on-load-uniqueness.js +52 -0
  14. package/dist/helpers/check-focus-on-load-uniqueness.js.map +1 -0
  15. package/dist/helpers/check-number-input-bounds.d.ts +12 -0
  16. package/dist/helpers/check-number-input-bounds.d.ts.map +1 -0
  17. package/dist/helpers/check-number-input-bounds.js +96 -0
  18. package/dist/helpers/check-number-input-bounds.js.map +1 -0
  19. package/dist/helpers/check-response-url-enabled-context.d.ts +25 -0
  20. package/dist/helpers/check-response-url-enabled-context.d.ts.map +1 -0
  21. package/dist/helpers/check-response-url-enabled-context.js +42 -0
  22. package/dist/helpers/check-response-url-enabled-context.js.map +1 -0
  23. package/dist/helpers/check-single-table-block.d.ts +10 -0
  24. package/dist/helpers/check-single-table-block.d.ts.map +1 -0
  25. package/dist/helpers/check-single-table-block.js +19 -0
  26. package/dist/helpers/check-single-table-block.js.map +1 -0
  27. package/dist/helpers/check-surface-compatibility.d.ts +22 -0
  28. package/dist/helpers/check-surface-compatibility.d.ts.map +1 -0
  29. package/dist/helpers/check-surface-compatibility.js +81 -0
  30. package/dist/helpers/check-surface-compatibility.js.map +1 -0
  31. package/dist/helpers/find-duplicate-block-ids.d.ts +17 -0
  32. package/dist/helpers/find-duplicate-block-ids.d.ts.map +1 -0
  33. package/dist/helpers/find-duplicate-block-ids.js +31 -0
  34. package/dist/helpers/find-duplicate-block-ids.js.map +1 -0
  35. package/dist/index.d.ts +11 -0
  36. package/dist/index.d.ts.map +1 -0
  37. package/dist/index.js +11 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/slack-block-kit.schema.json +1605 -0
  40. package/dist/validate-block-kit.d.ts +33 -0
  41. package/dist/validate-block-kit.d.ts.map +1 -0
  42. package/dist/validate-block-kit.js +135 -0
  43. package/dist/validate-block-kit.js.map +1 -0
  44. package/package.json +64 -0
@@ -0,0 +1,1605 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://tightknit.com/schemas/slack-block-kit.schema.json",
4
+ "title": "Slack Block Kit",
5
+ "description": "JSON Schema (draft 2020-12) for Slack Block Kit payloads. Validates a top-level array of blocks. Individual block, element, and composition object schemas are exposed via $defs for re-use. Compiled from https://docs.slack.dev/reference/block-kit (fetched 2026-04-16). Surface restrictions (messages vs modals vs home) and payload-level rules (e.g. cumulative 12k char markdown limit, single-table-per-message) are documented in $defs descriptions but not enforced at the per-block level.",
6
+ "type": "array",
7
+ "minItems": 1,
8
+ "maxItems": 100,
9
+ "items": { "$ref": "#/$defs/block" },
10
+
11
+ "$defs": {
12
+ "action_id": {
13
+ "type": "string",
14
+ "minLength": 1,
15
+ "maxLength": 255,
16
+ "description": "An identifier for the interactive element. Should be unique among all action_ids used in a single view/message."
17
+ },
18
+
19
+ "block_id": {
20
+ "type": "string",
21
+ "minLength": 1,
22
+ "maxLength": 255,
23
+ "description": "A unique identifier for a block. Should be unique within a single message or view."
24
+ },
25
+
26
+ "plain_text_object": {
27
+ "type": "object",
28
+ "additionalProperties": false,
29
+ "required": ["type", "text"],
30
+ "properties": {
31
+ "type": { "const": "plain_text" },
32
+ "text": { "type": "string", "minLength": 1, "maxLength": 3000 },
33
+ "emoji": { "type": "boolean" }
34
+ }
35
+ },
36
+
37
+ "mrkdwn_text_object": {
38
+ "type": "object",
39
+ "additionalProperties": false,
40
+ "required": ["type", "text"],
41
+ "properties": {
42
+ "type": { "const": "mrkdwn" },
43
+ "text": { "type": "string", "minLength": 1, "maxLength": 3000 },
44
+ "verbatim": { "type": "boolean" }
45
+ }
46
+ },
47
+
48
+ "text_object": {
49
+ "description": "A text object — either plain_text or mrkdwn.",
50
+ "oneOf": [{ "$ref": "#/$defs/plain_text_object" }, { "$ref": "#/$defs/mrkdwn_text_object" }]
51
+ },
52
+
53
+ "confirm_object": {
54
+ "type": "object",
55
+ "additionalProperties": false,
56
+ "required": ["title", "text", "confirm", "deny"],
57
+ "properties": {
58
+ "title": {
59
+ "allOf": [{ "$ref": "#/$defs/plain_text_object" }, { "properties": { "text": { "maxLength": 100 } } }]
60
+ },
61
+ "text": {
62
+ "description": "Per Slack docs examples, this field accepts plain_text OR mrkdwn. Prose on the docs page says plain_text, but the example payload uses mrkdwn.",
63
+ "allOf": [{ "$ref": "#/$defs/text_object" }, { "properties": { "text": { "maxLength": 300 } } }]
64
+ },
65
+ "confirm": {
66
+ "allOf": [{ "$ref": "#/$defs/plain_text_object" }, { "properties": { "text": { "maxLength": 30 } } }]
67
+ },
68
+ "deny": {
69
+ "allOf": [{ "$ref": "#/$defs/plain_text_object" }, { "properties": { "text": { "maxLength": 30 } } }]
70
+ },
71
+ "style": { "enum": ["primary", "danger"] }
72
+ }
73
+ },
74
+
75
+ "option_object_plain_text": {
76
+ "description": "Option object used in select / multi-select menus. text and description must be plain_text. url is not allowed here (overflow only).",
77
+ "type": "object",
78
+ "additionalProperties": false,
79
+ "required": ["text", "value"],
80
+ "properties": {
81
+ "text": {
82
+ "allOf": [{ "$ref": "#/$defs/plain_text_object" }, { "properties": { "text": { "maxLength": 75 } } }]
83
+ },
84
+ "value": { "type": "string", "minLength": 1, "maxLength": 150 },
85
+ "description": {
86
+ "allOf": [{ "$ref": "#/$defs/plain_text_object" }, { "properties": { "text": { "maxLength": 75 } } }]
87
+ }
88
+ }
89
+ },
90
+
91
+ "option_object_overflow": {
92
+ "description": "Option object used in overflow menus. Adds optional url field.",
93
+ "type": "object",
94
+ "additionalProperties": false,
95
+ "required": ["text", "value"],
96
+ "properties": {
97
+ "text": {
98
+ "allOf": [{ "$ref": "#/$defs/plain_text_object" }, { "properties": { "text": { "maxLength": 75 } } }]
99
+ },
100
+ "value": { "type": "string", "minLength": 1, "maxLength": 150 },
101
+ "description": {
102
+ "allOf": [{ "$ref": "#/$defs/plain_text_object" }, { "properties": { "text": { "maxLength": 75 } } }]
103
+ },
104
+ "url": { "type": "string", "format": "uri", "maxLength": 3000 }
105
+ }
106
+ },
107
+
108
+ "option_object_radio_or_checkbox": {
109
+ "description": "Option object used in radio_buttons and checkboxes elements. text and description may be plain_text or mrkdwn.",
110
+ "type": "object",
111
+ "additionalProperties": false,
112
+ "required": ["text", "value"],
113
+ "properties": {
114
+ "text": {
115
+ "oneOf": [
116
+ {
117
+ "allOf": [{ "$ref": "#/$defs/plain_text_object" }, { "properties": { "text": { "maxLength": 75 } } }]
118
+ },
119
+ {
120
+ "allOf": [{ "$ref": "#/$defs/mrkdwn_text_object" }, { "properties": { "text": { "maxLength": 75 } } }]
121
+ }
122
+ ]
123
+ },
124
+ "value": { "type": "string", "minLength": 1, "maxLength": 150 },
125
+ "description": {
126
+ "oneOf": [
127
+ {
128
+ "allOf": [{ "$ref": "#/$defs/plain_text_object" }, { "properties": { "text": { "maxLength": 75 } } }]
129
+ },
130
+ {
131
+ "allOf": [{ "$ref": "#/$defs/mrkdwn_text_object" }, { "properties": { "text": { "maxLength": 75 } } }]
132
+ }
133
+ ]
134
+ }
135
+ }
136
+ },
137
+
138
+ "option_group_object": {
139
+ "type": "object",
140
+ "additionalProperties": false,
141
+ "required": ["label", "options"],
142
+ "properties": {
143
+ "label": {
144
+ "allOf": [{ "$ref": "#/$defs/plain_text_object" }, { "properties": { "text": { "maxLength": 75 } } }]
145
+ },
146
+ "options": {
147
+ "type": "array",
148
+ "minItems": 1,
149
+ "maxItems": 100,
150
+ "items": { "$ref": "#/$defs/option_object_plain_text" }
151
+ }
152
+ }
153
+ },
154
+
155
+ "slack_file_object": {
156
+ "description": "Reference to a Slack file. Exactly one of url or id must be provided. Supported file types: png, jpg, jpeg, gif.",
157
+ "type": "object",
158
+ "additionalProperties": false,
159
+ "properties": {
160
+ "url": { "type": "string", "format": "uri" },
161
+ "id": { "type": "string", "minLength": 1 }
162
+ },
163
+ "oneOf": [
164
+ { "required": ["url"], "not": { "required": ["id"] } },
165
+ { "required": ["id"], "not": { "required": ["url"] } }
166
+ ]
167
+ },
168
+
169
+ "dispatch_action_config_object": {
170
+ "type": "object",
171
+ "additionalProperties": false,
172
+ "required": ["trigger_actions_on"],
173
+ "properties": {
174
+ "trigger_actions_on": {
175
+ "type": "array",
176
+ "minItems": 1,
177
+ "maxItems": 2,
178
+ "uniqueItems": true,
179
+ "items": { "enum": ["on_enter_pressed", "on_character_entered"] }
180
+ }
181
+ }
182
+ },
183
+
184
+ "conversation_filter_object": {
185
+ "description": "Filter object for conversations_select / multi_conversations_select. At least one of include / exclude_external_shared_channels / exclude_bot_users must be present.",
186
+ "type": "object",
187
+ "additionalProperties": false,
188
+ "minProperties": 1,
189
+ "properties": {
190
+ "include": {
191
+ "type": "array",
192
+ "minItems": 1,
193
+ "uniqueItems": true,
194
+ "items": { "enum": ["im", "mpim", "private", "public"] }
195
+ },
196
+ "exclude_external_shared_channels": { "type": "boolean" },
197
+ "exclude_bot_users": { "type": "boolean" }
198
+ }
199
+ },
200
+
201
+ "trigger_object": {
202
+ "type": "object",
203
+ "additionalProperties": false,
204
+ "required": ["url"],
205
+ "properties": {
206
+ "url": { "type": "string", "format": "uri" },
207
+ "customizable_input_parameters": {
208
+ "type": "array",
209
+ "items": {
210
+ "type": "object",
211
+ "additionalProperties": false,
212
+ "required": ["name", "value"],
213
+ "properties": {
214
+ "name": { "type": "string", "minLength": 1 },
215
+ "value": {}
216
+ }
217
+ }
218
+ }
219
+ }
220
+ },
221
+
222
+ "workflow_object": {
223
+ "type": "object",
224
+ "additionalProperties": false,
225
+ "required": ["trigger"],
226
+ "properties": {
227
+ "trigger": { "$ref": "#/$defs/trigger_object" }
228
+ }
229
+ },
230
+
231
+ "placeholder_object": {
232
+ "description": "Reusable placeholder text object (plain_text only, max 150 chars).",
233
+ "allOf": [{ "$ref": "#/$defs/plain_text_object" }, { "properties": { "text": { "maxLength": 150 } } }]
234
+ },
235
+
236
+ "button_element": {
237
+ "type": "object",
238
+ "additionalProperties": false,
239
+ "required": ["type", "text"],
240
+ "properties": {
241
+ "type": { "const": "button" },
242
+ "text": {
243
+ "allOf": [{ "$ref": "#/$defs/plain_text_object" }, { "properties": { "text": { "maxLength": 75 } } }]
244
+ },
245
+ "action_id": { "$ref": "#/$defs/action_id" },
246
+ "url": { "type": "string", "format": "uri", "maxLength": 3000 },
247
+ "value": { "type": "string", "minLength": 1, "maxLength": 2000 },
248
+ "style": { "enum": ["primary", "danger"] },
249
+ "confirm": { "$ref": "#/$defs/confirm_object" },
250
+ "accessibility_label": {
251
+ "type": "string",
252
+ "minLength": 1,
253
+ "maxLength": 75
254
+ }
255
+ }
256
+ },
257
+
258
+ "icon_button_element": {
259
+ "description": "Icon button — only valid inside a context_actions block.",
260
+ "type": "object",
261
+ "additionalProperties": false,
262
+ "required": ["type", "icon", "text"],
263
+ "properties": {
264
+ "type": { "const": "icon_button" },
265
+ "icon": { "enum": ["trash"] },
266
+ "text": {
267
+ "allOf": [{ "$ref": "#/$defs/plain_text_object" }, { "properties": { "text": { "maxLength": 75 } } }]
268
+ },
269
+ "action_id": { "$ref": "#/$defs/action_id" },
270
+ "value": { "type": "string", "minLength": 1, "maxLength": 2000 },
271
+ "confirm": { "$ref": "#/$defs/confirm_object" },
272
+ "accessibility_label": {
273
+ "type": "string",
274
+ "minLength": 1,
275
+ "maxLength": 75
276
+ },
277
+ "visible_to_user_ids": {
278
+ "type": "array",
279
+ "items": { "type": "string", "pattern": "^[UW][A-Z0-9]+$" }
280
+ }
281
+ }
282
+ },
283
+
284
+ "checkboxes_element": {
285
+ "type": "object",
286
+ "additionalProperties": false,
287
+ "required": ["type", "options"],
288
+ "properties": {
289
+ "type": { "const": "checkboxes" },
290
+ "action_id": { "$ref": "#/$defs/action_id" },
291
+ "options": {
292
+ "type": "array",
293
+ "minItems": 1,
294
+ "maxItems": 10,
295
+ "items": { "$ref": "#/$defs/option_object_radio_or_checkbox" }
296
+ },
297
+ "initial_options": {
298
+ "type": "array",
299
+ "minItems": 1,
300
+ "items": { "$ref": "#/$defs/option_object_radio_or_checkbox" }
301
+ },
302
+ "confirm": { "$ref": "#/$defs/confirm_object" },
303
+ "focus_on_load": { "type": "boolean" }
304
+ }
305
+ },
306
+
307
+ "datepicker_element": {
308
+ "type": "object",
309
+ "additionalProperties": false,
310
+ "required": ["type"],
311
+ "properties": {
312
+ "type": { "const": "datepicker" },
313
+ "action_id": { "$ref": "#/$defs/action_id" },
314
+ "initial_date": {
315
+ "type": "string",
316
+ "pattern": "^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$"
317
+ },
318
+ "confirm": { "$ref": "#/$defs/confirm_object" },
319
+ "focus_on_load": { "type": "boolean" },
320
+ "placeholder": { "$ref": "#/$defs/placeholder_object" }
321
+ }
322
+ },
323
+
324
+ "datetimepicker_element": {
325
+ "type": "object",
326
+ "additionalProperties": false,
327
+ "required": ["type"],
328
+ "properties": {
329
+ "type": { "const": "datetimepicker" },
330
+ "action_id": { "$ref": "#/$defs/action_id" },
331
+ "initial_date_time": {
332
+ "type": "integer",
333
+ "minimum": 0,
334
+ "maximum": 9999999999
335
+ },
336
+ "confirm": { "$ref": "#/$defs/confirm_object" },
337
+ "focus_on_load": { "type": "boolean" }
338
+ }
339
+ },
340
+
341
+ "timepicker_element": {
342
+ "type": "object",
343
+ "additionalProperties": false,
344
+ "required": ["type"],
345
+ "properties": {
346
+ "type": { "const": "timepicker" },
347
+ "action_id": { "$ref": "#/$defs/action_id" },
348
+ "initial_time": {
349
+ "type": "string",
350
+ "pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$"
351
+ },
352
+ "confirm": { "$ref": "#/$defs/confirm_object" },
353
+ "focus_on_load": { "type": "boolean" },
354
+ "placeholder": { "$ref": "#/$defs/placeholder_object" },
355
+ "timezone": { "type": "string", "minLength": 1 }
356
+ }
357
+ },
358
+
359
+ "email_input_element": {
360
+ "description": "Must be used inside an input block.",
361
+ "type": "object",
362
+ "additionalProperties": false,
363
+ "required": ["type"],
364
+ "properties": {
365
+ "type": { "const": "email_text_input" },
366
+ "action_id": { "$ref": "#/$defs/action_id" },
367
+ "initial_value": { "type": "string" },
368
+ "dispatch_action_config": {
369
+ "$ref": "#/$defs/dispatch_action_config_object"
370
+ },
371
+ "focus_on_load": { "type": "boolean" },
372
+ "placeholder": { "$ref": "#/$defs/placeholder_object" }
373
+ }
374
+ },
375
+
376
+ "url_input_element": {
377
+ "description": "Must be used inside an input block.",
378
+ "type": "object",
379
+ "additionalProperties": false,
380
+ "required": ["type"],
381
+ "properties": {
382
+ "type": { "const": "url_text_input" },
383
+ "action_id": { "$ref": "#/$defs/action_id" },
384
+ "initial_value": { "type": "string" },
385
+ "dispatch_action_config": {
386
+ "$ref": "#/$defs/dispatch_action_config_object"
387
+ },
388
+ "focus_on_load": { "type": "boolean" },
389
+ "placeholder": { "$ref": "#/$defs/placeholder_object" }
390
+ }
391
+ },
392
+
393
+ "number_input_element": {
394
+ "description": "Must be used inside an input block. min_value must not exceed max_value.",
395
+ "type": "object",
396
+ "additionalProperties": false,
397
+ "required": ["type", "is_decimal_allowed"],
398
+ "properties": {
399
+ "type": { "const": "number_input" },
400
+ "is_decimal_allowed": { "type": "boolean" },
401
+ "action_id": { "$ref": "#/$defs/action_id" },
402
+ "initial_value": {
403
+ "type": "string",
404
+ "pattern": "^-?[0-9]+(\\.[0-9]+)?$"
405
+ },
406
+ "min_value": { "type": "string", "pattern": "^-?[0-9]+(\\.[0-9]+)?$" },
407
+ "max_value": { "type": "string", "pattern": "^-?[0-9]+(\\.[0-9]+)?$" },
408
+ "dispatch_action_config": {
409
+ "$ref": "#/$defs/dispatch_action_config_object"
410
+ },
411
+ "focus_on_load": { "type": "boolean" },
412
+ "placeholder": { "$ref": "#/$defs/placeholder_object" }
413
+ }
414
+ },
415
+
416
+ "plain_text_input_element": {
417
+ "description": "Must be used inside an input block.",
418
+ "type": "object",
419
+ "additionalProperties": false,
420
+ "required": ["type"],
421
+ "properties": {
422
+ "type": { "const": "plain_text_input" },
423
+ "action_id": { "$ref": "#/$defs/action_id" },
424
+ "initial_value": { "type": "string" },
425
+ "multiline": { "type": "boolean" },
426
+ "min_length": { "type": "integer", "minimum": 0, "maximum": 3000 },
427
+ "max_length": { "type": "integer", "minimum": 1, "maximum": 3000 },
428
+ "dispatch_action_config": {
429
+ "$ref": "#/$defs/dispatch_action_config_object"
430
+ },
431
+ "focus_on_load": { "type": "boolean" },
432
+ "placeholder": { "$ref": "#/$defs/placeholder_object" }
433
+ }
434
+ },
435
+
436
+ "radio_buttons_element": {
437
+ "type": "object",
438
+ "additionalProperties": false,
439
+ "required": ["type", "options"],
440
+ "properties": {
441
+ "type": { "const": "radio_buttons" },
442
+ "action_id": { "$ref": "#/$defs/action_id" },
443
+ "options": {
444
+ "type": "array",
445
+ "minItems": 1,
446
+ "maxItems": 10,
447
+ "items": { "$ref": "#/$defs/option_object_radio_or_checkbox" }
448
+ },
449
+ "initial_option": { "$ref": "#/$defs/option_object_radio_or_checkbox" },
450
+ "confirm": { "$ref": "#/$defs/confirm_object" },
451
+ "focus_on_load": { "type": "boolean" }
452
+ }
453
+ },
454
+
455
+ "feedback_button_subobject": {
456
+ "type": "object",
457
+ "additionalProperties": false,
458
+ "required": ["text", "value"],
459
+ "properties": {
460
+ "text": {
461
+ "allOf": [{ "$ref": "#/$defs/plain_text_object" }, { "properties": { "text": { "maxLength": 75 } } }]
462
+ },
463
+ "value": { "type": "string", "minLength": 1, "maxLength": 2000 },
464
+ "accessibility_label": {
465
+ "type": "string",
466
+ "minLength": 1,
467
+ "maxLength": 75
468
+ }
469
+ }
470
+ },
471
+
472
+ "feedback_buttons_element": {
473
+ "description": "Must be used inside a context_actions block.",
474
+ "type": "object",
475
+ "additionalProperties": false,
476
+ "required": ["type", "positive_button", "negative_button"],
477
+ "properties": {
478
+ "type": { "const": "feedback_buttons" },
479
+ "positive_button": { "$ref": "#/$defs/feedback_button_subobject" },
480
+ "negative_button": { "$ref": "#/$defs/feedback_button_subobject" },
481
+ "action_id": { "$ref": "#/$defs/action_id" }
482
+ }
483
+ },
484
+
485
+ "workflow_button_element": {
486
+ "type": "object",
487
+ "additionalProperties": false,
488
+ "required": ["type", "text", "workflow", "action_id"],
489
+ "properties": {
490
+ "type": { "const": "workflow_button" },
491
+ "text": {
492
+ "allOf": [{ "$ref": "#/$defs/plain_text_object" }, { "properties": { "text": { "maxLength": 75 } } }]
493
+ },
494
+ "workflow": { "$ref": "#/$defs/workflow_object" },
495
+ "action_id": { "$ref": "#/$defs/action_id" },
496
+ "style": { "enum": ["primary", "danger"] },
497
+ "accessibility_label": {
498
+ "type": "string",
499
+ "minLength": 1,
500
+ "maxLength": 75
501
+ }
502
+ }
503
+ },
504
+
505
+ "static_select_element": {
506
+ "type": "object",
507
+ "additionalProperties": false,
508
+ "required": ["type"],
509
+ "oneOf": [
510
+ { "required": ["options"], "not": { "required": ["option_groups"] } },
511
+ { "required": ["option_groups"], "not": { "required": ["options"] } }
512
+ ],
513
+ "properties": {
514
+ "type": { "const": "static_select" },
515
+ "action_id": { "$ref": "#/$defs/action_id" },
516
+ "options": {
517
+ "type": "array",
518
+ "minItems": 1,
519
+ "maxItems": 100,
520
+ "items": { "$ref": "#/$defs/option_object_plain_text" }
521
+ },
522
+ "option_groups": {
523
+ "type": "array",
524
+ "minItems": 1,
525
+ "maxItems": 100,
526
+ "items": { "$ref": "#/$defs/option_group_object" }
527
+ },
528
+ "initial_option": { "$ref": "#/$defs/option_object_plain_text" },
529
+ "confirm": { "$ref": "#/$defs/confirm_object" },
530
+ "focus_on_load": { "type": "boolean" },
531
+ "placeholder": { "$ref": "#/$defs/placeholder_object" }
532
+ }
533
+ },
534
+
535
+ "external_select_element": {
536
+ "type": "object",
537
+ "additionalProperties": false,
538
+ "required": ["type"],
539
+ "properties": {
540
+ "type": { "const": "external_select" },
541
+ "action_id": { "$ref": "#/$defs/action_id" },
542
+ "initial_option": { "$ref": "#/$defs/option_object_plain_text" },
543
+ "min_query_length": { "type": "integer", "minimum": 0 },
544
+ "confirm": { "$ref": "#/$defs/confirm_object" },
545
+ "focus_on_load": { "type": "boolean" },
546
+ "placeholder": { "$ref": "#/$defs/placeholder_object" }
547
+ }
548
+ },
549
+
550
+ "users_select_element": {
551
+ "type": "object",
552
+ "additionalProperties": false,
553
+ "required": ["type"],
554
+ "properties": {
555
+ "type": { "const": "users_select" },
556
+ "action_id": { "$ref": "#/$defs/action_id" },
557
+ "initial_user": { "type": "string", "pattern": "^[UW][A-Z0-9]+$" },
558
+ "confirm": { "$ref": "#/$defs/confirm_object" },
559
+ "focus_on_load": { "type": "boolean" },
560
+ "placeholder": { "$ref": "#/$defs/placeholder_object" }
561
+ }
562
+ },
563
+
564
+ "conversations_select_element": {
565
+ "description": "response_url_enabled is only valid when used inside an input block within a modal.",
566
+ "type": "object",
567
+ "additionalProperties": false,
568
+ "required": ["type"],
569
+ "properties": {
570
+ "type": { "const": "conversations_select" },
571
+ "action_id": { "$ref": "#/$defs/action_id" },
572
+ "initial_conversation": { "type": "string", "minLength": 1 },
573
+ "default_to_current_conversation": { "type": "boolean" },
574
+ "confirm": { "$ref": "#/$defs/confirm_object" },
575
+ "response_url_enabled": { "type": "boolean" },
576
+ "filter": { "$ref": "#/$defs/conversation_filter_object" },
577
+ "focus_on_load": { "type": "boolean" },
578
+ "placeholder": { "$ref": "#/$defs/placeholder_object" }
579
+ }
580
+ },
581
+
582
+ "channels_select_element": {
583
+ "description": "response_url_enabled is only valid when used inside an input block within a modal.",
584
+ "type": "object",
585
+ "additionalProperties": false,
586
+ "required": ["type"],
587
+ "properties": {
588
+ "type": { "const": "channels_select" },
589
+ "action_id": { "$ref": "#/$defs/action_id" },
590
+ "initial_channel": { "type": "string", "pattern": "^[CG][A-Z0-9]+$" },
591
+ "confirm": { "$ref": "#/$defs/confirm_object" },
592
+ "response_url_enabled": { "type": "boolean" },
593
+ "focus_on_load": { "type": "boolean" },
594
+ "placeholder": { "$ref": "#/$defs/placeholder_object" }
595
+ }
596
+ },
597
+
598
+ "multi_static_select_element": {
599
+ "type": "object",
600
+ "additionalProperties": false,
601
+ "required": ["type"],
602
+ "oneOf": [
603
+ { "required": ["options"], "not": { "required": ["option_groups"] } },
604
+ { "required": ["option_groups"], "not": { "required": ["options"] } }
605
+ ],
606
+ "properties": {
607
+ "type": { "const": "multi_static_select" },
608
+ "action_id": { "$ref": "#/$defs/action_id" },
609
+ "options": {
610
+ "type": "array",
611
+ "minItems": 1,
612
+ "maxItems": 100,
613
+ "items": { "$ref": "#/$defs/option_object_plain_text" }
614
+ },
615
+ "option_groups": {
616
+ "type": "array",
617
+ "minItems": 1,
618
+ "maxItems": 100,
619
+ "items": { "$ref": "#/$defs/option_group_object" }
620
+ },
621
+ "initial_options": {
622
+ "type": "array",
623
+ "minItems": 1,
624
+ "items": { "$ref": "#/$defs/option_object_plain_text" }
625
+ },
626
+ "confirm": { "$ref": "#/$defs/confirm_object" },
627
+ "max_selected_items": { "type": "integer", "minimum": 1 },
628
+ "focus_on_load": { "type": "boolean" },
629
+ "placeholder": { "$ref": "#/$defs/placeholder_object" }
630
+ }
631
+ },
632
+
633
+ "multi_external_select_element": {
634
+ "type": "object",
635
+ "additionalProperties": false,
636
+ "required": ["type"],
637
+ "properties": {
638
+ "type": { "const": "multi_external_select" },
639
+ "action_id": { "$ref": "#/$defs/action_id" },
640
+ "min_query_length": { "type": "integer", "minimum": 0 },
641
+ "initial_options": {
642
+ "type": "array",
643
+ "minItems": 1,
644
+ "items": { "$ref": "#/$defs/option_object_plain_text" }
645
+ },
646
+ "confirm": { "$ref": "#/$defs/confirm_object" },
647
+ "max_selected_items": { "type": "integer", "minimum": 1 },
648
+ "focus_on_load": { "type": "boolean" },
649
+ "placeholder": { "$ref": "#/$defs/placeholder_object" }
650
+ }
651
+ },
652
+
653
+ "multi_users_select_element": {
654
+ "type": "object",
655
+ "additionalProperties": false,
656
+ "required": ["type"],
657
+ "properties": {
658
+ "type": { "const": "multi_users_select" },
659
+ "action_id": { "$ref": "#/$defs/action_id" },
660
+ "initial_users": {
661
+ "type": "array",
662
+ "minItems": 1,
663
+ "items": { "type": "string", "pattern": "^[UW][A-Z0-9]+$" }
664
+ },
665
+ "confirm": { "$ref": "#/$defs/confirm_object" },
666
+ "max_selected_items": { "type": "integer", "minimum": 1 },
667
+ "focus_on_load": { "type": "boolean" },
668
+ "placeholder": { "$ref": "#/$defs/placeholder_object" }
669
+ }
670
+ },
671
+
672
+ "multi_conversations_select_element": {
673
+ "type": "object",
674
+ "additionalProperties": false,
675
+ "required": ["type"],
676
+ "properties": {
677
+ "type": { "const": "multi_conversations_select" },
678
+ "action_id": { "$ref": "#/$defs/action_id" },
679
+ "initial_conversations": {
680
+ "type": "array",
681
+ "minItems": 1,
682
+ "items": { "type": "string", "minLength": 1 }
683
+ },
684
+ "default_to_current_conversation": { "type": "boolean" },
685
+ "confirm": { "$ref": "#/$defs/confirm_object" },
686
+ "max_selected_items": { "type": "integer", "minimum": 1 },
687
+ "filter": { "$ref": "#/$defs/conversation_filter_object" },
688
+ "focus_on_load": { "type": "boolean" },
689
+ "placeholder": { "$ref": "#/$defs/placeholder_object" }
690
+ }
691
+ },
692
+
693
+ "multi_channels_select_element": {
694
+ "type": "object",
695
+ "additionalProperties": false,
696
+ "required": ["type"],
697
+ "properties": {
698
+ "type": { "const": "multi_channels_select" },
699
+ "action_id": { "$ref": "#/$defs/action_id" },
700
+ "initial_channels": {
701
+ "type": "array",
702
+ "minItems": 1,
703
+ "items": { "type": "string", "pattern": "^[CG][A-Z0-9]+$" }
704
+ },
705
+ "confirm": { "$ref": "#/$defs/confirm_object" },
706
+ "max_selected_items": { "type": "integer", "minimum": 1 },
707
+ "focus_on_load": { "type": "boolean" },
708
+ "placeholder": { "$ref": "#/$defs/placeholder_object" }
709
+ }
710
+ },
711
+
712
+ "overflow_element": {
713
+ "description": "Must be used inside a section or actions block. Up to 5 options.",
714
+ "type": "object",
715
+ "additionalProperties": false,
716
+ "required": ["type", "options"],
717
+ "properties": {
718
+ "type": { "const": "overflow" },
719
+ "action_id": { "$ref": "#/$defs/action_id" },
720
+ "options": {
721
+ "type": "array",
722
+ "minItems": 1,
723
+ "maxItems": 5,
724
+ "items": { "$ref": "#/$defs/option_object_overflow" }
725
+ },
726
+ "confirm": { "$ref": "#/$defs/confirm_object" }
727
+ }
728
+ },
729
+
730
+ "rich_text_input_element": {
731
+ "description": "Must be used inside an input block.",
732
+ "type": "object",
733
+ "additionalProperties": false,
734
+ "required": ["type", "action_id"],
735
+ "properties": {
736
+ "type": { "const": "rich_text_input" },
737
+ "action_id": { "$ref": "#/$defs/action_id" },
738
+ "initial_value": { "$ref": "#/$defs/rich_text_block" },
739
+ "dispatch_action_config": {
740
+ "$ref": "#/$defs/dispatch_action_config_object"
741
+ },
742
+ "focus_on_load": { "type": "boolean" },
743
+ "placeholder": { "$ref": "#/$defs/placeholder_object" }
744
+ }
745
+ },
746
+
747
+ "file_input_element": {
748
+ "description": "Must be used inside an input block in modals only. Requires files:read OAuth scope. 10MB per-file limit (not enforceable in JSON Schema).",
749
+ "type": "object",
750
+ "additionalProperties": false,
751
+ "required": ["type"],
752
+ "properties": {
753
+ "type": { "const": "file_input" },
754
+ "action_id": { "$ref": "#/$defs/action_id" },
755
+ "filetypes": {
756
+ "type": "array",
757
+ "minItems": 1,
758
+ "items": { "type": "string", "minLength": 1 }
759
+ },
760
+ "max_files": { "type": "integer", "minimum": 1, "maximum": 10 }
761
+ }
762
+ },
763
+
764
+ "image_element": {
765
+ "description": "Must be used inside a section or context block. Either image_url or slack_file is required.",
766
+ "type": "object",
767
+ "additionalProperties": false,
768
+ "required": ["type", "alt_text"],
769
+ "oneOf": [
770
+ { "required": ["image_url"], "not": { "required": ["slack_file"] } },
771
+ { "required": ["slack_file"], "not": { "required": ["image_url"] } }
772
+ ],
773
+ "properties": {
774
+ "type": { "const": "image" },
775
+ "alt_text": { "type": "string", "minLength": 1 },
776
+ "image_url": { "type": "string", "format": "uri", "maxLength": 3000 },
777
+ "slack_file": { "$ref": "#/$defs/slack_file_object" }
778
+ }
779
+ },
780
+
781
+ "url_source_element": {
782
+ "description": "URL source element — only valid inside a task_card block's sources array.",
783
+ "type": "object",
784
+ "additionalProperties": false,
785
+ "required": ["type", "url", "text"],
786
+ "properties": {
787
+ "type": { "const": "url" },
788
+ "url": { "type": "string", "format": "uri" },
789
+ "text": { "type": "string", "minLength": 1 }
790
+ }
791
+ },
792
+
793
+ "actions_block_element": {
794
+ "description": "Elements allowed inside an actions block.",
795
+ "oneOf": [
796
+ { "$ref": "#/$defs/button_element" },
797
+ { "$ref": "#/$defs/checkboxes_element" },
798
+ { "$ref": "#/$defs/datepicker_element" },
799
+ { "$ref": "#/$defs/datetimepicker_element" },
800
+ { "$ref": "#/$defs/timepicker_element" },
801
+ { "$ref": "#/$defs/overflow_element" },
802
+ { "$ref": "#/$defs/radio_buttons_element" },
803
+ { "$ref": "#/$defs/static_select_element" },
804
+ { "$ref": "#/$defs/external_select_element" },
805
+ { "$ref": "#/$defs/users_select_element" },
806
+ { "$ref": "#/$defs/conversations_select_element" },
807
+ { "$ref": "#/$defs/channels_select_element" },
808
+ { "$ref": "#/$defs/multi_static_select_element" },
809
+ { "$ref": "#/$defs/multi_external_select_element" },
810
+ { "$ref": "#/$defs/multi_users_select_element" },
811
+ { "$ref": "#/$defs/multi_conversations_select_element" },
812
+ { "$ref": "#/$defs/multi_channels_select_element" },
813
+ { "$ref": "#/$defs/workflow_button_element" }
814
+ ]
815
+ },
816
+
817
+ "section_accessory_element": {
818
+ "description": "Elements that may appear as the accessory of a section block. datetimepicker is intentionally excluded — docs say it 'must be used inside the actions block or input block'.",
819
+ "oneOf": [
820
+ { "$ref": "#/$defs/button_element" },
821
+ { "$ref": "#/$defs/checkboxes_element" },
822
+ { "$ref": "#/$defs/datepicker_element" },
823
+ { "$ref": "#/$defs/timepicker_element" },
824
+ { "$ref": "#/$defs/image_element" },
825
+ { "$ref": "#/$defs/overflow_element" },
826
+ { "$ref": "#/$defs/radio_buttons_element" },
827
+ { "$ref": "#/$defs/static_select_element" },
828
+ { "$ref": "#/$defs/external_select_element" },
829
+ { "$ref": "#/$defs/users_select_element" },
830
+ { "$ref": "#/$defs/conversations_select_element" },
831
+ { "$ref": "#/$defs/channels_select_element" },
832
+ { "$ref": "#/$defs/multi_static_select_element" },
833
+ { "$ref": "#/$defs/multi_external_select_element" },
834
+ { "$ref": "#/$defs/multi_users_select_element" },
835
+ { "$ref": "#/$defs/multi_conversations_select_element" },
836
+ { "$ref": "#/$defs/multi_channels_select_element" },
837
+ { "$ref": "#/$defs/workflow_button_element" }
838
+ ]
839
+ },
840
+
841
+ "input_block_element": {
842
+ "description": "Elements that may appear as the element of an input block.",
843
+ "oneOf": [
844
+ { "$ref": "#/$defs/plain_text_input_element" },
845
+ { "$ref": "#/$defs/email_input_element" },
846
+ { "$ref": "#/$defs/url_input_element" },
847
+ { "$ref": "#/$defs/number_input_element" },
848
+ { "$ref": "#/$defs/checkboxes_element" },
849
+ { "$ref": "#/$defs/radio_buttons_element" },
850
+ { "$ref": "#/$defs/datepicker_element" },
851
+ { "$ref": "#/$defs/datetimepicker_element" },
852
+ { "$ref": "#/$defs/timepicker_element" },
853
+ { "$ref": "#/$defs/static_select_element" },
854
+ { "$ref": "#/$defs/external_select_element" },
855
+ { "$ref": "#/$defs/users_select_element" },
856
+ { "$ref": "#/$defs/conversations_select_element" },
857
+ { "$ref": "#/$defs/channels_select_element" },
858
+ { "$ref": "#/$defs/multi_static_select_element" },
859
+ { "$ref": "#/$defs/multi_external_select_element" },
860
+ { "$ref": "#/$defs/multi_users_select_element" },
861
+ { "$ref": "#/$defs/multi_conversations_select_element" },
862
+ { "$ref": "#/$defs/multi_channels_select_element" },
863
+ { "$ref": "#/$defs/rich_text_input_element" },
864
+ { "$ref": "#/$defs/file_input_element" }
865
+ ]
866
+ },
867
+
868
+ "context_block_element": {
869
+ "description": "Elements allowed inside a context block.",
870
+ "oneOf": [{ "$ref": "#/$defs/image_element" }, { "$ref": "#/$defs/text_object" }]
871
+ },
872
+
873
+ "context_actions_block_element": {
874
+ "description": "Elements allowed inside a context_actions block.",
875
+ "oneOf": [{ "$ref": "#/$defs/feedback_buttons_element" }, { "$ref": "#/$defs/icon_button_element" }]
876
+ },
877
+
878
+ "rich_text_style_object": {
879
+ "description": "Style flags for rich-text leaf elements. Slack docs disagree on which flags are allowed per leaf type; this is the union of all flags documented.",
880
+ "type": "object",
881
+ "additionalProperties": false,
882
+ "minProperties": 1,
883
+ "properties": {
884
+ "bold": { "type": "boolean" },
885
+ "italic": { "type": "boolean" },
886
+ "strike": { "type": "boolean" },
887
+ "underline": { "type": "boolean" },
888
+ "code": { "type": "boolean" },
889
+ "highlight": { "type": "boolean" },
890
+ "client_highlight": { "type": "boolean" },
891
+ "unlink": { "type": "boolean" }
892
+ }
893
+ },
894
+
895
+ "rich_text_text_leaf": {
896
+ "type": "object",
897
+ "additionalProperties": false,
898
+ "required": ["type", "text"],
899
+ "properties": {
900
+ "type": { "const": "text" },
901
+ "text": { "type": "string" },
902
+ "style": { "$ref": "#/$defs/rich_text_style_object" }
903
+ }
904
+ },
905
+
906
+ "rich_text_link_leaf": {
907
+ "type": "object",
908
+ "additionalProperties": false,
909
+ "required": ["type", "url"],
910
+ "properties": {
911
+ "type": { "const": "link" },
912
+ "url": { "type": "string", "format": "uri" },
913
+ "text": { "type": "string" },
914
+ "unsafe": { "type": "boolean" },
915
+ "style": { "$ref": "#/$defs/rich_text_style_object" }
916
+ }
917
+ },
918
+
919
+ "rich_text_user_leaf": {
920
+ "type": "object",
921
+ "additionalProperties": false,
922
+ "required": ["type", "user_id"],
923
+ "properties": {
924
+ "type": { "const": "user" },
925
+ "user_id": { "type": "string", "pattern": "^[UW][A-Z0-9]+$" },
926
+ "style": { "$ref": "#/$defs/rich_text_style_object" }
927
+ }
928
+ },
929
+
930
+ "rich_text_usergroup_leaf": {
931
+ "type": "object",
932
+ "additionalProperties": false,
933
+ "required": ["type", "usergroup_id"],
934
+ "properties": {
935
+ "type": { "const": "usergroup" },
936
+ "usergroup_id": { "type": "string", "pattern": "^S[A-Z0-9]+$" },
937
+ "style": { "$ref": "#/$defs/rich_text_style_object" }
938
+ }
939
+ },
940
+
941
+ "rich_text_channel_leaf": {
942
+ "type": "object",
943
+ "additionalProperties": false,
944
+ "required": ["type", "channel_id"],
945
+ "properties": {
946
+ "type": { "const": "channel" },
947
+ "channel_id": { "type": "string", "pattern": "^[CG][A-Z0-9]+$" },
948
+ "style": { "$ref": "#/$defs/rich_text_style_object" }
949
+ }
950
+ },
951
+
952
+ "rich_text_emoji_leaf": {
953
+ "description": "Slack's official docs (rich-text-block reference) only list type/name/unicode, but the API silently accepts a `style` object on emoji leaves. We allow it to match observed behavior.",
954
+ "type": "object",
955
+ "additionalProperties": false,
956
+ "required": ["type", "name"],
957
+ "properties": {
958
+ "type": { "const": "emoji" },
959
+ "name": { "type": "string", "minLength": 1 },
960
+ "skin_tone": { "type": "integer", "minimum": 1, "maximum": 6 },
961
+ "unicode": { "type": "string", "minLength": 1 },
962
+ "style": { "$ref": "#/$defs/rich_text_style_object" }
963
+ }
964
+ },
965
+
966
+ "rich_text_team_leaf": {
967
+ "description": "Whole-team mention (e.g. <!T12345>) — referenced by team_id.",
968
+ "type": "object",
969
+ "additionalProperties": false,
970
+ "required": ["type", "team_id"],
971
+ "properties": {
972
+ "type": { "const": "team" },
973
+ "team_id": { "type": "string", "pattern": "^T[A-Z0-9]+$" },
974
+ "style": { "$ref": "#/$defs/rich_text_style_object" }
975
+ }
976
+ },
977
+
978
+ "rich_text_broadcast_leaf": {
979
+ "type": "object",
980
+ "additionalProperties": false,
981
+ "required": ["type", "range"],
982
+ "properties": {
983
+ "type": { "const": "broadcast" },
984
+ "range": { "enum": ["here", "channel", "everyone"] },
985
+ "style": { "$ref": "#/$defs/rich_text_style_object" }
986
+ }
987
+ },
988
+
989
+ "rich_text_color_leaf": {
990
+ "type": "object",
991
+ "additionalProperties": false,
992
+ "required": ["type", "value"],
993
+ "properties": {
994
+ "type": { "const": "color" },
995
+ "value": { "type": "string", "pattern": "^#?[0-9a-fA-F]{6}$" },
996
+ "style": { "$ref": "#/$defs/rich_text_style_object" }
997
+ }
998
+ },
999
+
1000
+ "rich_text_date_leaf": {
1001
+ "type": "object",
1002
+ "additionalProperties": false,
1003
+ "required": ["type", "timestamp", "format"],
1004
+ "properties": {
1005
+ "type": { "const": "date" },
1006
+ "timestamp": { "type": "integer", "minimum": 0 },
1007
+ "format": { "type": "string", "minLength": 1 },
1008
+ "url": { "type": "string", "format": "uri" },
1009
+ "fallback": { "type": "string" },
1010
+ "style": { "$ref": "#/$defs/rich_text_style_object" }
1011
+ }
1012
+ },
1013
+
1014
+ "rich_text_leaf": {
1015
+ "description": "Any of the 10 rich-text leaf element kinds.",
1016
+ "oneOf": [
1017
+ { "$ref": "#/$defs/rich_text_text_leaf" },
1018
+ { "$ref": "#/$defs/rich_text_link_leaf" },
1019
+ { "$ref": "#/$defs/rich_text_user_leaf" },
1020
+ { "$ref": "#/$defs/rich_text_usergroup_leaf" },
1021
+ { "$ref": "#/$defs/rich_text_team_leaf" },
1022
+ { "$ref": "#/$defs/rich_text_channel_leaf" },
1023
+ { "$ref": "#/$defs/rich_text_emoji_leaf" },
1024
+ { "$ref": "#/$defs/rich_text_broadcast_leaf" },
1025
+ { "$ref": "#/$defs/rich_text_color_leaf" },
1026
+ { "$ref": "#/$defs/rich_text_date_leaf" }
1027
+ ]
1028
+ },
1029
+
1030
+ "rich_text_section_element": {
1031
+ "type": "object",
1032
+ "additionalProperties": false,
1033
+ "required": ["type", "elements"],
1034
+ "properties": {
1035
+ "type": { "const": "rich_text_section" },
1036
+ "elements": {
1037
+ "description": "Empty array is accepted by Slack (verified in Block Kit Builder 2026-04-16).",
1038
+ "type": "array",
1039
+ "items": { "$ref": "#/$defs/rich_text_leaf" }
1040
+ }
1041
+ }
1042
+ },
1043
+
1044
+ "rich_text_list_element": {
1045
+ "type": "object",
1046
+ "additionalProperties": false,
1047
+ "required": ["type", "style", "elements"],
1048
+ "properties": {
1049
+ "type": { "const": "rich_text_list" },
1050
+ "style": { "enum": ["bullet", "ordered"] },
1051
+ "elements": {
1052
+ "type": "array",
1053
+ "minItems": 1,
1054
+ "items": { "$ref": "#/$defs/rich_text_section_element" }
1055
+ },
1056
+ "indent": { "type": "integer", "minimum": 0 },
1057
+ "offset": { "type": "integer", "minimum": 0 },
1058
+ "border": { "type": "integer", "enum": [0, 1] }
1059
+ }
1060
+ },
1061
+
1062
+ "rich_text_preformatted_element": {
1063
+ "type": "object",
1064
+ "additionalProperties": false,
1065
+ "required": ["type", "elements"],
1066
+ "properties": {
1067
+ "type": { "const": "rich_text_preformatted" },
1068
+ "elements": {
1069
+ "description": "Empty array is accepted by Slack (verified in Block Kit Builder 2026-04-16).",
1070
+ "type": "array",
1071
+ "items": { "$ref": "#/$defs/rich_text_leaf" }
1072
+ },
1073
+ "border": { "type": "integer", "enum": [0, 1] },
1074
+ "language": { "type": "string", "minLength": 1 }
1075
+ }
1076
+ },
1077
+
1078
+ "rich_text_quote_element": {
1079
+ "type": "object",
1080
+ "additionalProperties": false,
1081
+ "required": ["type", "elements"],
1082
+ "properties": {
1083
+ "type": { "const": "rich_text_quote" },
1084
+ "elements": {
1085
+ "description": "Empty array is accepted by Slack (verified in Block Kit Builder 2026-04-16).",
1086
+ "type": "array",
1087
+ "items": { "$ref": "#/$defs/rich_text_leaf" }
1088
+ },
1089
+ "border": { "type": "integer", "enum": [0, 1] }
1090
+ }
1091
+ },
1092
+
1093
+ "rich_text_container_element": {
1094
+ "description": "Any of the 4 rich-text container kinds usable inside a rich_text block's elements array.",
1095
+ "oneOf": [
1096
+ { "$ref": "#/$defs/rich_text_section_element" },
1097
+ { "$ref": "#/$defs/rich_text_list_element" },
1098
+ { "$ref": "#/$defs/rich_text_preformatted_element" },
1099
+ { "$ref": "#/$defs/rich_text_quote_element" }
1100
+ ]
1101
+ },
1102
+
1103
+ "actions_block": {
1104
+ "type": "object",
1105
+ "additionalProperties": false,
1106
+ "required": ["type", "elements"],
1107
+ "properties": {
1108
+ "type": { "const": "actions" },
1109
+ "elements": {
1110
+ "type": "array",
1111
+ "minItems": 1,
1112
+ "maxItems": 25,
1113
+ "items": { "$ref": "#/$defs/actions_block_element" }
1114
+ },
1115
+ "block_id": { "$ref": "#/$defs/block_id" }
1116
+ }
1117
+ },
1118
+
1119
+ "alert_block": {
1120
+ "type": "object",
1121
+ "additionalProperties": false,
1122
+ "required": ["type", "text"],
1123
+ "properties": {
1124
+ "type": { "const": "alert" },
1125
+ "text": { "$ref": "#/$defs/text_object" },
1126
+ "level": { "enum": ["default", "info", "warning", "error", "success"] },
1127
+ "block_id": { "$ref": "#/$defs/block_id" }
1128
+ }
1129
+ },
1130
+
1131
+ "card_block": {
1132
+ "description": "At least one of hero_image, title, actions, or body is required.",
1133
+ "type": "object",
1134
+ "additionalProperties": false,
1135
+ "required": ["type"],
1136
+ "anyOf": [
1137
+ { "required": ["hero_image"] },
1138
+ { "required": ["title"] },
1139
+ { "required": ["actions"] },
1140
+ { "required": ["body"] }
1141
+ ],
1142
+ "properties": {
1143
+ "type": { "const": "card" },
1144
+ "block_id": { "$ref": "#/$defs/block_id" },
1145
+ "hero_image": { "$ref": "#/$defs/image_element" },
1146
+ "icon": { "$ref": "#/$defs/image_element" },
1147
+ "title": {
1148
+ "allOf": [{ "$ref": "#/$defs/text_object" }, { "properties": { "text": { "maxLength": 150 } } }]
1149
+ },
1150
+ "subtitle": {
1151
+ "allOf": [{ "$ref": "#/$defs/text_object" }, { "properties": { "text": { "maxLength": 150 } } }]
1152
+ },
1153
+ "body": {
1154
+ "allOf": [{ "$ref": "#/$defs/text_object" }, { "properties": { "text": { "maxLength": 200 } } }]
1155
+ },
1156
+ "actions": {
1157
+ "type": "array",
1158
+ "minItems": 1,
1159
+ "maxItems": 2,
1160
+ "items": { "$ref": "#/$defs/button_element" }
1161
+ }
1162
+ }
1163
+ },
1164
+
1165
+ "carousel_block": {
1166
+ "type": "object",
1167
+ "additionalProperties": false,
1168
+ "required": ["type", "elements"],
1169
+ "properties": {
1170
+ "type": { "const": "carousel" },
1171
+ "elements": {
1172
+ "type": "array",
1173
+ "minItems": 1,
1174
+ "maxItems": 10,
1175
+ "items": { "$ref": "#/$defs/card_block" }
1176
+ },
1177
+ "block_id": { "$ref": "#/$defs/block_id" }
1178
+ }
1179
+ },
1180
+
1181
+ "context_actions_block": {
1182
+ "type": "object",
1183
+ "additionalProperties": false,
1184
+ "required": ["type", "elements"],
1185
+ "properties": {
1186
+ "type": { "const": "context_actions" },
1187
+ "elements": {
1188
+ "type": "array",
1189
+ "minItems": 1,
1190
+ "maxItems": 5,
1191
+ "items": { "$ref": "#/$defs/context_actions_block_element" }
1192
+ },
1193
+ "block_id": { "$ref": "#/$defs/block_id" }
1194
+ }
1195
+ },
1196
+
1197
+ "context_block": {
1198
+ "type": "object",
1199
+ "additionalProperties": false,
1200
+ "required": ["type", "elements"],
1201
+ "properties": {
1202
+ "type": { "const": "context" },
1203
+ "elements": {
1204
+ "type": "array",
1205
+ "minItems": 1,
1206
+ "maxItems": 10,
1207
+ "items": { "$ref": "#/$defs/context_block_element" }
1208
+ },
1209
+ "block_id": { "$ref": "#/$defs/block_id" }
1210
+ }
1211
+ },
1212
+
1213
+ "divider_block": {
1214
+ "type": "object",
1215
+ "additionalProperties": false,
1216
+ "required": ["type"],
1217
+ "properties": {
1218
+ "type": { "const": "divider" },
1219
+ "block_id": { "$ref": "#/$defs/block_id" }
1220
+ }
1221
+ },
1222
+
1223
+ "file_block": {
1224
+ "description": "Cannot be added to app surfaces directly; surfaces only when retrieving messages that contain remote files.",
1225
+ "type": "object",
1226
+ "additionalProperties": false,
1227
+ "required": ["type", "external_id", "source"],
1228
+ "properties": {
1229
+ "type": { "const": "file" },
1230
+ "external_id": { "type": "string", "minLength": 1 },
1231
+ "source": { "const": "remote" },
1232
+ "block_id": { "$ref": "#/$defs/block_id" }
1233
+ }
1234
+ },
1235
+
1236
+ "header_block": {
1237
+ "type": "object",
1238
+ "additionalProperties": false,
1239
+ "required": ["type", "text"],
1240
+ "properties": {
1241
+ "type": { "const": "header" },
1242
+ "text": {
1243
+ "allOf": [{ "$ref": "#/$defs/plain_text_object" }, { "properties": { "text": { "maxLength": 150 } } }]
1244
+ },
1245
+ "block_id": { "$ref": "#/$defs/block_id" }
1246
+ }
1247
+ },
1248
+
1249
+ "image_block": {
1250
+ "description": "Either image_url or slack_file is required (not both).",
1251
+ "type": "object",
1252
+ "additionalProperties": false,
1253
+ "required": ["type", "alt_text"],
1254
+ "oneOf": [
1255
+ { "required": ["image_url"], "not": { "required": ["slack_file"] } },
1256
+ { "required": ["slack_file"], "not": { "required": ["image_url"] } }
1257
+ ],
1258
+ "properties": {
1259
+ "type": { "const": "image" },
1260
+ "alt_text": { "type": "string", "minLength": 1, "maxLength": 2000 },
1261
+ "image_url": { "type": "string", "format": "uri", "maxLength": 3000 },
1262
+ "slack_file": { "$ref": "#/$defs/slack_file_object" },
1263
+ "title": {
1264
+ "allOf": [{ "$ref": "#/$defs/plain_text_object" }, { "properties": { "text": { "maxLength": 2000 } } }]
1265
+ },
1266
+ "block_id": { "$ref": "#/$defs/block_id" }
1267
+ }
1268
+ },
1269
+
1270
+ "input_block": {
1271
+ "description": "If element is a file_input, dispatch_action must not be true.",
1272
+ "type": "object",
1273
+ "additionalProperties": false,
1274
+ "required": ["type", "label", "element"],
1275
+ "properties": {
1276
+ "type": { "const": "input" },
1277
+ "label": {
1278
+ "allOf": [{ "$ref": "#/$defs/plain_text_object" }, { "properties": { "text": { "maxLength": 2000 } } }]
1279
+ },
1280
+ "element": { "$ref": "#/$defs/input_block_element" },
1281
+ "dispatch_action": { "type": "boolean" },
1282
+ "block_id": { "$ref": "#/$defs/block_id" },
1283
+ "hint": {
1284
+ "allOf": [{ "$ref": "#/$defs/plain_text_object" }, { "properties": { "text": { "maxLength": 2000 } } }]
1285
+ },
1286
+ "optional": { "type": "boolean" }
1287
+ },
1288
+ "allOf": [
1289
+ {
1290
+ "if": {
1291
+ "properties": {
1292
+ "element": {
1293
+ "properties": { "type": { "const": "file_input" } },
1294
+ "required": ["type"]
1295
+ }
1296
+ },
1297
+ "required": ["element"]
1298
+ },
1299
+ "then": {
1300
+ "properties": { "dispatch_action": { "const": false } }
1301
+ }
1302
+ }
1303
+ ]
1304
+ },
1305
+
1306
+ "markdown_block": {
1307
+ "description": "block_id is ignored on markdown blocks. Cumulative 12,000-char limit across all markdown blocks in one payload is a payload-level rule, not enforced here.",
1308
+ "type": "object",
1309
+ "additionalProperties": false,
1310
+ "required": ["type", "text"],
1311
+ "properties": {
1312
+ "type": { "const": "markdown" },
1313
+ "text": { "type": "string", "minLength": 1, "maxLength": 12000 },
1314
+ "block_id": { "$ref": "#/$defs/block_id" }
1315
+ }
1316
+ },
1317
+
1318
+ "task_card_inline_object": {
1319
+ "description": "A task card as it appears inline within a plan_block tasks array — the docs' example omits the type discriminator.",
1320
+ "type": "object",
1321
+ "additionalProperties": false,
1322
+ "required": ["task_id", "title"],
1323
+ "properties": {
1324
+ "type": { "const": "task_card" },
1325
+ "task_id": { "type": "string", "minLength": 1 },
1326
+ "title": { "type": "string", "minLength": 1 },
1327
+ "details": { "$ref": "#/$defs/rich_text_block" },
1328
+ "output": { "$ref": "#/$defs/rich_text_block" },
1329
+ "sources": {
1330
+ "type": "array",
1331
+ "items": { "$ref": "#/$defs/url_source_element" }
1332
+ },
1333
+ "status": { "enum": ["pending", "in_progress", "complete", "error"] },
1334
+ "block_id": { "$ref": "#/$defs/block_id" }
1335
+ }
1336
+ },
1337
+
1338
+ "plan_block": {
1339
+ "type": "object",
1340
+ "additionalProperties": false,
1341
+ "required": ["type", "title"],
1342
+ "properties": {
1343
+ "type": { "const": "plan" },
1344
+ "title": {
1345
+ "oneOf": [{ "type": "string", "minLength": 1 }, { "$ref": "#/$defs/plain_text_object" }]
1346
+ },
1347
+ "block_id": { "$ref": "#/$defs/block_id" },
1348
+ "tasks": {
1349
+ "type": "array",
1350
+ "items": { "$ref": "#/$defs/task_card_inline_object" }
1351
+ }
1352
+ }
1353
+ },
1354
+
1355
+ "rich_text_block": {
1356
+ "type": "object",
1357
+ "additionalProperties": false,
1358
+ "required": ["type", "elements"],
1359
+ "properties": {
1360
+ "type": { "const": "rich_text" },
1361
+ "elements": {
1362
+ "description": "Empty array is accepted by Slack (verified in Block Kit Builder 2026-04-16).",
1363
+ "type": "array",
1364
+ "items": { "$ref": "#/$defs/rich_text_container_element" }
1365
+ },
1366
+ "block_id": { "$ref": "#/$defs/block_id" }
1367
+ }
1368
+ },
1369
+
1370
+ "section_block": {
1371
+ "description": "Must have text or fields (or both).",
1372
+ "type": "object",
1373
+ "additionalProperties": false,
1374
+ "required": ["type"],
1375
+ "anyOf": [{ "required": ["text"] }, { "required": ["fields"] }],
1376
+ "properties": {
1377
+ "type": { "const": "section" },
1378
+ "text": { "$ref": "#/$defs/text_object" },
1379
+ "block_id": { "$ref": "#/$defs/block_id" },
1380
+ "fields": {
1381
+ "type": "array",
1382
+ "minItems": 1,
1383
+ "maxItems": 10,
1384
+ "items": {
1385
+ "allOf": [{ "$ref": "#/$defs/text_object" }, { "properties": { "text": { "maxLength": 2000 } } }]
1386
+ }
1387
+ },
1388
+ "accessory": { "$ref": "#/$defs/section_accessory_element" },
1389
+ "expand": { "type": "boolean" }
1390
+ }
1391
+ },
1392
+
1393
+ "table_cell": {
1394
+ "description": "A cell inside a table_block row. Either raw_text or rich_text.",
1395
+ "oneOf": [
1396
+ {
1397
+ "type": "object",
1398
+ "additionalProperties": false,
1399
+ "required": ["type", "text"],
1400
+ "properties": {
1401
+ "type": { "const": "raw_text" },
1402
+ "text": { "type": "string" }
1403
+ }
1404
+ },
1405
+ {
1406
+ "type": "object",
1407
+ "additionalProperties": false,
1408
+ "required": ["type", "elements"],
1409
+ "properties": {
1410
+ "type": { "const": "rich_text" },
1411
+ "elements": {
1412
+ "description": "Empty array is accepted by Slack (verified in Block Kit Builder 2026-04-16).",
1413
+ "type": "array",
1414
+ "items": { "$ref": "#/$defs/rich_text_container_element" }
1415
+ }
1416
+ }
1417
+ }
1418
+ ]
1419
+ },
1420
+
1421
+ "table_column_setting": {
1422
+ "description": "Per-column settings inside table_block.column_settings. May be null to skip.",
1423
+ "oneOf": [
1424
+ { "type": "null" },
1425
+ {
1426
+ "type": "object",
1427
+ "additionalProperties": false,
1428
+ "properties": {
1429
+ "align": { "enum": ["left", "center", "right"] },
1430
+ "is_wrapped": { "type": "boolean" }
1431
+ }
1432
+ }
1433
+ ]
1434
+ },
1435
+
1436
+ "table_block": {
1437
+ "description": "One table per message (server-enforced via invalid_attachments / only_one_table_allowed). Up to 100 rows, up to 20 cells per row.",
1438
+ "type": "object",
1439
+ "additionalProperties": false,
1440
+ "required": ["type", "rows"],
1441
+ "properties": {
1442
+ "type": { "const": "table" },
1443
+ "block_id": { "$ref": "#/$defs/block_id" },
1444
+ "rows": {
1445
+ "type": "array",
1446
+ "minItems": 1,
1447
+ "maxItems": 100,
1448
+ "items": {
1449
+ "type": "array",
1450
+ "minItems": 1,
1451
+ "maxItems": 20,
1452
+ "items": { "$ref": "#/$defs/table_cell" }
1453
+ }
1454
+ },
1455
+ "column_settings": {
1456
+ "type": "array",
1457
+ "maxItems": 20,
1458
+ "items": { "$ref": "#/$defs/table_column_setting" }
1459
+ }
1460
+ }
1461
+ },
1462
+
1463
+ "task_card_block": {
1464
+ "description": "Standalone task_card block (also embeddable inline within plan_block).",
1465
+ "type": "object",
1466
+ "additionalProperties": false,
1467
+ "required": ["type", "task_id", "title"],
1468
+ "properties": {
1469
+ "type": { "const": "task_card" },
1470
+ "task_id": { "type": "string", "minLength": 1 },
1471
+ "title": { "type": "string", "minLength": 1 },
1472
+ "details": { "$ref": "#/$defs/rich_text_block" },
1473
+ "output": { "$ref": "#/$defs/rich_text_block" },
1474
+ "sources": {
1475
+ "type": "array",
1476
+ "items": { "$ref": "#/$defs/url_source_element" }
1477
+ },
1478
+ "status": { "enum": ["pending", "in_progress", "complete", "error"] },
1479
+ "block_id": { "$ref": "#/$defs/block_id" }
1480
+ }
1481
+ },
1482
+
1483
+ "video_block": {
1484
+ "description": "Requires links.embed:write OAuth scope. video_url must be in app's unfurl domains, HTTPS, embeddable, return 2xx, not point to Slack-related domains.",
1485
+ "type": "object",
1486
+ "additionalProperties": false,
1487
+ "required": ["type", "alt_text", "title", "thumbnail_url", "video_url"],
1488
+ "properties": {
1489
+ "type": { "const": "video" },
1490
+ "alt_text": { "type": "string", "minLength": 1 },
1491
+ "title": {
1492
+ "allOf": [{ "$ref": "#/$defs/plain_text_object" }, { "properties": { "text": { "maxLength": 199 } } }]
1493
+ },
1494
+ "thumbnail_url": { "type": "string", "format": "uri" },
1495
+ "video_url": {
1496
+ "type": "string",
1497
+ "format": "uri",
1498
+ "pattern": "^https://"
1499
+ },
1500
+ "author_name": { "type": "string", "maxLength": 49 },
1501
+ "description": {
1502
+ "allOf": [{ "$ref": "#/$defs/plain_text_object" }, { "properties": { "text": { "maxLength": 199 } } }]
1503
+ },
1504
+ "provider_icon_url": { "type": "string", "format": "uri" },
1505
+ "provider_name": { "type": "string", "minLength": 1 },
1506
+ "title_url": {
1507
+ "type": "string",
1508
+ "format": "uri",
1509
+ "pattern": "^https://"
1510
+ },
1511
+ "block_id": { "$ref": "#/$defs/block_id" }
1512
+ }
1513
+ },
1514
+
1515
+ "block": {
1516
+ "description": "Discriminated union of every Block Kit block type.",
1517
+ "oneOf": [
1518
+ { "$ref": "#/$defs/actions_block" },
1519
+ { "$ref": "#/$defs/alert_block" },
1520
+ { "$ref": "#/$defs/card_block" },
1521
+ { "$ref": "#/$defs/carousel_block" },
1522
+ { "$ref": "#/$defs/context_actions_block" },
1523
+ { "$ref": "#/$defs/context_block" },
1524
+ { "$ref": "#/$defs/divider_block" },
1525
+ { "$ref": "#/$defs/file_block" },
1526
+ { "$ref": "#/$defs/header_block" },
1527
+ { "$ref": "#/$defs/image_block" },
1528
+ { "$ref": "#/$defs/input_block" },
1529
+ { "$ref": "#/$defs/markdown_block" },
1530
+ { "$ref": "#/$defs/plan_block" },
1531
+ { "$ref": "#/$defs/rich_text_block" },
1532
+ { "$ref": "#/$defs/section_block" },
1533
+ { "$ref": "#/$defs/table_block" },
1534
+ { "$ref": "#/$defs/task_card_block" },
1535
+ { "$ref": "#/$defs/video_block" }
1536
+ ]
1537
+ },
1538
+
1539
+ "modal_view": {
1540
+ "description": "Modal view surface (views.open / views.push / views.update payload). title/submit/close text capped at 24 chars. When blocks contain any input block, submit is required (per docs).",
1541
+ "type": "object",
1542
+ "additionalProperties": false,
1543
+ "required": ["type", "title", "blocks"],
1544
+ "properties": {
1545
+ "type": { "const": "modal" },
1546
+ "title": {
1547
+ "allOf": [{ "$ref": "#/$defs/plain_text_object" }, { "properties": { "text": { "maxLength": 24 } } }]
1548
+ },
1549
+ "blocks": {
1550
+ "type": "array",
1551
+ "minItems": 1,
1552
+ "maxItems": 100,
1553
+ "items": { "$ref": "#/$defs/block" }
1554
+ },
1555
+ "close": {
1556
+ "allOf": [{ "$ref": "#/$defs/plain_text_object" }, { "properties": { "text": { "maxLength": 24 } } }]
1557
+ },
1558
+ "submit": {
1559
+ "allOf": [{ "$ref": "#/$defs/plain_text_object" }, { "properties": { "text": { "maxLength": 24 } } }]
1560
+ },
1561
+ "private_metadata": { "type": "string", "maxLength": 3000 },
1562
+ "callback_id": { "type": "string", "maxLength": 255 },
1563
+ "clear_on_close": { "type": "boolean" },
1564
+ "notify_on_close": { "type": "boolean" },
1565
+ "external_id": { "type": "string", "maxLength": 255 },
1566
+ "submit_disabled": { "type": "boolean" }
1567
+ },
1568
+ "allOf": [
1569
+ {
1570
+ "if": {
1571
+ "properties": {
1572
+ "blocks": {
1573
+ "contains": {
1574
+ "type": "object",
1575
+ "properties": { "type": { "const": "input" } },
1576
+ "required": ["type"]
1577
+ }
1578
+ }
1579
+ }
1580
+ },
1581
+ "then": { "required": ["submit"] }
1582
+ }
1583
+ ]
1584
+ },
1585
+
1586
+ "home_view": {
1587
+ "description": "Home tab view surface (views.publish payload).",
1588
+ "type": "object",
1589
+ "additionalProperties": false,
1590
+ "required": ["type", "blocks"],
1591
+ "properties": {
1592
+ "type": { "const": "home" },
1593
+ "blocks": {
1594
+ "type": "array",
1595
+ "minItems": 1,
1596
+ "maxItems": 100,
1597
+ "items": { "$ref": "#/$defs/block" }
1598
+ },
1599
+ "private_metadata": { "type": "string", "maxLength": 3000 },
1600
+ "callback_id": { "type": "string", "maxLength": 255 },
1601
+ "external_id": { "type": "string", "maxLength": 255 }
1602
+ }
1603
+ }
1604
+ }
1605
+ }