Introduction
The Transcript API is a high-performance endpoint that generates and delivers clean channel transcripts for Discord bots — with no HTML overhead, no SDK requirements, and no configuration complexity.
A single authenticated POST request is all it takes. The API fetches the channel history, formats the transcript, and delivers it directly to a channel you designate — all in under 200ms.
Whether you're powering a ticket system, moderation log, or any workflow requiring channel history, this API integrates in minutes and runs reliably in production.
Base URL
Endpoint
There is one endpoint. Send a POST request with a JSON body to generate and deliver a transcript to your specified channel.
The request body must be valid JSON. Set your Content-Type header to application/json on every request.
Parameters
The request body must be valid JSON. Only botToken and channelId are strictly required — all other parameters are optional and have sensible defaults. Parameters are grouped below by purpose.
Core
| Parameter | Type | Status | Description |
|---|---|---|---|
| botToken | string | Required | Your Discord bot token. Used to authenticate with the Discord API and read channel history. Prefix Bot is added automatically if omitted. |
| channelId | string | Required | Snowflake ID of the Discord channel to transcribe. The bot must have Read Message History access to this channel. |
| transcriptChannelId | string | Optional | Snowflake ID of the destination channel where the finished transcript file and embed will be sent. If omitted, the transcript is generated and stored but not delivered to any channel. |
Ticket Identity
| Parameter | Type | Status | Description |
|---|---|---|---|
| ticketCreatorId | string | Optional | Discord user ID of the ticket opener. Populates the embed, badges the user as OWNER in the transcript, and triggers a DM with the transcript file sent directly to them. |
| ownerId | string | Optional | Legacy alias for ticketCreatorId. Ignored if ticketCreatorId is also provided. |
| ticketCloserId | string | Optional | Discord user ID of the staff member who closed the ticket. Shown in the embed's "Closed By" field. |
| ticketId | string | Optional | Your internal ticket number or identifier. Displayed as a labelled field in the embed when provided. |
| claimedBy | string | Optional | Discord user ID of the staff member who claimed the ticket. Appended to the embed as a "Claimed By" field. |
Ticket Meta
| Parameter | Type | Status | Description |
|---|---|---|---|
| ticketType | string | Optional | Category or type of the ticket (e.g. "billing", "appeal", "support"). Shown in the embed's "Ticket Type" field. Default: "Support". |
| supportRoles | array | Optional | Array of Discord role IDs that identify support staff. Members with these roles receive an ADMIN badge in the rendered transcript. |
Transcript Config
| Parameter | Type | Default | Description |
|---|---|---|---|
| includeMessages | boolean | true |
Include message text content in the transcript. Set to false to produce a metadata-only transcript. |
| includeAttachments | boolean | true |
Render file attachments inline. Images and videos are embedded; other files are shown as download links. |
| includeEmbeds | boolean | true |
Render Discord message embeds (author, title, description, fields) inside the transcript. |
| saveImages | boolean | false |
When enabled, image attachments are saved and embedded as data URIs, making the transcript self-contained even if original URLs expire. |
Embed Customization
These fields control the Discord embed sent to your transcript channel. If embedDescription is provided, the embed switches to description-only mode — a single resolved text block, no fields. Without it, a structured fields layout is used automatically.
| Parameter | Type | Default | Description |
|---|---|---|---|
| embedTitle | string | "Ticket Transcript" |
Embed title. Supports placeholders. |
| embedDescription | string | — | Custom embed body text. When set, disables the auto-generated fields layout. Supports placeholders. |
| embedColor | string | "#5865F2" |
Hex color for the embed accent bar (e.g. "#00eeff"). The leading # is optional. |
| embedFooter | string | Guild name | Footer text shown below the embed. Supports placeholders. |
| embedTimestamp | boolean | true |
Attach the current timestamp to the embed footer. |
| embedThumbnail | string | — | URL of an image to display as the embed thumbnail (small image in the top-right corner). |
| embedImage | string | — | URL of a full-width image to display at the bottom of the embed. |
Advanced
| Parameter | Type | Default | Description |
|---|---|---|---|
| timezone | string | "UTC" |
IANA timezone string used to format message timestamps in the HTML (e.g. "America/New_York", "Europe/London"). |
| autoDeleteAfter | number | — | Seconds after which the transcript messages are automatically deleted from Discord. Useful for temporary or private transcripts. |
| customFields | object | — | Arbitrary JSON object attached to the transcript record. Useful for storing metadata specific to your system (e.g. {"tier": "premium", "region": "eu"}). |
Pro Features
| Parameter | Type | Default | Description |
|---|---|---|---|
| showJoinLeave | boolean | false |
Include server join and leave events in the transcript timeline. |
| showEdits | boolean | false |
Show the full edit history for messages that were edited by the author. |
| showDeletes | boolean | false |
Include deleted messages in the transcript (shown with a strikethrough style). |
| generateSummary | boolean | false |
Auto-generate a short summary of the transcript conversation and prepend it to the HTML output. |
| watermark | string | — | Custom watermark text rendered at the bottom of the transcript HTML (e.g. your bot name or server name). |
Example Request
Production-ready examples for every major environment. Copy, replace the placeholder values, and ship.
Example Response
On success, the API returns a 200 OK JSON response confirming the transcript was generated and delivered to your channel.
Error Handling
The API uses standard HTTP status codes. All error responses return a JSON body with an error field containing a human-readable message. For 500 errors a detail field is also included with the underlying exception message.
A required parameter is missing or invalid. The three distinct 400 paths are: botToken absent, channelId absent, or channelId is invalid / the bot cannot access it. A descriptive error message is returned in each case, and the bot also sends the error to your transcriptChannelId if possible.
botToken or channelId is missing, empty, or refers to a channel the bot cannot read.
Your IP or guild has hit the rate limit. Two limits are enforced independently: a 5-second per-IP cooldown and a 5-second per-guild cooldown. The response tells you exactly how many seconds to wait before retrying.
An unexpected condition occurred on the server. This is extremely rare — zero 500 errors have been recorded in production. A detail field is included in the response with the underlying error message. The bot also attempts to send the error to your transcriptChannelId.
Rate Limits
Two independent rate limits protect the API from abuse. Both use a sliding-window mechanism — the cooldown resets from the timestamp of your last request.
| Scope | Limit | Key | Notes |
|---|---|---|---|
| IP | 1 req / 5 s | Caller's IP address | Applied before any parameter validation. Returns 429 with a countdown in seconds. |
| Guild | 1 req / 5 s | Discord guild ID (from channelId) |
Applied after the channel is resolved. Prevents burst usage within the same server. |
Placeholders
Placeholders let you inject live data into embedTitle, embedDescription, and embedFooter. They are resolved at request time using values from the channel, guild, and your request body. Placeholders are case-insensitive.
| Placeholder | Resolves to |
|---|---|
| {ticketOpener} | Discord mention of the ticket creator — <@USER_ID>. Requires ticketCreatorId (or ownerId). |
| {ticketOpenerID} | Raw user ID of the ticket creator. |
| {ticketCloser} | Discord mention of the staff member who closed the ticket. Requires ticketCloserId. |
| {ticketCloserID} | Raw user ID of the ticket closer. |
| {ticketID} | Your ticketId value (e.g. "42"). |
| {ticketChannelID} | Snowflake ID of the transcribed channel. |
| {channelName} | Name of the transcribed channel (e.g. ticket-0042). Also aliased as {channel}. |
| {serverName} | Name of the Discord guild. Also aliased as {server}. |
| {ticketType} | Value of ticketType (or panelName). Defaults to "Support". |
| {claimedBy} | Discord mention of the staff member who claimed the ticket. Requires claimedBy. |
| {claimedByID} | Raw user ID of the staff member who claimed the ticket. |
| {users} | Comma-separated Discord mentions of every unique non-bot user who sent a message in the transcript. |
| {messageCount} | Total number of messages included in the transcript. |
| {closedAt} | Discord long-form timestamp of when the transcript was generated — e.g. Monday, 7 April 2026 14:30:00. |
| {closedAtR} | Discord relative timestamp — e.g. 2 minutes ago. |
{ticketCloser} without ticketCloserId) resolve to "Unknown" rather than throwing an error.