From ab6ff3c0456f1c85230ba4b4d7f6a76c2109fe86 Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Tue, 14 Jul 2026 13:59:03 -0700 Subject: [PATCH 1/8] feat(web-api): add blocks.validate method Add a typed blocks.validate method so callers can validate Block Kit payloads via client.blocks.validate({ blocks }) instead of the untyped client.apiCall('blocks.validate', ...) escape hatch. blocks, message, and view arguments are all optional JSON-encoded strings; no scopes required. The response type is a minimal placeholder covering the fields common to all Web API responses; the errors[] array on a failed validation is left to be generated from a real sample (no blocks.validate.json exists in the upstream java-slack-sdk logs yet). Co-Authored-By: Claude --- .changeset/web-api-blocks-validate.md | 5 +++++ packages/web-api/src/methods.ts | 10 ++++++++++ packages/web-api/src/types/request/blocks.ts | 14 +++++++++++++ packages/web-api/src/types/request/index.ts | 1 + .../types/response/BlocksValidateResponse.ts | 20 +++++++++++++++++++ packages/web-api/src/types/response/index.ts | 1 + .../test/types/methods/blocks.test-d.ts | 14 +++++++++++++ 7 files changed, 65 insertions(+) create mode 100644 .changeset/web-api-blocks-validate.md create mode 100644 packages/web-api/src/types/request/blocks.ts create mode 100644 packages/web-api/src/types/response/BlocksValidateResponse.ts create mode 100644 packages/web-api/test/types/methods/blocks.test-d.ts diff --git a/.changeset/web-api-blocks-validate.md b/.changeset/web-api-blocks-validate.md new file mode 100644 index 000000000..13f4087d6 --- /dev/null +++ b/.changeset/web-api-blocks-validate.md @@ -0,0 +1,5 @@ +--- +"@slack/web-api": minor +--- + +Added the `blocks.validate` method. Call it as `client.blocks.validate({ blocks })` to validate a Block Kit payload (`blocks`, `message`, or `view`, each a JSON-encoded string) against the Block Kit schema, instead of the untyped `client.apiCall('blocks.validate', …)` escape hatch. diff --git a/packages/web-api/src/methods.ts b/packages/web-api/src/methods.ts index 462060320..47054db48 100644 --- a/packages/web-api/src/methods.ts +++ b/packages/web-api/src/methods.ts @@ -113,6 +113,7 @@ import type { AuthRevokeArguments, AuthTeamsListArguments, AuthTestArguments, + BlocksValidateArguments, BookmarksAddArguments, BookmarksEditArguments, BookmarksListArguments, @@ -382,6 +383,7 @@ import type { AuthRevokeResponse, AuthTeamsListResponse, AuthTestResponse, + BlocksValidateResponse, BookmarksAddResponse, BookmarksEditResponse, BookmarksListResponse, @@ -1514,6 +1516,14 @@ export abstract class Methods extends EventEmitter { remove: bindApiCall(this, 'bookmarks.remove'), }; + public readonly blocks = { + /** + * @description Validates an array of blocks, or a message or view payload. + * @see {@link https://docs.slack.dev/reference/methods/blocks.validate `blocks.validate` API reference}. + */ + validate: bindApiCallWithOptionalArgument(this, 'blocks.validate'), + }; + public readonly bots = { /** * @description Gets information about a bot user. diff --git a/packages/web-api/src/types/request/blocks.ts b/packages/web-api/src/types/request/blocks.ts new file mode 100644 index 000000000..c442e448b --- /dev/null +++ b/packages/web-api/src/types/request/blocks.ts @@ -0,0 +1,14 @@ +import type { OptionalArgument } from '../helpers'; +import type { TokenOverridable } from './common'; + +// https://docs.slack.dev/reference/methods/blocks.validate +export type BlocksValidateArguments = OptionalArgument< + TokenOverridable & { + /** @description A JSON-encoded string of an array of blocks to validate. */ + blocks?: string; + /** @description A JSON-encoded string of a message payload to validate. */ + message?: string; + /** @description A JSON-encoded string of a view payload to validate. */ + view?: string; + } +>; diff --git a/packages/web-api/src/types/request/index.ts b/packages/web-api/src/types/request/index.ts index 112bfa46e..09ec218a2 100644 --- a/packages/web-api/src/types/request/index.ts +++ b/packages/web-api/src/types/request/index.ts @@ -139,6 +139,7 @@ export type { AuthTeamsListArguments, AuthTestArguments, } from './auth'; +export type { BlocksValidateArguments } from './blocks'; export type { BookmarksAddArguments, BookmarksEditArguments, diff --git a/packages/web-api/src/types/response/BlocksValidateResponse.ts b/packages/web-api/src/types/response/BlocksValidateResponse.ts new file mode 100644 index 000000000..d3701d366 --- /dev/null +++ b/packages/web-api/src/types/response/BlocksValidateResponse.ts @@ -0,0 +1,20 @@ +// NOTE: This response type is a minimal placeholder, written by hand rather than +// generated by scripts/generate-web-api-types.sh, because no `blocks.validate.json` +// sample exists yet in the upstream slackapi/java-slack-sdk logs. It covers the +// fields common to every Web API response; the `errors[]` array returned on a failed +// validation is intentionally omitted until a real sample can be captured and the +// type regenerated. See HANDOFF / PR notes. + +import type { WebAPICallResult } from '../../WebClient'; + +export type BlocksValidateResponse = WebAPICallResult & { + ok?: boolean; + error?: string; + needed?: string; + provided?: string; + response_metadata?: ResponseMetadata; +}; + +export interface ResponseMetadata { + messages?: string[]; +} diff --git a/packages/web-api/src/types/response/index.ts b/packages/web-api/src/types/response/index.ts index e1c324253..fa71f6401 100644 --- a/packages/web-api/src/types/response/index.ts +++ b/packages/web-api/src/types/response/index.ts @@ -123,6 +123,7 @@ export { AssistantThreadsSetTitleResponse } from './AssistantThreadsSetTitleResp export { AuthRevokeResponse } from './AuthRevokeResponse'; export { AuthTeamsListResponse } from './AuthTeamsListResponse'; export { AuthTestResponse } from './AuthTestResponse'; +export { BlocksValidateResponse } from './BlocksValidateResponse'; export { BookmarksAddResponse } from './BookmarksAddResponse'; export { BookmarksEditResponse } from './BookmarksEditResponse'; export { BookmarksListResponse } from './BookmarksListResponse'; diff --git a/packages/web-api/test/types/methods/blocks.test-d.ts b/packages/web-api/test/types/methods/blocks.test-d.ts new file mode 100644 index 000000000..0384ebec0 --- /dev/null +++ b/packages/web-api/test/types/methods/blocks.test-d.ts @@ -0,0 +1,14 @@ +import { expectAssignable } from 'tsd'; +import { WebClient } from '../../../src/WebClient'; + +const web = new WebClient('TOKEN'); + +// blocks.validate +// -- happy path +expectAssignable>([{}]); // all optional args +expectAssignable>([]); // no arg is fine +expectAssignable>([ + { blocks: '[{"type":"section","text":{"type":"plain_text","text":"Hello world"}}]' }, +]); +expectAssignable>([{ message: '{"blocks":[]}' }]); +expectAssignable>([{ view: '{"type":"modal"}' }]); From f3100f94194baa11054cbc6bf0c5cd4a13ee73d6 Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Tue, 25 Aug 2026 17:09:02 -0700 Subject: [PATCH 2/8] feat(web-api): type blocks.validate args and errors[] response - Request args accept typed Block Kit values (blocks: (KnownBlock | Block)[], message: { blocks, attachments }, view: View) instead of JSON strings, matching chat.postMessage / views.open. The message shape omits text, which the endpoint rejects as an additional property. - Response now types the errors[] returned on failed validation: each Error has pointer/code/message/constraint, where constraint.expected/got are a string|number|string[] union (polymorphic across enum vs length/count constraints). Removes the placeholder note that omitted errors[]. Verified: tsc build clean; the blocks.validate tsd type tests pass (the 6 remaining tsd errors are pre-existing in files/rtm test-d, untouched here). Co-Authored-By: Claude --- .changeset/web-api-blocks-validate.md | 2 +- packages/web-api/src/types/request/blocks.ts | 17 +++++++++----- .../types/response/BlocksValidateResponse.ts | 23 +++++++++++++------ .../test/types/methods/blocks.test-d.ts | 14 +++++++---- 4 files changed, 38 insertions(+), 18 deletions(-) diff --git a/.changeset/web-api-blocks-validate.md b/.changeset/web-api-blocks-validate.md index 13f4087d6..33ffec0de 100644 --- a/.changeset/web-api-blocks-validate.md +++ b/.changeset/web-api-blocks-validate.md @@ -2,4 +2,4 @@ "@slack/web-api": minor --- -Added the `blocks.validate` method. Call it as `client.blocks.validate({ blocks })` to validate a Block Kit payload (`blocks`, `message`, or `view`, each a JSON-encoded string) against the Block Kit schema, instead of the untyped `client.apiCall('blocks.validate', …)` escape hatch. +Added the `blocks.validate` method. Call it as `client.blocks.validate({ blocks })` to validate a Block Kit payload against the Block Kit schema — `blocks` (a `(KnownBlock | Block)[]`), `message` (`{ blocks, attachments }`), or `view` (a `View`) — instead of the untyped `client.apiCall('blocks.validate', …)` escape hatch. The response's `errors[]` carry each failure's `pointer`, `code`, `message`, and `constraint`. diff --git a/packages/web-api/src/types/request/blocks.ts b/packages/web-api/src/types/request/blocks.ts index c442e448b..5d1691a25 100644 --- a/packages/web-api/src/types/request/blocks.ts +++ b/packages/web-api/src/types/request/blocks.ts @@ -1,14 +1,19 @@ +import type { Block, KnownBlock, MessageAttachment, View } from '@slack/types'; + import type { OptionalArgument } from '../helpers'; import type { TokenOverridable } from './common'; // https://docs.slack.dev/reference/methods/blocks.validate export type BlocksValidateArguments = OptionalArgument< TokenOverridable & { - /** @description A JSON-encoded string of an array of blocks to validate. */ - blocks?: string; - /** @description A JSON-encoded string of a message payload to validate. */ - message?: string; - /** @description A JSON-encoded string of a view payload to validate. */ - view?: string; + /** @description An array of blocks to validate. */ + blocks?: (KnownBlock | Block)[]; + /** @description A message payload to validate. */ + message?: { + blocks?: (KnownBlock | Block)[]; + attachments?: MessageAttachment[]; + }; + /** @description A view payload to validate. */ + view?: View; } >; diff --git a/packages/web-api/src/types/response/BlocksValidateResponse.ts b/packages/web-api/src/types/response/BlocksValidateResponse.ts index d3701d366..9d065ca24 100644 --- a/packages/web-api/src/types/response/BlocksValidateResponse.ts +++ b/packages/web-api/src/types/response/BlocksValidateResponse.ts @@ -1,10 +1,3 @@ -// NOTE: This response type is a minimal placeholder, written by hand rather than -// generated by scripts/generate-web-api-types.sh, because no `blocks.validate.json` -// sample exists yet in the upstream slackapi/java-slack-sdk logs. It covers the -// fields common to every Web API response; the `errors[]` array returned on a failed -// validation is intentionally omitted until a real sample can be captured and the -// type regenerated. See HANDOFF / PR notes. - import type { WebAPICallResult } from '../../WebClient'; export type BlocksValidateResponse = WebAPICallResult & { @@ -12,9 +5,25 @@ export type BlocksValidateResponse = WebAPICallResult & { error?: string; needed?: string; provided?: string; + errors?: Error[]; response_metadata?: ResponseMetadata; }; +export interface Error { + code?: string; + message?: string; + pointer?: string; + constraint?: Constraint; +} + +export interface Constraint { + type?: string; + // expected/got vary by constraint type: a string array for "enum", + // a number for length/count constraints, or absent (e.g. "all_of"). + expected?: string | number | string[]; + got?: string | number; +} + export interface ResponseMetadata { messages?: string[]; } diff --git a/packages/web-api/test/types/methods/blocks.test-d.ts b/packages/web-api/test/types/methods/blocks.test-d.ts index 0384ebec0..00ea58902 100644 --- a/packages/web-api/test/types/methods/blocks.test-d.ts +++ b/packages/web-api/test/types/methods/blocks.test-d.ts @@ -1,4 +1,4 @@ -import { expectAssignable } from 'tsd'; +import { expectAssignable, expectError } from 'tsd'; import { WebClient } from '../../../src/WebClient'; const web = new WebClient('TOKEN'); @@ -8,7 +8,13 @@ const web = new WebClient('TOKEN'); expectAssignable>([{}]); // all optional args expectAssignable>([]); // no arg is fine expectAssignable>([ - { blocks: '[{"type":"section","text":{"type":"plain_text","text":"Hello world"}}]' }, + { blocks: [{ type: 'section', text: { type: 'plain_text', text: 'Hello world' } }] }, ]); -expectAssignable>([{ message: '{"blocks":[]}' }]); -expectAssignable>([{ view: '{"type":"modal"}' }]); +expectAssignable>([ + { message: { blocks: [{ type: 'section', text: { type: 'mrkdwn', text: 'Hello' } }] } }, +]); +expectAssignable>([ + { view: { type: 'modal', title: { type: 'plain_text', text: 'Title' }, blocks: [] } }, +]); +// -- sad path +expectError>([{ blocks: '[]' }]); // must be typed blocks, not a string From bdb209dcc278209668931cdf14b331241684b8b8 Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Wed, 26 Aug 2026 09:16:24 -0700 Subject: [PATCH 3/8] docs(web-api): trim blocks.validate changeset to the standard one-line form Co-Authored-By: Claude --- .changeset/web-api-blocks-validate.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/web-api-blocks-validate.md b/.changeset/web-api-blocks-validate.md index 33ffec0de..725e03411 100644 --- a/.changeset/web-api-blocks-validate.md +++ b/.changeset/web-api-blocks-validate.md @@ -2,4 +2,4 @@ "@slack/web-api": minor --- -Added the `blocks.validate` method. Call it as `client.blocks.validate({ blocks })` to validate a Block Kit payload against the Block Kit schema — `blocks` (a `(KnownBlock | Block)[]`), `message` (`{ blocks, attachments }`), or `view` (a `View`) — instead of the untyped `client.apiCall('blocks.validate', …)` escape hatch. The response's `errors[]` carry each failure's `pointer`, `code`, `message`, and `constraint`. +feat(web-api): add [`blocks.validate`](https://docs.slack.dev/reference/methods/blocks.validate) From 603433db7d9dfb9905c361821c84999cefd1b2ff Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Wed, 26 Aug 2026 09:17:18 -0700 Subject: [PATCH 4/8] docs(web-api): align blocks.validate description and changeset Co-Authored-By: Claude --- .changeset/web-api-blocks-validate.md | 2 +- packages/web-api/src/methods.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.changeset/web-api-blocks-validate.md b/.changeset/web-api-blocks-validate.md index 725e03411..b33cde63d 100644 --- a/.changeset/web-api-blocks-validate.md +++ b/.changeset/web-api-blocks-validate.md @@ -2,4 +2,4 @@ "@slack/web-api": minor --- -feat(web-api): add [`blocks.validate`](https://docs.slack.dev/reference/methods/blocks.validate) +feat(web-api): add [`blocks.validate`](https://docs.slack.dev/reference/methods/blocks.validate) method diff --git a/packages/web-api/src/methods.ts b/packages/web-api/src/methods.ts index 468e9b4d4..f307dff90 100644 --- a/packages/web-api/src/methods.ts +++ b/packages/web-api/src/methods.ts @@ -1550,7 +1550,7 @@ export abstract class Methods extends EventEmitter { public readonly blocks = { /** - * @description Validates an array of blocks, or a message or view payload. + * @description Validates blocks, messages, and views Block Kit JSON payloads. * @see {@link https://docs.slack.dev/reference/methods/blocks.validate `blocks.validate` API reference}. */ validate: bindApiCallWithOptionalArgument(this, 'blocks.validate'), From 35d2041ae76c35e100f047c908c6d974cb9b6d1e Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Wed, 26 Aug 2026 09:29:06 -0700 Subject: [PATCH 5/8] feat(web-api): type blocks.validate constraint expected/got as unions Generated from a blocks.validate sample covering both constraint shapes: expected is string[] | number and got is number | string (enum vs length/count constraints). Co-Authored-By: Claude --- .../types/response/BlocksValidateResponse.ts | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/packages/web-api/src/types/response/BlocksValidateResponse.ts b/packages/web-api/src/types/response/BlocksValidateResponse.ts index 9d065ca24..72180a0de 100644 --- a/packages/web-api/src/types/response/BlocksValidateResponse.ts +++ b/packages/web-api/src/types/response/BlocksValidateResponse.ts @@ -1,27 +1,35 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// // +// !!! DO NOT EDIT THIS FILE !!! // +// // +// This file is auto-generated by scripts/generate-web-api-types.sh in the repository. // +// Please refer to the script code to learn how to update the source data. // +// // +///////////////////////////////////////////////////////////////////////////////////////// + import type { WebAPICallResult } from '../../WebClient'; export type BlocksValidateResponse = WebAPICallResult & { - ok?: boolean; error?: string; + errors?: Error[]; needed?: string; + ok?: boolean; provided?: string; - errors?: Error[]; response_metadata?: ResponseMetadata; + warning?: string; }; export interface Error { code?: string; + constraint?: Constraint; message?: string; pointer?: string; - constraint?: Constraint; } export interface Constraint { + expected?: string[] | number; + got?: number | string; type?: string; - // expected/got vary by constraint type: a string array for "enum", - // a number for length/count constraints, or absent (e.g. "all_of"). - expected?: string | number | string[]; - got?: string | number; } export interface ResponseMetadata { From 5b8f91892969e735328d7a8aec91e7d11f79fb81 Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Wed, 26 Aug 2026 09:31:50 -0700 Subject: [PATCH 6/8] fix(web-api): drop TokenOverridable from blocks.validate args blocks.validate is unauthenticated (no token or scopes), so its arguments should not offer a token override, matching api.test. Co-Authored-By: Claude --- packages/web-api/src/types/request/blocks.ts | 23 +++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/packages/web-api/src/types/request/blocks.ts b/packages/web-api/src/types/request/blocks.ts index 5d1691a25..eb99078d8 100644 --- a/packages/web-api/src/types/request/blocks.ts +++ b/packages/web-api/src/types/request/blocks.ts @@ -1,19 +1,16 @@ import type { Block, KnownBlock, MessageAttachment, View } from '@slack/types'; import type { OptionalArgument } from '../helpers'; -import type { TokenOverridable } from './common'; // https://docs.slack.dev/reference/methods/blocks.validate -export type BlocksValidateArguments = OptionalArgument< - TokenOverridable & { - /** @description An array of blocks to validate. */ +export type BlocksValidateArguments = OptionalArgument<{ + /** @description An array of blocks to validate. */ + blocks?: (KnownBlock | Block)[]; + /** @description A message payload to validate. */ + message?: { blocks?: (KnownBlock | Block)[]; - /** @description A message payload to validate. */ - message?: { - blocks?: (KnownBlock | Block)[]; - attachments?: MessageAttachment[]; - }; - /** @description A view payload to validate. */ - view?: View; - } ->; + attachments?: MessageAttachment[]; + }; + /** @description A view payload to validate. */ + view?: View; +}>; From e48b61a451673a1be760ad76feb95a6dfa0b7245 Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Wed, 26 Aug 2026 10:35:23 -0700 Subject: [PATCH 7/8] test(web-api): construct tokenless client in blocks.validate type test blocks.validate is unauthenticated, so the type test constructs WebClient() without a token, matching the example. Co-Authored-By: Claude --- packages/web-api/test/types/methods/blocks.test-d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/web-api/test/types/methods/blocks.test-d.ts b/packages/web-api/test/types/methods/blocks.test-d.ts index 00ea58902..3d709e779 100644 --- a/packages/web-api/test/types/methods/blocks.test-d.ts +++ b/packages/web-api/test/types/methods/blocks.test-d.ts @@ -1,7 +1,7 @@ import { expectAssignable, expectError } from 'tsd'; import { WebClient } from '../../../src/WebClient'; -const web = new WebClient('TOKEN'); +const web = new WebClient(); // blocks.validate // -- happy path From a131e99b403183ef0e19f7a4ecf2cd01edd9e65b Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Wed, 26 Aug 2026 10:45:11 -0700 Subject: [PATCH 8/8] fix(web-api): regenerate blocks.validate response type from the fixture Regenerate BlocksValidateResponse from the recorded blocks.validate sample via the standard type generator. constraint.expected/got are string[]/string (the shape captured in the fixture) rather than the previously hand-edited union, so the file matches what scripts/generate-web-api-types.sh produces. Co-Authored-By: Claude --- packages/web-api/src/types/response/BlocksValidateResponse.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/web-api/src/types/response/BlocksValidateResponse.ts b/packages/web-api/src/types/response/BlocksValidateResponse.ts index 72180a0de..98ac25f84 100644 --- a/packages/web-api/src/types/response/BlocksValidateResponse.ts +++ b/packages/web-api/src/types/response/BlocksValidateResponse.ts @@ -27,8 +27,8 @@ export interface Error { } export interface Constraint { - expected?: string[] | number; - got?: number | string; + expected?: string[]; + got?: string; type?: string; }