Voznest Forge

Workspace

WorkspaceProjects

Development

DocsAPI ReferenceSDKsEmbed StudioChangelog
  1. Forge
  2. /Docs

Start here

Getting StartedQuickstartPlatform ConceptsEnvironments

Build

ProjectsIdentityAgentsGatewayCapabilitiesPermissions ReferenceInstallationsLive activity

Commands & interactions

CommandsContext-menu CommandsInteractionsComponentsModals (Forms)Activities (Embedded Apps)

Acting in hubs

MessagesEmbedsEmbeds v2 (Blocks)Embeds v3Incoming WebhooksHub Management APIEvent StreamDelivery

Sign in with Voznest

AccessOpenID Connect

API

APIAuthenticationErrorsRate LimitsSecurity

Publish & operate

App Market & ListingTemplates & SandboxObservability & Team Tools

Tools

SDKsExamplesFAQ & TroubleshootingReference

Acting in hubs

Embeds v2 (Blocks)

Composable message layouts: containers, columns, tabs, pages, charts, tables, countdowns, galleries and controls anywhere.

Classic embeds are one fixed card. Blocks let you build the whole message out of pieces: put a header, live stats and a chart in a tinted container; split it into columns; hide details behind tabs, an accordion or flippable pages; and drop buttons or menus wherever they make sense. Tabs, pages, accordions, spoilers, carousels, image zoom and countdowns run in the member's app — no round trip to your bot, no rate limit spent.

Design and test layouts visually in the Embed Studio: live preview, validation against the real limits, and code you can paste.

New: Embeds v3 adds animated gradient themes (or your own colors), 300+ icons and the hero, features, steps, timeline, quote, cards and rating blocks — on top of everything on this page, in every hub.

Sending blocks

Add a blocks array anywhere you can send embeds: new messages, edits, interaction replies (reply and update, ephemeral included) and webhooks. A message may combine content, embeds, components and blocks. Send blocks: [] in an edit to remove them.

js
await ctx.reply({  blocks: [    {      type: "container",      accent: ["#7c5cff", "#22d3ee"],   // one color or a gradient      tint: true,      blocks: [        { type: "header", eyebrow: "Weekly report", title: "Hub health", subtitle: "Last 7 days" },        { type: "stats", items: [          { label: "Members", value: "1,204", delta: "+38", trend: "up" },          { label: "Messages", value: "9.8k", trend: "flat" },        ] },        { type: "chart", kind: "line", title: "Messages per day", data: [          { label: "Mon", value: 1200 }, { label: "Tue", value: 1480 }, { label: "Wed", value: 1710 },        ] },        { type: "tabs", tabs: [          { label: "Top members", blocks: [{ type: "table",            columns: [{ label: "Member" }, { label: "XP", align: "right" }],            rows: [["Ana", "12,480"], ["Leo", "9,870"]] }] },          { label: "Next event", blocks: [{ type: "countdown", to: "2026-12-31T20:00:00Z", style: "big" }] },        ] },        { type: "section",          blocks: [{ type: "text", content: "Want the full report?" }],          accessory: { type: "button", style: "primary", label: "Open", customId: "report:open" } },      ],    },  ],});
Blocks are for apps and webhooks. Sending them in a channel needs the embedLinks permission (not needed when answering an interaction). Text inside blocks goes through the hub's AutoMod like any message.

Content blocks

typeFieldsNotes
textcontent, size (sm·md·lg·xl), tone, alignMarkdown, mentions and links; up to 4000 chars
headertitle, subtitle, eyebrow, iconUrl, urlA title with an optional small caps line above
imageurl, alt, caption, spoiler, aspect (auto·wide·square·banner)Click to zoom; spoilers blur until clicked
galleryitems[1–10] {url, alt, caption, spoiler}, layout (grid·carousel)Smart grid or swipeable carousel with a lightbox
fieldsitems[1–25] {name, value}, columns (1–3)Like classic embed fields, in a real grid
statsitems[1–6] {label, value, delta, trend (up·down·flat), emoji}KPI cards with colored trends
progressvalue, max (100), label, color, showValue, segments (2–20)Animated bar or segmented meter
tablecolumns[1–6] {label, align}, rows[1–20][cells], stripedEach row needs one cell per column; scrolls on phones
chartkind (bar·line·donut), data[1–24] {label, value, color}, title, unitHover shows values; donut takes up to 8 slices
callouttone (info·success·warning·danger·tip), content, title, emojiHighlighted note
codecontent, language, filenameHighlighted, with a copy button
countdownto (ISO date), label, doneText, style (inline·big)Ticks live on every member's screen
badgesitems[1–12] {label, color, emoji}Colored pills
listitems[1–25] {text, checked, emoji}, style (bullet·number·check)Checklists strike done items
separatorline, spacing (sm·md·lg), style (line·gradient)A divider or spacer; gradient follows the v3 theme
actionscomponents[1–5] (buttons, or one select)Same buttons and menus as components

Layout blocks

typeFieldsNotes
containerblocks[1–30], accent (hex or [hex, hex]), tint, spoiler · v3: theme, gradient, animatedA card with an accent bar (or an animated gradient frame in v3). Top level only. Spoiler blurs the whole card
sectionblocks[1–5], accessory (thumbnail {url} or a button)Text next to an image or a button. Holds text, header, badges, list, progress, countdown and fields
columnscolumns[2–3] {width (1–3), blocks[1–10]}Side by side on wide screens, stacked on phones

Interactive blocks (run in the app)

typeFieldsNotes
tabstabs[2–6] {label, emoji, blocks[1–20]}Switching tabs is instant and private to each member
accordionitems[1–8] {title, emoji, open, blocks[1–20]}Collapsible sections (FAQ, release notes)
pagespages[2–10] {title, blocks[1–20]}A wizard or slideshow with Back / Next and dots

Buttons and menus inside blocks

Put them in an actions block or as a section accessory, at any depth. Clicks reach your app exactly like classic components (an INTERACTION_CREATE with type: "component" and the customId). Answer with update to swap the layout in place — for example to move a member to the next step. customIds must be unique across the whole message (rows and blocks together).

Limits

  • Up to 12 top-level blocks and 80 blocks in total.
  • Nesting up to 4 levels (container → tabs → accordion → content). A container can't be inside another block.
  • Up to 10,000 characters of text across the message, and 25 buttons and menus.
  • Every URL must be http(s); unknown fields are rejected so typos surface immediately.
  • Webhooks can use link buttons only (they can't receive clicks).

Validate without sending

POST https://api.voznest.com/api/v1/blocks/validate with { "blocks": [...] } returns valid, the issues (path and message) and usage against each limit. No authentication; nothing is stored. Handy in CI.

From a webhook

bash
curl -X POST "https://api.voznest.com/api/v1/webhooks/<id>/<token>" \  -H "Content-Type: application/json" \  -d '{"blocks":[{"type":"callout","tone":"success","title":"Deploy finished","content":"**v2.4.0** is live."},       {"type":"actions","components":[{"type":"button","style":"link","label":"Changelog","url":"https://example.com"}]}]}'
PreviousEmbedsNext Embeds v3