From a7c05c7a8c111d4e56610eb09edbc23360940b6f Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Tue, 14 Jul 2026 15:15:34 -0700 Subject: [PATCH 1/5] feat(methods): add blocks.validate method Add the blocks.validate Web API method to the Slack API client. Callers can validate Block Kit payloads via methods().blocksValidate(req) (and the async equivalent), passing blocks, message, or view as JSON-encoded strings. No scopes are required. Adds the endpoint constant, sync and async interface methods and impls, the request form builder, the request/response model classes (with an errors[] list of code/message/pointer/relatedComponent), the Tier3 rate limit, a local test, and a response sample for type generation. Co-Authored-By: Claude --- json-logs/samples/api/blocks.validate.json | 20 +++++++++ metadata/web-api/rate_limit_tiers.json | 1 + .../slack/api/methods/AsyncMethodsClient.java | 10 +++++ .../java/com/slack/api/methods/Methods.java | 6 +++ .../com/slack/api/methods/MethodsClient.java | 12 ++++++ .../slack/api/methods/MethodsRateLimits.java | 2 + .../slack/api/methods/RequestFormBuilder.java | 9 ++++ .../methods/impl/AsyncMethodsClientImpl.java | 12 ++++++ .../api/methods/impl/MethodsClientImpl.java | 12 ++++++ .../request/blocks/BlocksValidateRequest.java | 27 ++++++++++++ .../blocks/BlocksValidateResponse.java | 30 +++++++++++++ .../java/test_locally/api/MethodsTest.java | 2 +- .../test_locally/api/methods/BlocksTest.java | 42 +++++++++++++++++++ 13 files changed, 184 insertions(+), 1 deletion(-) create mode 100644 json-logs/samples/api/blocks.validate.json create mode 100644 slack-api-client/src/main/java/com/slack/api/methods/request/blocks/BlocksValidateRequest.java create mode 100644 slack-api-client/src/main/java/com/slack/api/methods/response/blocks/BlocksValidateResponse.java create mode 100644 slack-api-client/src/test/java/test_locally/api/methods/BlocksTest.java diff --git a/json-logs/samples/api/blocks.validate.json b/json-logs/samples/api/blocks.validate.json new file mode 100644 index 000000000..b99a88772 --- /dev/null +++ b/json-logs/samples/api/blocks.validate.json @@ -0,0 +1,20 @@ +{ + "ok": false, + "error": "", + "response_metadata": { + "messages": [ + "" + ] + }, + "needed": "", + "provided": "", + "errors": [ + { + "code": "", + "message": "", + "pointer": "", + "related_component": "" + } + ], + "warning": "" +} diff --git a/metadata/web-api/rate_limit_tiers.json b/metadata/web-api/rate_limit_tiers.json index 93f929e67..472b4e56a 100644 --- a/metadata/web-api/rate_limit_tiers.json +++ b/metadata/web-api/rate_limit_tiers.json @@ -124,6 +124,7 @@ "bookmarks.edit": "Tier2", "bookmarks.list": "Tier3", "bookmarks.remove": "Tier2", + "blocks.validate": "Tier3", "bots.info": "Tier3", "calls.add": "Tier2", "calls.end": "Tier2", diff --git a/slack-api-client/src/main/java/com/slack/api/methods/AsyncMethodsClient.java b/slack-api-client/src/main/java/com/slack/api/methods/AsyncMethodsClient.java index 4d9b57ead..5427aa341 100644 --- a/slack-api-client/src/main/java/com/slack/api/methods/AsyncMethodsClient.java +++ b/slack-api-client/src/main/java/com/slack/api/methods/AsyncMethodsClient.java @@ -54,6 +54,7 @@ import com.slack.api.methods.request.bookmarks.BookmarksEditRequest; import com.slack.api.methods.request.bookmarks.BookmarksListRequest; import com.slack.api.methods.request.bookmarks.BookmarksRemoveRequest; +import com.slack.api.methods.request.blocks.BlocksValidateRequest; import com.slack.api.methods.request.bots.BotsInfoRequest; import com.slack.api.methods.request.calls.CallsAddRequest; import com.slack.api.methods.request.calls.CallsEndRequest; @@ -193,6 +194,7 @@ import com.slack.api.methods.response.bookmarks.BookmarksEditResponse; import com.slack.api.methods.response.bookmarks.BookmarksListResponse; import com.slack.api.methods.response.bookmarks.BookmarksRemoveResponse; +import com.slack.api.methods.response.blocks.BlocksValidateResponse; import com.slack.api.methods.response.bots.BotsInfoResponse; import com.slack.api.methods.response.calls.CallsAddResponse; import com.slack.api.methods.response.calls.CallsEndResponse; @@ -915,6 +917,14 @@ CompletableFuture CompletableFuture bookmarksRemove(RequestConfigurator req); + // ------------------------------ + // blocks + // ------------------------------ + + CompletableFuture blocksValidate(BlocksValidateRequest req); + + CompletableFuture blocksValidate(RequestConfigurator req); + // ------------------------------ // bots // ------------------------------ diff --git a/slack-api-client/src/main/java/com/slack/api/methods/Methods.java b/slack-api-client/src/main/java/com/slack/api/methods/Methods.java index 2e39655d4..3c28410f3 100644 --- a/slack-api-client/src/main/java/com/slack/api/methods/Methods.java +++ b/slack-api-client/src/main/java/com/slack/api/methods/Methods.java @@ -304,6 +304,12 @@ private Methods() { public static final String AUTH_TEAMS_LIST = "auth.teams.list"; + // ------------------------------ + // blocks + // ------------------------------ + + public static final String BLOCKS_VALIDATE = "blocks.validate"; + // ------------------------------ // bookmarks // ------------------------------ diff --git a/slack-api-client/src/main/java/com/slack/api/methods/MethodsClient.java b/slack-api-client/src/main/java/com/slack/api/methods/MethodsClient.java index 3a4722eb0..73c68f6ba 100644 --- a/slack-api-client/src/main/java/com/slack/api/methods/MethodsClient.java +++ b/slack-api-client/src/main/java/com/slack/api/methods/MethodsClient.java @@ -60,6 +60,7 @@ import com.slack.api.methods.request.bookmarks.BookmarksEditRequest; import com.slack.api.methods.request.bookmarks.BookmarksListRequest; import com.slack.api.methods.request.bookmarks.BookmarksRemoveRequest; +import com.slack.api.methods.request.blocks.BlocksValidateRequest; import com.slack.api.methods.request.bots.BotsInfoRequest; import com.slack.api.methods.request.calls.CallsAddRequest; import com.slack.api.methods.request.calls.CallsEndRequest; @@ -212,6 +213,7 @@ import com.slack.api.methods.response.bookmarks.BookmarksEditResponse; import com.slack.api.methods.response.bookmarks.BookmarksListResponse; import com.slack.api.methods.response.bookmarks.BookmarksRemoveResponse; +import com.slack.api.methods.response.blocks.BlocksValidateResponse; import com.slack.api.methods.response.bots.BotsInfoResponse; import com.slack.api.methods.response.calls.CallsAddResponse; import com.slack.api.methods.response.calls.CallsEndResponse; @@ -1355,6 +1357,16 @@ AuthTestResponse authTest(RequestConfigurator req) throws IOException, SlackApiException; + // ------------------------------ + // blocks + // ------------------------------ + + BlocksValidateResponse blocksValidate(BlocksValidateRequest req) throws IOException, SlackApiException; + + BlocksValidateResponse blocksValidate( + RequestConfigurator req) + throws IOException, SlackApiException; + // ------------------------------ // bookmarks // ------------------------------ diff --git a/slack-api-client/src/main/java/com/slack/api/methods/MethodsRateLimits.java b/slack-api-client/src/main/java/com/slack/api/methods/MethodsRateLimits.java index 9ecc6fee6..d26e4abe7 100644 --- a/slack-api-client/src/main/java/com/slack/api/methods/MethodsRateLimits.java +++ b/slack-api-client/src/main/java/com/slack/api/methods/MethodsRateLimits.java @@ -242,6 +242,8 @@ public static void setRateLimitTier(String methodName, MethodsRateLimitTier tier setRateLimitTier(BOOKMARKS_LIST, Tier3); setRateLimitTier(BOOKMARKS_REMOVE, Tier2); + setRateLimitTier(BLOCKS_VALIDATE, Tier3); + setRateLimitTier(BOTS_INFO, Tier3); setRateLimitTier(CALLS_ADD, Tier2); diff --git a/slack-api-client/src/main/java/com/slack/api/methods/RequestFormBuilder.java b/slack-api-client/src/main/java/com/slack/api/methods/RequestFormBuilder.java index cb5884a7e..75677e9eb 100644 --- a/slack-api-client/src/main/java/com/slack/api/methods/RequestFormBuilder.java +++ b/slack-api-client/src/main/java/com/slack/api/methods/RequestFormBuilder.java @@ -61,6 +61,7 @@ import com.slack.api.methods.request.bookmarks.BookmarksEditRequest; import com.slack.api.methods.request.bookmarks.BookmarksListRequest; import com.slack.api.methods.request.bookmarks.BookmarksRemoveRequest; +import com.slack.api.methods.request.blocks.BlocksValidateRequest; import com.slack.api.methods.request.bots.BotsInfoRequest; import com.slack.api.methods.request.calls.CallsAddRequest; import com.slack.api.methods.request.calls.CallsEndRequest; @@ -1251,6 +1252,14 @@ public static FormBody.Builder toForm(BookmarksRemoveRequest req) { return form; } + public static FormBody.Builder toForm(BlocksValidateRequest req) { + FormBody.Builder form = new FormBody.Builder(); + setIfNotNull("blocks", req.getBlocks(), form); + setIfNotNull("message", req.getMessage(), form); + setIfNotNull("view", req.getView(), form); + return form; + } + public static FormBody.Builder toForm(BotsInfoRequest req) { FormBody.Builder form = new FormBody.Builder(); setIfNotNull("bot", req.getBot(), form); diff --git a/slack-api-client/src/main/java/com/slack/api/methods/impl/AsyncMethodsClientImpl.java b/slack-api-client/src/main/java/com/slack/api/methods/impl/AsyncMethodsClientImpl.java index 21e007510..5b1e3bbf1 100644 --- a/slack-api-client/src/main/java/com/slack/api/methods/impl/AsyncMethodsClientImpl.java +++ b/slack-api-client/src/main/java/com/slack/api/methods/impl/AsyncMethodsClientImpl.java @@ -59,6 +59,7 @@ import com.slack.api.methods.request.bookmarks.BookmarksEditRequest; import com.slack.api.methods.request.bookmarks.BookmarksListRequest; import com.slack.api.methods.request.bookmarks.BookmarksRemoveRequest; +import com.slack.api.methods.request.blocks.BlocksValidateRequest; import com.slack.api.methods.request.bots.BotsInfoRequest; import com.slack.api.methods.request.calls.CallsAddRequest; import com.slack.api.methods.request.calls.CallsEndRequest; @@ -198,6 +199,7 @@ import com.slack.api.methods.response.bookmarks.BookmarksEditResponse; import com.slack.api.methods.response.bookmarks.BookmarksListResponse; import com.slack.api.methods.response.bookmarks.BookmarksRemoveResponse; +import com.slack.api.methods.response.blocks.BlocksValidateResponse; import com.slack.api.methods.response.bots.BotsInfoResponse; import com.slack.api.methods.response.calls.CallsAddResponse; import com.slack.api.methods.response.calls.CallsEndResponse; @@ -1520,6 +1522,16 @@ public CompletableFuture bookmarksRemove(RequestConfigu return bookmarksRemove(req.configure(BookmarksRemoveRequest.builder()).build()); } + @Override + public CompletableFuture blocksValidate(BlocksValidateRequest req) { + return executor.execute(BLOCKS_VALIDATE, toMap(req), () -> methods.blocksValidate(req)); + } + + @Override + public CompletableFuture blocksValidate(RequestConfigurator req) { + return blocksValidate(req.configure(BlocksValidateRequest.builder()).build()); + } + @Override public CompletableFuture botsInfo(BotsInfoRequest req) { return executor.execute(BOTS_INFO, toMap(req), () -> methods.botsInfo(req)); diff --git a/slack-api-client/src/main/java/com/slack/api/methods/impl/MethodsClientImpl.java b/slack-api-client/src/main/java/com/slack/api/methods/impl/MethodsClientImpl.java index f1d26b619..9d4303b1c 100644 --- a/slack-api-client/src/main/java/com/slack/api/methods/impl/MethodsClientImpl.java +++ b/slack-api-client/src/main/java/com/slack/api/methods/impl/MethodsClientImpl.java @@ -62,6 +62,7 @@ import com.slack.api.methods.request.bookmarks.BookmarksEditRequest; import com.slack.api.methods.request.bookmarks.BookmarksListRequest; import com.slack.api.methods.request.bookmarks.BookmarksRemoveRequest; +import com.slack.api.methods.request.blocks.BlocksValidateRequest; import com.slack.api.methods.request.bots.BotsInfoRequest; import com.slack.api.methods.request.calls.CallsAddRequest; import com.slack.api.methods.request.calls.CallsEndRequest; @@ -214,6 +215,7 @@ import com.slack.api.methods.response.bookmarks.BookmarksEditResponse; import com.slack.api.methods.response.bookmarks.BookmarksListResponse; import com.slack.api.methods.response.bookmarks.BookmarksRemoveResponse; +import com.slack.api.methods.response.blocks.BlocksValidateResponse; import com.slack.api.methods.response.bots.BotsInfoResponse; import com.slack.api.methods.response.calls.CallsAddResponse; import com.slack.api.methods.response.calls.CallsEndResponse; @@ -1598,6 +1600,16 @@ public BookmarksRemoveResponse bookmarksRemove(RequestConfigurator req) throws IOException, SlackApiException { + return blocksValidate(req.configure(BlocksValidateRequest.builder()).build()); + } + @Override public BotsInfoResponse botsInfo(BotsInfoRequest req) throws IOException, SlackApiException { this.teamId.ifPresent(currentTeamId -> { diff --git a/slack-api-client/src/main/java/com/slack/api/methods/request/blocks/BlocksValidateRequest.java b/slack-api-client/src/main/java/com/slack/api/methods/request/blocks/BlocksValidateRequest.java new file mode 100644 index 000000000..62476a338 --- /dev/null +++ b/slack-api-client/src/main/java/com/slack/api/methods/request/blocks/BlocksValidateRequest.java @@ -0,0 +1,27 @@ +package com.slack.api.methods.request.blocks; + +import com.slack.api.methods.SlackApiRequest; +import lombok.Builder; +import lombok.Data; + +@Data +@Builder +public class BlocksValidateRequest implements SlackApiRequest { + + private String token; + + /** + * A JSON-encoded string of an array of blocks to validate. + */ + private String blocks; + + /** + * A JSON-encoded string of a message payload to validate. + */ + private String message; + + /** + * A JSON-encoded string of a view payload to validate. + */ + private String view; +} diff --git a/slack-api-client/src/main/java/com/slack/api/methods/response/blocks/BlocksValidateResponse.java b/slack-api-client/src/main/java/com/slack/api/methods/response/blocks/BlocksValidateResponse.java new file mode 100644 index 000000000..493f3b548 --- /dev/null +++ b/slack-api-client/src/main/java/com/slack/api/methods/response/blocks/BlocksValidateResponse.java @@ -0,0 +1,30 @@ +package com.slack.api.methods.response.blocks; + +import com.slack.api.methods.SlackApiTextResponse; +import com.slack.api.model.ResponseMetadata; +import lombok.Data; + +import java.util.List; +import java.util.Map; + +@Data +public class BlocksValidateResponse implements SlackApiTextResponse { + + private boolean ok; + private String warning; + private String error; + private String needed; + private String provided; + private transient Map> httpResponseHeaders; + + private ResponseMetadata responseMetadata; + private List errors; + + @Data + public static class Error { + private String code; + private String message; + private String pointer; + private String relatedComponent; + } +} diff --git a/slack-api-client/src/test/java/test_locally/api/MethodsTest.java b/slack-api-client/src/test/java/test_locally/api/MethodsTest.java index 39f74b8bb..15d1c3643 100644 --- a/slack-api-client/src/test/java/test_locally/api/MethodsTest.java +++ b/slack-api-client/src/test/java/test_locally/api/MethodsTest.java @@ -20,7 +20,7 @@ public void verifyTheCoverage() { // https://docs.slack.dev/reference/methods // var methodNames = [].slice.call(document.getElementsByClassName('apiReferenceFilterableList__listItemLink')).map(e => e.href.replace("https://docs.slack.dev/reference/methods/", ""));console.log(methodNames.toString());console.log(methodNames.length); // 308 endpoints as of February 26, 2026 - String methods = "admin.analytics.getFile,admin.apps.activities.list,admin.apps.approve,admin.apps.clearResolution,admin.apps.restrict,admin.apps.uninstall,admin.apps.approved.list,admin.apps.config.lookup,admin.apps.config.set,admin.apps.requests.cancel,admin.apps.requests.list,admin.apps.restricted.list,admin.audit.anomaly.allow.getItem,admin.audit.anomaly.allow.updateItem,admin.auth.policy.assignEntities,admin.auth.policy.getEntities,admin.auth.policy.removeEntities,admin.barriers.create,admin.barriers.delete,admin.barriers.list,admin.barriers.update,admin.conversations.archive,admin.conversations.bulkArchive,admin.conversations.bulkDelete,admin.conversations.bulkMove,admin.conversations.convertToPrivate,admin.conversations.convertToPublic,admin.conversations.create,admin.conversations.createForObjects,admin.conversations.delete,admin.conversations.disconnectShared,admin.conversations.getConversationPrefs,admin.conversations.getCustomRetention,admin.conversations.getTeams,admin.conversations.invite,admin.conversations.linkObjects,admin.conversations.lookup,admin.conversations.removeCustomRetention,admin.conversations.rename,admin.conversations.search,admin.conversations.setConversationPrefs,admin.conversations.setCustomRetention,admin.conversations.setTeams,admin.conversations.unarchive,admin.conversations.unlinkObjects,admin.conversations.ekm.listOriginalConnectedChannelInfo,admin.conversations.restrictAccess.addGroup,admin.conversations.restrictAccess.listGroups,admin.conversations.restrictAccess.removeGroup,admin.emoji.add,admin.emoji.addAlias,admin.emoji.list,admin.emoji.remove,admin.emoji.rename,admin.functions.list,admin.functions.permissions.lookup,admin.functions.permissions.set,admin.inviteRequests.approve,admin.inviteRequests.deny,admin.inviteRequests.list,admin.inviteRequests.approved.list,admin.inviteRequests.denied.list,admin.roles.addAssignments,admin.roles.listAssignments,admin.roles.removeAssignments,admin.teams.admins.list,admin.teams.create,admin.teams.list,admin.teams.owners.list,admin.teams.settings.info,admin.teams.settings.setDefaultChannels,admin.teams.settings.setDescription,admin.teams.settings.setDiscoverability,admin.teams.settings.setIcon,admin.teams.settings.setName,admin.usergroups.addChannels,admin.usergroups.addTeams,admin.usergroups.listChannels,admin.usergroups.removeChannels,admin.users.assign,admin.users.getExpiration,admin.users.invite,admin.users.list,admin.users.remove,admin.users.setAdmin,admin.users.setExpiration,admin.users.setOwner,admin.users.setRegular,admin.users.session.clearSettings,admin.users.session.getSettings,admin.users.session.invalidate,admin.users.session.list,admin.users.session.reset,admin.users.session.resetBulk,admin.users.session.setSettings,admin.users.unsupportedVersions.export,admin.workflows.collaborators.add,admin.workflows.collaborators.remove,admin.workflows.permissions.lookup,admin.workflows.search,admin.workflows.unpublish,admin.workflows.triggers.types.permissions.lookup,admin.workflows.triggers.types.permissions.set,api.test,apps.activities.list,apps.auth.external.delete,apps.auth.external.get,apps.connections.open,apps.datastore.bulkDelete,apps.datastore.bulkGet,apps.datastore.bulkPut,apps.datastore.count,apps.datastore.delete,apps.datastore.get,apps.datastore.put,apps.datastore.query,apps.datastore.update,apps.event.authorizations.list,apps.manifest.create,apps.manifest.delete,apps.manifest.export,apps.manifest.update,apps.manifest.validate,apps.uninstall,apps.user.connection.update,assistant.search.context,assistant.threads.setStatus,assistant.threads.setSuggestedPrompts,assistant.threads.setTitle,auth.revoke,auth.test,auth.teams.list,bookmarks.add,bookmarks.edit,bookmarks.list,bookmarks.remove,bots.info,calls.add,calls.end,calls.info,calls.update,calls.participants.add,calls.participants.remove,canvases.access.delete,canvases.access.set,canvases.create,canvases.delete,canvases.edit,canvases.sections.lookup,channels.mark,chat.appendStream,chat.delete,chat.deleteScheduledMessage,chat.getPermalink,chat.meMessage,chat.postEphemeral,chat.postMessage,chat.scheduleMessage,chat.startStream,chat.stopStream,chat.unfurl,chat.update,chat.scheduledMessages.list,conversations.acceptSharedInvite,conversations.approveSharedInvite,conversations.archive,conversations.close,conversations.create,conversations.declineSharedInvite,conversations.history,conversations.info,conversations.invite,conversations.inviteShared,conversations.join,conversations.kick,conversations.leave,conversations.list,conversations.listConnectInvites,conversations.mark,conversations.members,conversations.open,conversations.rename,conversations.replies,conversations.setPurpose,conversations.setTopic,conversations.unarchive,conversations.canvases.create,conversations.externalInvitePermissions.set,conversations.requestSharedInvite.approve,conversations.requestSharedInvite.deny,conversations.requestSharedInvite.list,dialog.open,dnd.endDnd,dnd.endSnooze,dnd.info,dnd.setSnooze,dnd.teamInfo,emoji.list,files.comments.delete,files.completeUploadExternal,files.delete,files.getUploadURLExternal,files.info,files.list,files.revokePublicURL,files.sharedPublicURL,files.upload,files.remote.add,files.remote.info,files.remote.list,files.remote.remove,files.remote.share,files.remote.update,functions.completeError,functions.completeSuccess,functions.distributions.permissions.add,functions.distributions.permissions.list,functions.distributions.permissions.remove,functions.distributions.permissions.set,functions.workflows.steps.list,functions.workflows.steps.responses.export,groups.mark,migration.exchange,oauth.access,oauth.v2.access,oauth.v2.exchange,openid.connect.token,openid.connect.userInfo,pins.add,pins.list,pins.remove,reactions.add,reactions.get,reactions.list,reactions.remove,reminders.add,reminders.complete,reminders.delete,reminders.info,reminders.list,rtm.connect,rtm.start,search.all,search.files,search.messages,slackLists.access.delete,slackLists.access.set,slackLists.create,slackLists.download.get,slackLists.download.start,slackLists.items.create,slackLists.items.delete,slackLists.items.deleteMultiple,slackLists.items.info,slackLists.items.list,slackLists.items.update,slackLists.update,stars.add,stars.list,stars.remove,team.accessLogs,team.billableInfo,team.info,team.integrationLogs,team.billing.info,team.externalTeams.disconnect,team.externalTeams.list,team.preferences.list,team.profile.get,tooling.tokens.rotate,usergroups.create,usergroups.disable,usergroups.enable,usergroups.list,usergroups.update,usergroups.users.list,usergroups.users.update,users.conversations,users.deletePhoto,users.getPresence,users.identity,users.info,users.list,users.lookupByEmail,users.setActive,users.setPhoto,users.setPresence,users.discoverableContacts.lookup,users.profile.get,users.profile.set,views.open,views.publish,views.push,views.update,workflows.featured.add,workflows.featured.list,workflows.featured.remove,workflows.featured.set,workflows.stepCompleted,workflows.stepFailed,workflows.updateStep,workflows.triggers.permissions.add,workflows.triggers.permissions.list,workflows.triggers.permissions.remove,workflows.triggers.permissions.set,im.list,im.mark,mpim.list,mpim.mark"; + String methods = "admin.analytics.getFile,admin.apps.activities.list,admin.apps.approve,admin.apps.clearResolution,admin.apps.restrict,admin.apps.uninstall,admin.apps.approved.list,admin.apps.config.lookup,admin.apps.config.set,admin.apps.requests.cancel,admin.apps.requests.list,admin.apps.restricted.list,admin.audit.anomaly.allow.getItem,admin.audit.anomaly.allow.updateItem,admin.auth.policy.assignEntities,admin.auth.policy.getEntities,admin.auth.policy.removeEntities,admin.barriers.create,admin.barriers.delete,admin.barriers.list,admin.barriers.update,admin.conversations.archive,admin.conversations.bulkArchive,admin.conversations.bulkDelete,admin.conversations.bulkMove,admin.conversations.convertToPrivate,admin.conversations.convertToPublic,admin.conversations.create,admin.conversations.createForObjects,admin.conversations.delete,admin.conversations.disconnectShared,admin.conversations.getConversationPrefs,admin.conversations.getCustomRetention,admin.conversations.getTeams,admin.conversations.invite,admin.conversations.linkObjects,admin.conversations.lookup,admin.conversations.removeCustomRetention,admin.conversations.rename,admin.conversations.search,admin.conversations.setConversationPrefs,admin.conversations.setCustomRetention,admin.conversations.setTeams,admin.conversations.unarchive,admin.conversations.unlinkObjects,admin.conversations.ekm.listOriginalConnectedChannelInfo,admin.conversations.restrictAccess.addGroup,admin.conversations.restrictAccess.listGroups,admin.conversations.restrictAccess.removeGroup,admin.emoji.add,admin.emoji.addAlias,admin.emoji.list,admin.emoji.remove,admin.emoji.rename,admin.functions.list,admin.functions.permissions.lookup,admin.functions.permissions.set,admin.inviteRequests.approve,admin.inviteRequests.deny,admin.inviteRequests.list,admin.inviteRequests.approved.list,admin.inviteRequests.denied.list,admin.roles.addAssignments,admin.roles.listAssignments,admin.roles.removeAssignments,admin.teams.admins.list,admin.teams.create,admin.teams.list,admin.teams.owners.list,admin.teams.settings.info,admin.teams.settings.setDefaultChannels,admin.teams.settings.setDescription,admin.teams.settings.setDiscoverability,admin.teams.settings.setIcon,admin.teams.settings.setName,admin.usergroups.addChannels,admin.usergroups.addTeams,admin.usergroups.listChannels,admin.usergroups.removeChannels,admin.users.assign,admin.users.getExpiration,admin.users.invite,admin.users.list,admin.users.remove,admin.users.setAdmin,admin.users.setExpiration,admin.users.setOwner,admin.users.setRegular,admin.users.session.clearSettings,admin.users.session.getSettings,admin.users.session.invalidate,admin.users.session.list,admin.users.session.reset,admin.users.session.resetBulk,admin.users.session.setSettings,admin.users.unsupportedVersions.export,admin.workflows.collaborators.add,admin.workflows.collaborators.remove,admin.workflows.permissions.lookup,admin.workflows.search,admin.workflows.unpublish,admin.workflows.triggers.types.permissions.lookup,admin.workflows.triggers.types.permissions.set,api.test,apps.activities.list,apps.auth.external.delete,apps.auth.external.get,apps.connections.open,apps.datastore.bulkDelete,apps.datastore.bulkGet,apps.datastore.bulkPut,apps.datastore.count,apps.datastore.delete,apps.datastore.get,apps.datastore.put,apps.datastore.query,apps.datastore.update,apps.event.authorizations.list,apps.manifest.create,apps.manifest.delete,apps.manifest.export,apps.manifest.update,apps.manifest.validate,apps.uninstall,apps.user.connection.update,assistant.search.context,assistant.threads.setStatus,assistant.threads.setSuggestedPrompts,assistant.threads.setTitle,auth.revoke,auth.test,auth.teams.list,bookmarks.add,bookmarks.edit,bookmarks.list,bookmarks.remove,blocks.validate,bots.info,calls.add,calls.end,calls.info,calls.update,calls.participants.add,calls.participants.remove,canvases.access.delete,canvases.access.set,canvases.create,canvases.delete,canvases.edit,canvases.sections.lookup,channels.mark,chat.appendStream,chat.delete,chat.deleteScheduledMessage,chat.getPermalink,chat.meMessage,chat.postEphemeral,chat.postMessage,chat.scheduleMessage,chat.startStream,chat.stopStream,chat.unfurl,chat.update,chat.scheduledMessages.list,conversations.acceptSharedInvite,conversations.approveSharedInvite,conversations.archive,conversations.close,conversations.create,conversations.declineSharedInvite,conversations.history,conversations.info,conversations.invite,conversations.inviteShared,conversations.join,conversations.kick,conversations.leave,conversations.list,conversations.listConnectInvites,conversations.mark,conversations.members,conversations.open,conversations.rename,conversations.replies,conversations.setPurpose,conversations.setTopic,conversations.unarchive,conversations.canvases.create,conversations.externalInvitePermissions.set,conversations.requestSharedInvite.approve,conversations.requestSharedInvite.deny,conversations.requestSharedInvite.list,dialog.open,dnd.endDnd,dnd.endSnooze,dnd.info,dnd.setSnooze,dnd.teamInfo,emoji.list,files.comments.delete,files.completeUploadExternal,files.delete,files.getUploadURLExternal,files.info,files.list,files.revokePublicURL,files.sharedPublicURL,files.upload,files.remote.add,files.remote.info,files.remote.list,files.remote.remove,files.remote.share,files.remote.update,functions.completeError,functions.completeSuccess,functions.distributions.permissions.add,functions.distributions.permissions.list,functions.distributions.permissions.remove,functions.distributions.permissions.set,functions.workflows.steps.list,functions.workflows.steps.responses.export,groups.mark,migration.exchange,oauth.access,oauth.v2.access,oauth.v2.exchange,openid.connect.token,openid.connect.userInfo,pins.add,pins.list,pins.remove,reactions.add,reactions.get,reactions.list,reactions.remove,reminders.add,reminders.complete,reminders.delete,reminders.info,reminders.list,rtm.connect,rtm.start,search.all,search.files,search.messages,slackLists.access.delete,slackLists.access.set,slackLists.create,slackLists.download.get,slackLists.download.start,slackLists.items.create,slackLists.items.delete,slackLists.items.deleteMultiple,slackLists.items.info,slackLists.items.list,slackLists.items.update,slackLists.update,stars.add,stars.list,stars.remove,team.accessLogs,team.billableInfo,team.info,team.integrationLogs,team.billing.info,team.externalTeams.disconnect,team.externalTeams.list,team.preferences.list,team.profile.get,tooling.tokens.rotate,usergroups.create,usergroups.disable,usergroups.enable,usergroups.list,usergroups.update,usergroups.users.list,usergroups.users.update,users.conversations,users.deletePhoto,users.getPresence,users.identity,users.info,users.list,users.lookupByEmail,users.setActive,users.setPhoto,users.setPresence,users.discoverableContacts.lookup,users.profile.get,users.profile.set,views.open,views.publish,views.push,views.update,workflows.featured.add,workflows.featured.list,workflows.featured.remove,workflows.featured.set,workflows.stepCompleted,workflows.stepFailed,workflows.updateStep,workflows.triggers.permissions.add,workflows.triggers.permissions.list,workflows.triggers.permissions.remove,workflows.triggers.permissions.set,im.list,im.mark,mpim.list,mpim.mark"; final List existingMethods = new ArrayList<>(); for (Field f : Methods.class.getDeclaredFields()) { int modifiers = f.getModifiers(); diff --git a/slack-api-client/src/test/java/test_locally/api/methods/BlocksTest.java b/slack-api-client/src/test/java/test_locally/api/methods/BlocksTest.java new file mode 100644 index 000000000..7225e2de6 --- /dev/null +++ b/slack-api-client/src/test/java/test_locally/api/methods/BlocksTest.java @@ -0,0 +1,42 @@ +package test_locally.api.methods; + +import com.slack.api.Slack; +import com.slack.api.SlackConfig; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import util.MockSlackApiServer; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static test_locally.api.status.ApiTest.ValidToken; + +public class BlocksTest { + + MockSlackApiServer server = new MockSlackApiServer(); + SlackConfig config = new SlackConfig(); + Slack slack = Slack.getInstance(config); + + @Before + public void setup() throws Exception { + server.start(); + config.setMethodsEndpointUrlPrefix(server.getMethodsEndpointPrefix()); + } + + @After + public void tearDown() throws Exception { + server.stop(); + } + + @Test + public void validate() throws Exception { + assertThat(slack.methods(ValidToken).blocksValidate(r -> r + .blocks("[{\"type\":\"section\",\"text\":{\"type\":\"plain_text\",\"text\":\"Hello world\"}}]")).isOk(), is(true)); + } + + @Test + public void validate_async() throws Exception { + assertThat(slack.methodsAsync(ValidToken).blocksValidate(r -> r + .blocks("[{\"type\":\"section\",\"text\":{\"type\":\"plain_text\",\"text\":\"Hello world\"}}]")).get().isOk(), is(true)); + } +} From 02a29a7a34bf9824fb19661ffa4b57b53da901de Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Fri, 14 Aug 2026 18:30:33 -0700 Subject: [PATCH 2/5] fix(methods): classify blocks.validate as a special rate-limit tier MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit blocks.validate has special rate-limiting conditions rather than a standard tier (see https://docs.slack.dev/reference/methods/blocks.validate), so model it as SpecialTier_blocks_validate instead of Tier3. Regenerate the rate-limit metadata so the committed rate_limit_tiers.json matches the generated output, which also sorts blocks.validate into its correct alphabetical position — this is what was tripping the CI tree-drift check. Co-Authored-By: Claude --- metadata/web-api/rate_limit_tiers.json | 2 +- .../com/slack/api/methods/MethodsRateLimitTier.java | 10 +++++++++- .../java/com/slack/api/methods/MethodsRateLimits.java | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/metadata/web-api/rate_limit_tiers.json b/metadata/web-api/rate_limit_tiers.json index 472b4e56a..8884d448f 100644 --- a/metadata/web-api/rate_limit_tiers.json +++ b/metadata/web-api/rate_limit_tiers.json @@ -120,11 +120,11 @@ "auth.revoke": "Tier3", "auth.teams.list": "Tier2", "auth.test": "SpecialTier_auth_test", + "blocks.validate": "SpecialTier_blocks_validate", "bookmarks.add": "Tier2", "bookmarks.edit": "Tier2", "bookmarks.list": "Tier3", "bookmarks.remove": "Tier2", - "blocks.validate": "Tier3", "bots.info": "Tier3", "calls.add": "Tier2", "calls.end": "Tier2", diff --git a/slack-api-client/src/main/java/com/slack/api/methods/MethodsRateLimitTier.java b/slack-api-client/src/main/java/com/slack/api/methods/MethodsRateLimitTier.java index cbbfca4f9..894522e84 100644 --- a/slack-api-client/src/main/java/com/slack/api/methods/MethodsRateLimitTier.java +++ b/slack-api-client/src/main/java/com/slack/api/methods/MethodsRateLimitTier.java @@ -57,7 +57,14 @@ public enum MethodsRateLimitTier { /** * This method allows hundreds of requests per minute. Use it as often as is reasonably required. */ - SpecialTier_chat_getPermalink; + SpecialTier_chat_getPermalink, + + /** + * blocks.validate has special rate limiting conditions rather than a standard tier. + * It requires no scopes and is a lightweight validation call, so it allows hundreds of + * requests per minute. See https://docs.slack.dev/reference/methods/blocks.validate. + */ + SpecialTier_blocks_validate; // -------------------------------------------------------------------------------------------- @@ -72,6 +79,7 @@ public enum MethodsRateLimitTier { allowedRequestsPerMinute.put(MethodsRateLimitTier.SpecialTier_chat_getPermalink, 600); allowedRequestsPerMinute.put(MethodsRateLimitTier.SpecialTier_chat_postMessage, 60); // per channel allowedRequestsPerMinute.put(MethodsRateLimitTier.SpecialTier_assistant_threads_setStatus, 60); // per DM + allowedRequestsPerMinute.put(MethodsRateLimitTier.SpecialTier_blocks_validate, 600); } public static Integer getAllowedRequestsPerMinute(MethodsRateLimitTier tier) { diff --git a/slack-api-client/src/main/java/com/slack/api/methods/MethodsRateLimits.java b/slack-api-client/src/main/java/com/slack/api/methods/MethodsRateLimits.java index d26e4abe7..cde4fc138 100644 --- a/slack-api-client/src/main/java/com/slack/api/methods/MethodsRateLimits.java +++ b/slack-api-client/src/main/java/com/slack/api/methods/MethodsRateLimits.java @@ -242,7 +242,7 @@ public static void setRateLimitTier(String methodName, MethodsRateLimitTier tier setRateLimitTier(BOOKMARKS_LIST, Tier3); setRateLimitTier(BOOKMARKS_REMOVE, Tier2); - setRateLimitTier(BLOCKS_VALIDATE, Tier3); + setRateLimitTier(BLOCKS_VALIDATE, SpecialTier_blocks_validate); setRateLimitTier(BOTS_INFO, Tier3); From efb20b636486d51f005f2dc98f3f6991231bfcc7 Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Fri, 14 Aug 2026 18:30:39 -0700 Subject: [PATCH 3/5] test(methods): add remote coverage for blocks.validate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a blocks_Test integration test under test_with_remote_apis that exercises blocks.validate against the real API: a well-formed payload validates with no errors, and a malformed payload surfaces the live validation feedback (recording the actual contract — ok=false with an error, or ok=true with a populated errors[] carrying code/message/pointer). Refresh the method-coverage scrape marker in MethodsTest to reflect the current 310-endpoint list. Co-Authored-By: Claude --- .../java/test_locally/api/MethodsTest.java | 2 +- .../methods/blocks_Test.java | 60 +++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 slack-api-client/src/test/java/test_with_remote_apis/methods/blocks_Test.java diff --git a/slack-api-client/src/test/java/test_locally/api/MethodsTest.java b/slack-api-client/src/test/java/test_locally/api/MethodsTest.java index 15d1c3643..f3dc32a23 100644 --- a/slack-api-client/src/test/java/test_locally/api/MethodsTest.java +++ b/slack-api-client/src/test/java/test_locally/api/MethodsTest.java @@ -19,7 +19,7 @@ public class MethodsTest { public void verifyTheCoverage() { // https://docs.slack.dev/reference/methods // var methodNames = [].slice.call(document.getElementsByClassName('apiReferenceFilterableList__listItemLink')).map(e => e.href.replace("https://docs.slack.dev/reference/methods/", ""));console.log(methodNames.toString());console.log(methodNames.length); - // 308 endpoints as of February 26, 2026 + // 310 endpoints as of August 14, 2026 String methods = "admin.analytics.getFile,admin.apps.activities.list,admin.apps.approve,admin.apps.clearResolution,admin.apps.restrict,admin.apps.uninstall,admin.apps.approved.list,admin.apps.config.lookup,admin.apps.config.set,admin.apps.requests.cancel,admin.apps.requests.list,admin.apps.restricted.list,admin.audit.anomaly.allow.getItem,admin.audit.anomaly.allow.updateItem,admin.auth.policy.assignEntities,admin.auth.policy.getEntities,admin.auth.policy.removeEntities,admin.barriers.create,admin.barriers.delete,admin.barriers.list,admin.barriers.update,admin.conversations.archive,admin.conversations.bulkArchive,admin.conversations.bulkDelete,admin.conversations.bulkMove,admin.conversations.convertToPrivate,admin.conversations.convertToPublic,admin.conversations.create,admin.conversations.createForObjects,admin.conversations.delete,admin.conversations.disconnectShared,admin.conversations.getConversationPrefs,admin.conversations.getCustomRetention,admin.conversations.getTeams,admin.conversations.invite,admin.conversations.linkObjects,admin.conversations.lookup,admin.conversations.removeCustomRetention,admin.conversations.rename,admin.conversations.search,admin.conversations.setConversationPrefs,admin.conversations.setCustomRetention,admin.conversations.setTeams,admin.conversations.unarchive,admin.conversations.unlinkObjects,admin.conversations.ekm.listOriginalConnectedChannelInfo,admin.conversations.restrictAccess.addGroup,admin.conversations.restrictAccess.listGroups,admin.conversations.restrictAccess.removeGroup,admin.emoji.add,admin.emoji.addAlias,admin.emoji.list,admin.emoji.remove,admin.emoji.rename,admin.functions.list,admin.functions.permissions.lookup,admin.functions.permissions.set,admin.inviteRequests.approve,admin.inviteRequests.deny,admin.inviteRequests.list,admin.inviteRequests.approved.list,admin.inviteRequests.denied.list,admin.roles.addAssignments,admin.roles.listAssignments,admin.roles.removeAssignments,admin.teams.admins.list,admin.teams.create,admin.teams.list,admin.teams.owners.list,admin.teams.settings.info,admin.teams.settings.setDefaultChannels,admin.teams.settings.setDescription,admin.teams.settings.setDiscoverability,admin.teams.settings.setIcon,admin.teams.settings.setName,admin.usergroups.addChannels,admin.usergroups.addTeams,admin.usergroups.listChannels,admin.usergroups.removeChannels,admin.users.assign,admin.users.getExpiration,admin.users.invite,admin.users.list,admin.users.remove,admin.users.setAdmin,admin.users.setExpiration,admin.users.setOwner,admin.users.setRegular,admin.users.session.clearSettings,admin.users.session.getSettings,admin.users.session.invalidate,admin.users.session.list,admin.users.session.reset,admin.users.session.resetBulk,admin.users.session.setSettings,admin.users.unsupportedVersions.export,admin.workflows.collaborators.add,admin.workflows.collaborators.remove,admin.workflows.permissions.lookup,admin.workflows.search,admin.workflows.unpublish,admin.workflows.triggers.types.permissions.lookup,admin.workflows.triggers.types.permissions.set,api.test,apps.activities.list,apps.auth.external.delete,apps.auth.external.get,apps.connections.open,apps.datastore.bulkDelete,apps.datastore.bulkGet,apps.datastore.bulkPut,apps.datastore.count,apps.datastore.delete,apps.datastore.get,apps.datastore.put,apps.datastore.query,apps.datastore.update,apps.event.authorizations.list,apps.manifest.create,apps.manifest.delete,apps.manifest.export,apps.manifest.update,apps.manifest.validate,apps.uninstall,apps.user.connection.update,assistant.search.context,assistant.threads.setStatus,assistant.threads.setSuggestedPrompts,assistant.threads.setTitle,auth.revoke,auth.test,auth.teams.list,bookmarks.add,bookmarks.edit,bookmarks.list,bookmarks.remove,blocks.validate,bots.info,calls.add,calls.end,calls.info,calls.update,calls.participants.add,calls.participants.remove,canvases.access.delete,canvases.access.set,canvases.create,canvases.delete,canvases.edit,canvases.sections.lookup,channels.mark,chat.appendStream,chat.delete,chat.deleteScheduledMessage,chat.getPermalink,chat.meMessage,chat.postEphemeral,chat.postMessage,chat.scheduleMessage,chat.startStream,chat.stopStream,chat.unfurl,chat.update,chat.scheduledMessages.list,conversations.acceptSharedInvite,conversations.approveSharedInvite,conversations.archive,conversations.close,conversations.create,conversations.declineSharedInvite,conversations.history,conversations.info,conversations.invite,conversations.inviteShared,conversations.join,conversations.kick,conversations.leave,conversations.list,conversations.listConnectInvites,conversations.mark,conversations.members,conversations.open,conversations.rename,conversations.replies,conversations.setPurpose,conversations.setTopic,conversations.unarchive,conversations.canvases.create,conversations.externalInvitePermissions.set,conversations.requestSharedInvite.approve,conversations.requestSharedInvite.deny,conversations.requestSharedInvite.list,dialog.open,dnd.endDnd,dnd.endSnooze,dnd.info,dnd.setSnooze,dnd.teamInfo,emoji.list,files.comments.delete,files.completeUploadExternal,files.delete,files.getUploadURLExternal,files.info,files.list,files.revokePublicURL,files.sharedPublicURL,files.upload,files.remote.add,files.remote.info,files.remote.list,files.remote.remove,files.remote.share,files.remote.update,functions.completeError,functions.completeSuccess,functions.distributions.permissions.add,functions.distributions.permissions.list,functions.distributions.permissions.remove,functions.distributions.permissions.set,functions.workflows.steps.list,functions.workflows.steps.responses.export,groups.mark,migration.exchange,oauth.access,oauth.v2.access,oauth.v2.exchange,openid.connect.token,openid.connect.userInfo,pins.add,pins.list,pins.remove,reactions.add,reactions.get,reactions.list,reactions.remove,reminders.add,reminders.complete,reminders.delete,reminders.info,reminders.list,rtm.connect,rtm.start,search.all,search.files,search.messages,slackLists.access.delete,slackLists.access.set,slackLists.create,slackLists.download.get,slackLists.download.start,slackLists.items.create,slackLists.items.delete,slackLists.items.deleteMultiple,slackLists.items.info,slackLists.items.list,slackLists.items.update,slackLists.update,stars.add,stars.list,stars.remove,team.accessLogs,team.billableInfo,team.info,team.integrationLogs,team.billing.info,team.externalTeams.disconnect,team.externalTeams.list,team.preferences.list,team.profile.get,tooling.tokens.rotate,usergroups.create,usergroups.disable,usergroups.enable,usergroups.list,usergroups.update,usergroups.users.list,usergroups.users.update,users.conversations,users.deletePhoto,users.getPresence,users.identity,users.info,users.list,users.lookupByEmail,users.setActive,users.setPhoto,users.setPresence,users.discoverableContacts.lookup,users.profile.get,users.profile.set,views.open,views.publish,views.push,views.update,workflows.featured.add,workflows.featured.list,workflows.featured.remove,workflows.featured.set,workflows.stepCompleted,workflows.stepFailed,workflows.updateStep,workflows.triggers.permissions.add,workflows.triggers.permissions.list,workflows.triggers.permissions.remove,workflows.triggers.permissions.set,im.list,im.mark,mpim.list,mpim.mark"; final List existingMethods = new ArrayList<>(); for (Field f : Methods.class.getDeclaredFields()) { diff --git a/slack-api-client/src/test/java/test_with_remote_apis/methods/blocks_Test.java b/slack-api-client/src/test/java/test_with_remote_apis/methods/blocks_Test.java new file mode 100644 index 000000000..406ea17c0 --- /dev/null +++ b/slack-api-client/src/test/java/test_with_remote_apis/methods/blocks_Test.java @@ -0,0 +1,60 @@ +package test_with_remote_apis.methods; + +import com.slack.api.Slack; +import com.slack.api.methods.response.blocks.BlocksValidateResponse; +import config.Constants; +import config.SlackTestConfig; +import org.junit.AfterClass; +import org.junit.Test; + +import java.util.List; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.hamcrest.MatcherAssert.assertThat; + +public class blocks_Test { + + String botToken = System.getenv(Constants.SLACK_SDK_TEST_BOT_TOKEN); + + static SlackTestConfig testConfig = SlackTestConfig.getInstance(); + static Slack slack = Slack.getInstance(testConfig.getConfig()); + + @AfterClass + public static void tearDown() throws InterruptedException { + SlackTestConfig.awaitCompletion(testConfig); + } + + @Test + public void validate_wellFormed() throws Exception { + // A well-formed block payload should validate without errors. + String validBlocks = "[{\"type\":\"section\",\"text\":{\"type\":\"mrkdwn\",\"text\":\"Hello\"}}]"; + BlocksValidateResponse response = slack.methods(botToken).blocksValidate(r -> r.blocks(validBlocks)); + assertThat(response.getError(), is(nullValue())); + assertThat(response.isOk(), is(true)); + assertThat(response.getErrors() == null || response.getErrors().isEmpty(), is(true)); + } + + @Test + public void validate_malformed() throws Exception { + // A malformed block payload (a section with neither text nor fields) should surface + // validation feedback. This test records the live contract rather than asserting a fixed + // shape: blocks.validate may return ok=false with an error, or ok=true with a populated + // errors[] carrying code/message/pointer/relatedComponent. + String invalidBlocks = "[{\"type\":\"section\"}]"; + BlocksValidateResponse response = slack.methods(botToken).blocksValidate(r -> r.blocks(invalidBlocks)); + if (response.isOk()) { + List errors = response.getErrors(); + assertThat(errors, is(notNullValue())); + assertThat(errors.isEmpty(), is(false)); + BlocksValidateResponse.Error first = errors.get(0); + // The error entry carries the structured validation feedback contract. + assertThat(first.getCode(), is(notNullValue())); + assertThat(first.getMessage(), is(notNullValue())); + assertThat(first.getPointer(), is(notNullValue())); + } else { + assertThat(response.getError(), is(notNullValue())); + } + } +} From eb983efa6cdb314695fb66d0ca48c029986e931d Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Fri, 14 Aug 2026 18:35:40 -0700 Subject: [PATCH 4/5] style(methods): sort blocks.validate into its alphabetical position MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The method was consistently placed after the bookmarks family, but "blocks" sorts before "bookmarks". Move every insertion site into alphabetical order: request/response imports, the sync/async interface declarations and their implementations, the RequestFormBuilder toForm mapping, the rate-limit tier registration, and the method-coverage string in MethodsTest. Pure reordering — no behavior change. Co-Authored-By: Claude --- .../slack/api/methods/AsyncMethodsClient.java | 20 ++++++++-------- .../com/slack/api/methods/MethodsClient.java | 4 ++-- .../slack/api/methods/MethodsRateLimits.java | 4 ++-- .../slack/api/methods/RequestFormBuilder.java | 18 +++++++------- .../methods/impl/AsyncMethodsClientImpl.java | 24 +++++++++---------- .../api/methods/impl/MethodsClientImpl.java | 24 +++++++++---------- .../java/test_locally/api/MethodsTest.java | 2 +- 7 files changed, 48 insertions(+), 48 deletions(-) diff --git a/slack-api-client/src/main/java/com/slack/api/methods/AsyncMethodsClient.java b/slack-api-client/src/main/java/com/slack/api/methods/AsyncMethodsClient.java index 5427aa341..128e0b619 100644 --- a/slack-api-client/src/main/java/com/slack/api/methods/AsyncMethodsClient.java +++ b/slack-api-client/src/main/java/com/slack/api/methods/AsyncMethodsClient.java @@ -50,11 +50,11 @@ import com.slack.api.methods.request.auth.AuthRevokeRequest; import com.slack.api.methods.request.auth.AuthTestRequest; import com.slack.api.methods.request.auth.teams.AuthTeamsListRequest; +import com.slack.api.methods.request.blocks.BlocksValidateRequest; import com.slack.api.methods.request.bookmarks.BookmarksAddRequest; import com.slack.api.methods.request.bookmarks.BookmarksEditRequest; import com.slack.api.methods.request.bookmarks.BookmarksListRequest; import com.slack.api.methods.request.bookmarks.BookmarksRemoveRequest; -import com.slack.api.methods.request.blocks.BlocksValidateRequest; import com.slack.api.methods.request.bots.BotsInfoRequest; import com.slack.api.methods.request.calls.CallsAddRequest; import com.slack.api.methods.request.calls.CallsEndRequest; @@ -190,11 +190,11 @@ import com.slack.api.methods.response.auth.AuthRevokeResponse; import com.slack.api.methods.response.auth.AuthTestResponse; import com.slack.api.methods.response.auth.teams.AuthTeamsListResponse; +import com.slack.api.methods.response.blocks.BlocksValidateResponse; import com.slack.api.methods.response.bookmarks.BookmarksAddResponse; import com.slack.api.methods.response.bookmarks.BookmarksEditResponse; import com.slack.api.methods.response.bookmarks.BookmarksListResponse; import com.slack.api.methods.response.bookmarks.BookmarksRemoveResponse; -import com.slack.api.methods.response.blocks.BlocksValidateResponse; import com.slack.api.methods.response.bots.BotsInfoResponse; import com.slack.api.methods.response.calls.CallsAddResponse; import com.slack.api.methods.response.calls.CallsEndResponse; @@ -897,6 +897,14 @@ CompletableFuture CompletableFuture authTeamsList(RequestConfigurator req); + // ------------------------------ + // blocks + // ------------------------------ + + CompletableFuture blocksValidate(BlocksValidateRequest req); + + CompletableFuture blocksValidate(RequestConfigurator req); + // ------------------------------ // bookmarks // ------------------------------ @@ -917,14 +925,6 @@ CompletableFuture CompletableFuture bookmarksRemove(RequestConfigurator req); - // ------------------------------ - // blocks - // ------------------------------ - - CompletableFuture blocksValidate(BlocksValidateRequest req); - - CompletableFuture blocksValidate(RequestConfigurator req); - // ------------------------------ // bots // ------------------------------ diff --git a/slack-api-client/src/main/java/com/slack/api/methods/MethodsClient.java b/slack-api-client/src/main/java/com/slack/api/methods/MethodsClient.java index 73c68f6ba..c5048447f 100644 --- a/slack-api-client/src/main/java/com/slack/api/methods/MethodsClient.java +++ b/slack-api-client/src/main/java/com/slack/api/methods/MethodsClient.java @@ -56,11 +56,11 @@ import com.slack.api.methods.request.auth.AuthRevokeRequest; import com.slack.api.methods.request.auth.AuthTestRequest; import com.slack.api.methods.request.auth.teams.AuthTeamsListRequest; +import com.slack.api.methods.request.blocks.BlocksValidateRequest; import com.slack.api.methods.request.bookmarks.BookmarksAddRequest; import com.slack.api.methods.request.bookmarks.BookmarksEditRequest; import com.slack.api.methods.request.bookmarks.BookmarksListRequest; import com.slack.api.methods.request.bookmarks.BookmarksRemoveRequest; -import com.slack.api.methods.request.blocks.BlocksValidateRequest; import com.slack.api.methods.request.bots.BotsInfoRequest; import com.slack.api.methods.request.calls.CallsAddRequest; import com.slack.api.methods.request.calls.CallsEndRequest; @@ -209,11 +209,11 @@ import com.slack.api.methods.response.auth.AuthRevokeResponse; import com.slack.api.methods.response.auth.AuthTestResponse; import com.slack.api.methods.response.auth.teams.AuthTeamsListResponse; +import com.slack.api.methods.response.blocks.BlocksValidateResponse; import com.slack.api.methods.response.bookmarks.BookmarksAddResponse; import com.slack.api.methods.response.bookmarks.BookmarksEditResponse; import com.slack.api.methods.response.bookmarks.BookmarksListResponse; import com.slack.api.methods.response.bookmarks.BookmarksRemoveResponse; -import com.slack.api.methods.response.blocks.BlocksValidateResponse; import com.slack.api.methods.response.bots.BotsInfoResponse; import com.slack.api.methods.response.calls.CallsAddResponse; import com.slack.api.methods.response.calls.CallsEndResponse; diff --git a/slack-api-client/src/main/java/com/slack/api/methods/MethodsRateLimits.java b/slack-api-client/src/main/java/com/slack/api/methods/MethodsRateLimits.java index cde4fc138..2c268c478 100644 --- a/slack-api-client/src/main/java/com/slack/api/methods/MethodsRateLimits.java +++ b/slack-api-client/src/main/java/com/slack/api/methods/MethodsRateLimits.java @@ -237,13 +237,13 @@ public static void setRateLimitTier(String methodName, MethodsRateLimitTier tier setRateLimitTier(AUTH_TEST, SpecialTier_auth_test); setRateLimitTier(AUTH_TEAMS_LIST, Tier2); + setRateLimitTier(BLOCKS_VALIDATE, SpecialTier_blocks_validate); + setRateLimitTier(BOOKMARKS_ADD, Tier2); setRateLimitTier(BOOKMARKS_EDIT, Tier2); setRateLimitTier(BOOKMARKS_LIST, Tier3); setRateLimitTier(BOOKMARKS_REMOVE, Tier2); - setRateLimitTier(BLOCKS_VALIDATE, SpecialTier_blocks_validate); - setRateLimitTier(BOTS_INFO, Tier3); setRateLimitTier(CALLS_ADD, Tier2); diff --git a/slack-api-client/src/main/java/com/slack/api/methods/RequestFormBuilder.java b/slack-api-client/src/main/java/com/slack/api/methods/RequestFormBuilder.java index 75677e9eb..167f6471f 100644 --- a/slack-api-client/src/main/java/com/slack/api/methods/RequestFormBuilder.java +++ b/slack-api-client/src/main/java/com/slack/api/methods/RequestFormBuilder.java @@ -57,11 +57,11 @@ import com.slack.api.methods.request.auth.AuthRevokeRequest; import com.slack.api.methods.request.auth.AuthTestRequest; import com.slack.api.methods.request.auth.teams.AuthTeamsListRequest; +import com.slack.api.methods.request.blocks.BlocksValidateRequest; import com.slack.api.methods.request.bookmarks.BookmarksAddRequest; import com.slack.api.methods.request.bookmarks.BookmarksEditRequest; import com.slack.api.methods.request.bookmarks.BookmarksListRequest; import com.slack.api.methods.request.bookmarks.BookmarksRemoveRequest; -import com.slack.api.methods.request.blocks.BlocksValidateRequest; import com.slack.api.methods.request.bots.BotsInfoRequest; import com.slack.api.methods.request.calls.CallsAddRequest; import com.slack.api.methods.request.calls.CallsEndRequest; @@ -1217,6 +1217,14 @@ public static FormBody.Builder toForm(AuthTeamsListRequest req) { return form; } + public static FormBody.Builder toForm(BlocksValidateRequest req) { + FormBody.Builder form = new FormBody.Builder(); + setIfNotNull("blocks", req.getBlocks(), form); + setIfNotNull("message", req.getMessage(), form); + setIfNotNull("view", req.getView(), form); + return form; + } + public static FormBody.Builder toForm(BookmarksAddRequest req) { FormBody.Builder form = new FormBody.Builder(); setIfNotNull("channel_id", req.getChannelId(), form); @@ -1252,14 +1260,6 @@ public static FormBody.Builder toForm(BookmarksRemoveRequest req) { return form; } - public static FormBody.Builder toForm(BlocksValidateRequest req) { - FormBody.Builder form = new FormBody.Builder(); - setIfNotNull("blocks", req.getBlocks(), form); - setIfNotNull("message", req.getMessage(), form); - setIfNotNull("view", req.getView(), form); - return form; - } - public static FormBody.Builder toForm(BotsInfoRequest req) { FormBody.Builder form = new FormBody.Builder(); setIfNotNull("bot", req.getBot(), form); diff --git a/slack-api-client/src/main/java/com/slack/api/methods/impl/AsyncMethodsClientImpl.java b/slack-api-client/src/main/java/com/slack/api/methods/impl/AsyncMethodsClientImpl.java index 5b1e3bbf1..2c20f6532 100644 --- a/slack-api-client/src/main/java/com/slack/api/methods/impl/AsyncMethodsClientImpl.java +++ b/slack-api-client/src/main/java/com/slack/api/methods/impl/AsyncMethodsClientImpl.java @@ -55,11 +55,11 @@ import com.slack.api.methods.request.auth.AuthRevokeRequest; import com.slack.api.methods.request.auth.AuthTestRequest; import com.slack.api.methods.request.auth.teams.AuthTeamsListRequest; +import com.slack.api.methods.request.blocks.BlocksValidateRequest; import com.slack.api.methods.request.bookmarks.BookmarksAddRequest; import com.slack.api.methods.request.bookmarks.BookmarksEditRequest; import com.slack.api.methods.request.bookmarks.BookmarksListRequest; import com.slack.api.methods.request.bookmarks.BookmarksRemoveRequest; -import com.slack.api.methods.request.blocks.BlocksValidateRequest; import com.slack.api.methods.request.bots.BotsInfoRequest; import com.slack.api.methods.request.calls.CallsAddRequest; import com.slack.api.methods.request.calls.CallsEndRequest; @@ -195,11 +195,11 @@ import com.slack.api.methods.response.auth.AuthRevokeResponse; import com.slack.api.methods.response.auth.AuthTestResponse; import com.slack.api.methods.response.auth.teams.AuthTeamsListResponse; +import com.slack.api.methods.response.blocks.BlocksValidateResponse; import com.slack.api.methods.response.bookmarks.BookmarksAddResponse; import com.slack.api.methods.response.bookmarks.BookmarksEditResponse; import com.slack.api.methods.response.bookmarks.BookmarksListResponse; import com.slack.api.methods.response.bookmarks.BookmarksRemoveResponse; -import com.slack.api.methods.response.blocks.BlocksValidateResponse; import com.slack.api.methods.response.bots.BotsInfoResponse; import com.slack.api.methods.response.calls.CallsAddResponse; import com.slack.api.methods.response.calls.CallsEndResponse; @@ -1482,6 +1482,16 @@ public CompletableFuture authTeamsList(RequestConfigurato return authTeamsList(req.configure(AuthTeamsListRequest.builder()).build()); } + @Override + public CompletableFuture blocksValidate(BlocksValidateRequest req) { + return executor.execute(BLOCKS_VALIDATE, toMap(req), () -> methods.blocksValidate(req)); + } + + @Override + public CompletableFuture blocksValidate(RequestConfigurator req) { + return blocksValidate(req.configure(BlocksValidateRequest.builder()).build()); + } + @Override public CompletableFuture bookmarksAdd(BookmarksAddRequest req) { return executor.execute(BOOKMARKS_ADD, toMap(req), () -> methods.bookmarksAdd(req)); @@ -1522,16 +1532,6 @@ public CompletableFuture bookmarksRemove(RequestConfigu return bookmarksRemove(req.configure(BookmarksRemoveRequest.builder()).build()); } - @Override - public CompletableFuture blocksValidate(BlocksValidateRequest req) { - return executor.execute(BLOCKS_VALIDATE, toMap(req), () -> methods.blocksValidate(req)); - } - - @Override - public CompletableFuture blocksValidate(RequestConfigurator req) { - return blocksValidate(req.configure(BlocksValidateRequest.builder()).build()); - } - @Override public CompletableFuture botsInfo(BotsInfoRequest req) { return executor.execute(BOTS_INFO, toMap(req), () -> methods.botsInfo(req)); diff --git a/slack-api-client/src/main/java/com/slack/api/methods/impl/MethodsClientImpl.java b/slack-api-client/src/main/java/com/slack/api/methods/impl/MethodsClientImpl.java index 9d4303b1c..596726714 100644 --- a/slack-api-client/src/main/java/com/slack/api/methods/impl/MethodsClientImpl.java +++ b/slack-api-client/src/main/java/com/slack/api/methods/impl/MethodsClientImpl.java @@ -58,11 +58,11 @@ import com.slack.api.methods.request.auth.AuthRevokeRequest; import com.slack.api.methods.request.auth.AuthTestRequest; import com.slack.api.methods.request.auth.teams.AuthTeamsListRequest; +import com.slack.api.methods.request.blocks.BlocksValidateRequest; import com.slack.api.methods.request.bookmarks.BookmarksAddRequest; import com.slack.api.methods.request.bookmarks.BookmarksEditRequest; import com.slack.api.methods.request.bookmarks.BookmarksListRequest; import com.slack.api.methods.request.bookmarks.BookmarksRemoveRequest; -import com.slack.api.methods.request.blocks.BlocksValidateRequest; import com.slack.api.methods.request.bots.BotsInfoRequest; import com.slack.api.methods.request.calls.CallsAddRequest; import com.slack.api.methods.request.calls.CallsEndRequest; @@ -211,11 +211,11 @@ import com.slack.api.methods.response.auth.AuthRevokeResponse; import com.slack.api.methods.response.auth.AuthTestResponse; import com.slack.api.methods.response.auth.teams.AuthTeamsListResponse; +import com.slack.api.methods.response.blocks.BlocksValidateResponse; import com.slack.api.methods.response.bookmarks.BookmarksAddResponse; import com.slack.api.methods.response.bookmarks.BookmarksEditResponse; import com.slack.api.methods.response.bookmarks.BookmarksListResponse; import com.slack.api.methods.response.bookmarks.BookmarksRemoveResponse; -import com.slack.api.methods.response.blocks.BlocksValidateResponse; import com.slack.api.methods.response.bots.BotsInfoResponse; import com.slack.api.methods.response.calls.CallsAddResponse; import com.slack.api.methods.response.calls.CallsEndResponse; @@ -1560,6 +1560,16 @@ public AuthTeamsListResponse authTeamsList(RequestConfigurator req) throws IOException, SlackApiException { + return blocksValidate(req.configure(BlocksValidateRequest.builder()).build()); + } + @Override public BookmarksAddResponse bookmarksAdd(BookmarksAddRequest req) throws IOException, SlackApiException { return postFormWithTokenAndParseResponse(toForm(req), Methods.BOOKMARKS_ADD, getToken(req), BookmarksAddResponse.class); @@ -1600,16 +1610,6 @@ public BookmarksRemoveResponse bookmarksRemove(RequestConfigurator req) throws IOException, SlackApiException { - return blocksValidate(req.configure(BlocksValidateRequest.builder()).build()); - } - @Override public BotsInfoResponse botsInfo(BotsInfoRequest req) throws IOException, SlackApiException { this.teamId.ifPresent(currentTeamId -> { diff --git a/slack-api-client/src/test/java/test_locally/api/MethodsTest.java b/slack-api-client/src/test/java/test_locally/api/MethodsTest.java index f3dc32a23..013183e63 100644 --- a/slack-api-client/src/test/java/test_locally/api/MethodsTest.java +++ b/slack-api-client/src/test/java/test_locally/api/MethodsTest.java @@ -20,7 +20,7 @@ public void verifyTheCoverage() { // https://docs.slack.dev/reference/methods // var methodNames = [].slice.call(document.getElementsByClassName('apiReferenceFilterableList__listItemLink')).map(e => e.href.replace("https://docs.slack.dev/reference/methods/", ""));console.log(methodNames.toString());console.log(methodNames.length); // 310 endpoints as of August 14, 2026 - String methods = "admin.analytics.getFile,admin.apps.activities.list,admin.apps.approve,admin.apps.clearResolution,admin.apps.restrict,admin.apps.uninstall,admin.apps.approved.list,admin.apps.config.lookup,admin.apps.config.set,admin.apps.requests.cancel,admin.apps.requests.list,admin.apps.restricted.list,admin.audit.anomaly.allow.getItem,admin.audit.anomaly.allow.updateItem,admin.auth.policy.assignEntities,admin.auth.policy.getEntities,admin.auth.policy.removeEntities,admin.barriers.create,admin.barriers.delete,admin.barriers.list,admin.barriers.update,admin.conversations.archive,admin.conversations.bulkArchive,admin.conversations.bulkDelete,admin.conversations.bulkMove,admin.conversations.convertToPrivate,admin.conversations.convertToPublic,admin.conversations.create,admin.conversations.createForObjects,admin.conversations.delete,admin.conversations.disconnectShared,admin.conversations.getConversationPrefs,admin.conversations.getCustomRetention,admin.conversations.getTeams,admin.conversations.invite,admin.conversations.linkObjects,admin.conversations.lookup,admin.conversations.removeCustomRetention,admin.conversations.rename,admin.conversations.search,admin.conversations.setConversationPrefs,admin.conversations.setCustomRetention,admin.conversations.setTeams,admin.conversations.unarchive,admin.conversations.unlinkObjects,admin.conversations.ekm.listOriginalConnectedChannelInfo,admin.conversations.restrictAccess.addGroup,admin.conversations.restrictAccess.listGroups,admin.conversations.restrictAccess.removeGroup,admin.emoji.add,admin.emoji.addAlias,admin.emoji.list,admin.emoji.remove,admin.emoji.rename,admin.functions.list,admin.functions.permissions.lookup,admin.functions.permissions.set,admin.inviteRequests.approve,admin.inviteRequests.deny,admin.inviteRequests.list,admin.inviteRequests.approved.list,admin.inviteRequests.denied.list,admin.roles.addAssignments,admin.roles.listAssignments,admin.roles.removeAssignments,admin.teams.admins.list,admin.teams.create,admin.teams.list,admin.teams.owners.list,admin.teams.settings.info,admin.teams.settings.setDefaultChannels,admin.teams.settings.setDescription,admin.teams.settings.setDiscoverability,admin.teams.settings.setIcon,admin.teams.settings.setName,admin.usergroups.addChannels,admin.usergroups.addTeams,admin.usergroups.listChannels,admin.usergroups.removeChannels,admin.users.assign,admin.users.getExpiration,admin.users.invite,admin.users.list,admin.users.remove,admin.users.setAdmin,admin.users.setExpiration,admin.users.setOwner,admin.users.setRegular,admin.users.session.clearSettings,admin.users.session.getSettings,admin.users.session.invalidate,admin.users.session.list,admin.users.session.reset,admin.users.session.resetBulk,admin.users.session.setSettings,admin.users.unsupportedVersions.export,admin.workflows.collaborators.add,admin.workflows.collaborators.remove,admin.workflows.permissions.lookup,admin.workflows.search,admin.workflows.unpublish,admin.workflows.triggers.types.permissions.lookup,admin.workflows.triggers.types.permissions.set,api.test,apps.activities.list,apps.auth.external.delete,apps.auth.external.get,apps.connections.open,apps.datastore.bulkDelete,apps.datastore.bulkGet,apps.datastore.bulkPut,apps.datastore.count,apps.datastore.delete,apps.datastore.get,apps.datastore.put,apps.datastore.query,apps.datastore.update,apps.event.authorizations.list,apps.manifest.create,apps.manifest.delete,apps.manifest.export,apps.manifest.update,apps.manifest.validate,apps.uninstall,apps.user.connection.update,assistant.search.context,assistant.threads.setStatus,assistant.threads.setSuggestedPrompts,assistant.threads.setTitle,auth.revoke,auth.test,auth.teams.list,bookmarks.add,bookmarks.edit,bookmarks.list,bookmarks.remove,blocks.validate,bots.info,calls.add,calls.end,calls.info,calls.update,calls.participants.add,calls.participants.remove,canvases.access.delete,canvases.access.set,canvases.create,canvases.delete,canvases.edit,canvases.sections.lookup,channels.mark,chat.appendStream,chat.delete,chat.deleteScheduledMessage,chat.getPermalink,chat.meMessage,chat.postEphemeral,chat.postMessage,chat.scheduleMessage,chat.startStream,chat.stopStream,chat.unfurl,chat.update,chat.scheduledMessages.list,conversations.acceptSharedInvite,conversations.approveSharedInvite,conversations.archive,conversations.close,conversations.create,conversations.declineSharedInvite,conversations.history,conversations.info,conversations.invite,conversations.inviteShared,conversations.join,conversations.kick,conversations.leave,conversations.list,conversations.listConnectInvites,conversations.mark,conversations.members,conversations.open,conversations.rename,conversations.replies,conversations.setPurpose,conversations.setTopic,conversations.unarchive,conversations.canvases.create,conversations.externalInvitePermissions.set,conversations.requestSharedInvite.approve,conversations.requestSharedInvite.deny,conversations.requestSharedInvite.list,dialog.open,dnd.endDnd,dnd.endSnooze,dnd.info,dnd.setSnooze,dnd.teamInfo,emoji.list,files.comments.delete,files.completeUploadExternal,files.delete,files.getUploadURLExternal,files.info,files.list,files.revokePublicURL,files.sharedPublicURL,files.upload,files.remote.add,files.remote.info,files.remote.list,files.remote.remove,files.remote.share,files.remote.update,functions.completeError,functions.completeSuccess,functions.distributions.permissions.add,functions.distributions.permissions.list,functions.distributions.permissions.remove,functions.distributions.permissions.set,functions.workflows.steps.list,functions.workflows.steps.responses.export,groups.mark,migration.exchange,oauth.access,oauth.v2.access,oauth.v2.exchange,openid.connect.token,openid.connect.userInfo,pins.add,pins.list,pins.remove,reactions.add,reactions.get,reactions.list,reactions.remove,reminders.add,reminders.complete,reminders.delete,reminders.info,reminders.list,rtm.connect,rtm.start,search.all,search.files,search.messages,slackLists.access.delete,slackLists.access.set,slackLists.create,slackLists.download.get,slackLists.download.start,slackLists.items.create,slackLists.items.delete,slackLists.items.deleteMultiple,slackLists.items.info,slackLists.items.list,slackLists.items.update,slackLists.update,stars.add,stars.list,stars.remove,team.accessLogs,team.billableInfo,team.info,team.integrationLogs,team.billing.info,team.externalTeams.disconnect,team.externalTeams.list,team.preferences.list,team.profile.get,tooling.tokens.rotate,usergroups.create,usergroups.disable,usergroups.enable,usergroups.list,usergroups.update,usergroups.users.list,usergroups.users.update,users.conversations,users.deletePhoto,users.getPresence,users.identity,users.info,users.list,users.lookupByEmail,users.setActive,users.setPhoto,users.setPresence,users.discoverableContacts.lookup,users.profile.get,users.profile.set,views.open,views.publish,views.push,views.update,workflows.featured.add,workflows.featured.list,workflows.featured.remove,workflows.featured.set,workflows.stepCompleted,workflows.stepFailed,workflows.updateStep,workflows.triggers.permissions.add,workflows.triggers.permissions.list,workflows.triggers.permissions.remove,workflows.triggers.permissions.set,im.list,im.mark,mpim.list,mpim.mark"; + String methods = "admin.analytics.getFile,admin.apps.activities.list,admin.apps.approve,admin.apps.clearResolution,admin.apps.restrict,admin.apps.uninstall,admin.apps.approved.list,admin.apps.config.lookup,admin.apps.config.set,admin.apps.requests.cancel,admin.apps.requests.list,admin.apps.restricted.list,admin.audit.anomaly.allow.getItem,admin.audit.anomaly.allow.updateItem,admin.auth.policy.assignEntities,admin.auth.policy.getEntities,admin.auth.policy.removeEntities,admin.barriers.create,admin.barriers.delete,admin.barriers.list,admin.barriers.update,admin.conversations.archive,admin.conversations.bulkArchive,admin.conversations.bulkDelete,admin.conversations.bulkMove,admin.conversations.convertToPrivate,admin.conversations.convertToPublic,admin.conversations.create,admin.conversations.createForObjects,admin.conversations.delete,admin.conversations.disconnectShared,admin.conversations.getConversationPrefs,admin.conversations.getCustomRetention,admin.conversations.getTeams,admin.conversations.invite,admin.conversations.linkObjects,admin.conversations.lookup,admin.conversations.removeCustomRetention,admin.conversations.rename,admin.conversations.search,admin.conversations.setConversationPrefs,admin.conversations.setCustomRetention,admin.conversations.setTeams,admin.conversations.unarchive,admin.conversations.unlinkObjects,admin.conversations.ekm.listOriginalConnectedChannelInfo,admin.conversations.restrictAccess.addGroup,admin.conversations.restrictAccess.listGroups,admin.conversations.restrictAccess.removeGroup,admin.emoji.add,admin.emoji.addAlias,admin.emoji.list,admin.emoji.remove,admin.emoji.rename,admin.functions.list,admin.functions.permissions.lookup,admin.functions.permissions.set,admin.inviteRequests.approve,admin.inviteRequests.deny,admin.inviteRequests.list,admin.inviteRequests.approved.list,admin.inviteRequests.denied.list,admin.roles.addAssignments,admin.roles.listAssignments,admin.roles.removeAssignments,admin.teams.admins.list,admin.teams.create,admin.teams.list,admin.teams.owners.list,admin.teams.settings.info,admin.teams.settings.setDefaultChannels,admin.teams.settings.setDescription,admin.teams.settings.setDiscoverability,admin.teams.settings.setIcon,admin.teams.settings.setName,admin.usergroups.addChannels,admin.usergroups.addTeams,admin.usergroups.listChannels,admin.usergroups.removeChannels,admin.users.assign,admin.users.getExpiration,admin.users.invite,admin.users.list,admin.users.remove,admin.users.setAdmin,admin.users.setExpiration,admin.users.setOwner,admin.users.setRegular,admin.users.session.clearSettings,admin.users.session.getSettings,admin.users.session.invalidate,admin.users.session.list,admin.users.session.reset,admin.users.session.resetBulk,admin.users.session.setSettings,admin.users.unsupportedVersions.export,admin.workflows.collaborators.add,admin.workflows.collaborators.remove,admin.workflows.permissions.lookup,admin.workflows.search,admin.workflows.unpublish,admin.workflows.triggers.types.permissions.lookup,admin.workflows.triggers.types.permissions.set,api.test,apps.activities.list,apps.auth.external.delete,apps.auth.external.get,apps.connections.open,apps.datastore.bulkDelete,apps.datastore.bulkGet,apps.datastore.bulkPut,apps.datastore.count,apps.datastore.delete,apps.datastore.get,apps.datastore.put,apps.datastore.query,apps.datastore.update,apps.event.authorizations.list,apps.manifest.create,apps.manifest.delete,apps.manifest.export,apps.manifest.update,apps.manifest.validate,apps.uninstall,apps.user.connection.update,assistant.search.context,assistant.threads.setStatus,assistant.threads.setSuggestedPrompts,assistant.threads.setTitle,auth.revoke,auth.test,auth.teams.list,blocks.validate,bookmarks.add,bookmarks.edit,bookmarks.list,bookmarks.remove,bots.info,calls.add,calls.end,calls.info,calls.update,calls.participants.add,calls.participants.remove,canvases.access.delete,canvases.access.set,canvases.create,canvases.delete,canvases.edit,canvases.sections.lookup,channels.mark,chat.appendStream,chat.delete,chat.deleteScheduledMessage,chat.getPermalink,chat.meMessage,chat.postEphemeral,chat.postMessage,chat.scheduleMessage,chat.startStream,chat.stopStream,chat.unfurl,chat.update,chat.scheduledMessages.list,conversations.acceptSharedInvite,conversations.approveSharedInvite,conversations.archive,conversations.close,conversations.create,conversations.declineSharedInvite,conversations.history,conversations.info,conversations.invite,conversations.inviteShared,conversations.join,conversations.kick,conversations.leave,conversations.list,conversations.listConnectInvites,conversations.mark,conversations.members,conversations.open,conversations.rename,conversations.replies,conversations.setPurpose,conversations.setTopic,conversations.unarchive,conversations.canvases.create,conversations.externalInvitePermissions.set,conversations.requestSharedInvite.approve,conversations.requestSharedInvite.deny,conversations.requestSharedInvite.list,dialog.open,dnd.endDnd,dnd.endSnooze,dnd.info,dnd.setSnooze,dnd.teamInfo,emoji.list,files.comments.delete,files.completeUploadExternal,files.delete,files.getUploadURLExternal,files.info,files.list,files.revokePublicURL,files.sharedPublicURL,files.upload,files.remote.add,files.remote.info,files.remote.list,files.remote.remove,files.remote.share,files.remote.update,functions.completeError,functions.completeSuccess,functions.distributions.permissions.add,functions.distributions.permissions.list,functions.distributions.permissions.remove,functions.distributions.permissions.set,functions.workflows.steps.list,functions.workflows.steps.responses.export,groups.mark,migration.exchange,oauth.access,oauth.v2.access,oauth.v2.exchange,openid.connect.token,openid.connect.userInfo,pins.add,pins.list,pins.remove,reactions.add,reactions.get,reactions.list,reactions.remove,reminders.add,reminders.complete,reminders.delete,reminders.info,reminders.list,rtm.connect,rtm.start,search.all,search.files,search.messages,slackLists.access.delete,slackLists.access.set,slackLists.create,slackLists.download.get,slackLists.download.start,slackLists.items.create,slackLists.items.delete,slackLists.items.deleteMultiple,slackLists.items.info,slackLists.items.list,slackLists.items.update,slackLists.update,stars.add,stars.list,stars.remove,team.accessLogs,team.billableInfo,team.info,team.integrationLogs,team.billing.info,team.externalTeams.disconnect,team.externalTeams.list,team.preferences.list,team.profile.get,tooling.tokens.rotate,usergroups.create,usergroups.disable,usergroups.enable,usergroups.list,usergroups.update,usergroups.users.list,usergroups.users.update,users.conversations,users.deletePhoto,users.getPresence,users.identity,users.info,users.list,users.lookupByEmail,users.setActive,users.setPhoto,users.setPresence,users.discoverableContacts.lookup,users.profile.get,users.profile.set,views.open,views.publish,views.push,views.update,workflows.featured.add,workflows.featured.list,workflows.featured.remove,workflows.featured.set,workflows.stepCompleted,workflows.stepFailed,workflows.updateStep,workflows.triggers.permissions.add,workflows.triggers.permissions.list,workflows.triggers.permissions.remove,workflows.triggers.permissions.set,im.list,im.mark,mpim.list,mpim.mark"; final List existingMethods = new ArrayList<>(); for (Field f : Methods.class.getDeclaredFields()) { int modifiers = f.getModifiers(); From 2764f5265a9199071e36ce843fca96e7b31b43ee Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Fri, 14 Aug 2026 18:45:34 -0700 Subject: [PATCH 5/5] fix(methods): treat blocks.validate as unauthenticated blocks.validate requires no token or scopes (https://docs.slack.dev/reference/methods/blocks.validate), so it should not send an Authorization header. Model it like api.test: drop the token field from BlocksValidateRequest (overriding getToken() to return null) and call it through the tokenless postFormAndParseResponse path. The local BlocksTest now asserts the request round-trips (the shared mock answers a tokenless call with not_authed); end-to-end ok/errors[] behavior is covered by the remote blocks_Test. Co-Authored-By: Claude --- .../slack/api/methods/impl/MethodsClientImpl.java | 2 +- .../request/blocks/BlocksValidateRequest.java | 11 +++++++++-- .../java/test_locally/api/methods/BlocksTest.java | 15 ++++++++++----- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/slack-api-client/src/main/java/com/slack/api/methods/impl/MethodsClientImpl.java b/slack-api-client/src/main/java/com/slack/api/methods/impl/MethodsClientImpl.java index 596726714..c527e75ef 100644 --- a/slack-api-client/src/main/java/com/slack/api/methods/impl/MethodsClientImpl.java +++ b/slack-api-client/src/main/java/com/slack/api/methods/impl/MethodsClientImpl.java @@ -1562,7 +1562,7 @@ public AuthTeamsListResponse authTeamsList(RequestConfigurator r - .blocks("[{\"type\":\"section\",\"text\":{\"type\":\"plain_text\",\"text\":\"Hello world\"}}]")).isOk(), is(true)); + assertThat(slack.methods().blocksValidate(r -> r + .blocks("[{\"type\":\"section\",\"text\":{\"type\":\"plain_text\",\"text\":\"Hello world\"}}]")).getError(), is("not_authed")); } @Test public void validate_async() throws Exception { - assertThat(slack.methodsAsync(ValidToken).blocksValidate(r -> r - .blocks("[{\"type\":\"section\",\"text\":{\"type\":\"plain_text\",\"text\":\"Hello world\"}}]")).get().isOk(), is(true)); + assertThat(slack.methodsAsync().blocksValidate(r -> r + .blocks("[{\"type\":\"section\",\"text\":{\"type\":\"plain_text\",\"text\":\"Hello world\"}}]")).get().getError(), is("not_authed")); } }