Commands & interactions
Modals (Forms)
Ask members for text input with a form opened from a command or a button.
A modal is a small form your agent opens in response to an interaction. The member fills it in inside Voznest and submits; your agent receives a new interaction of type modal_submit with the values. Voznest enforces your field rules before it reaches you.
ts
// 1. A command (or button) opens a form — this must be the FIRST answer.await answer(d, { type: "modal", data: { modal: { customId: "feedback", title: "Send feedback", // ≤ 45 characters fields: [ // 1 to 5 fields { customId: "topic", label: "Topic", style: "short", placeholder: "Billing, bugs…", maxLength: 80 }, { customId: "details", label: "Details", style: "paragraph", minLength: 10, maxLength: 2000 }, { customId: "contact", label: "How can we reach you?", style: "short", required: false }, ], }, },});// 2. When the member submits, you get a NEW interaction of type "modal_submit".gateway.on("event", async ({ t, d }) => { if (t !== "INTERACTION_CREATE" || d.type !== "modal_submit" || d.data.customId !== "feedback") return; const field = (id) => d.data.fields.find((f) => f.customId === id)?.value ?? ""; await saveFeedback({ topic: field("topic"), details: field("details"), contact: field("contact"), user: d.user.id }); await answer(d, { type: "reply", data: { content: "Thanks! We read every message.", ephemeral: true } });});Fields
| Property | Rules |
|---|---|
customId | 1–100 characters, unique within the form |
label | 1–45 characters |
style | short (one line) or paragraph (multi-line) |
required | Default true |
minLength / maxLength | 0–4000 / 1–4000 |
placeholder | ≤ 100 characters |
value | Pre-filled text, ≤ 4000 |
Rules
- A form must be the first answer to an interaction (409 after a reply or defer). A
modal_submitcan't open another form — reply instead. - Forms expire 15 minutes after opening and can be submitted once.
- Only the member who opened it can submit it, in the same channel.
- The title is ≤ 45 characters; 1–5 fields.