API Reference
Brightdeck API Reference
Every endpoint used by the Brightdeck integration for Zapier. Base URL https://api.brightdeck.ai.
The Zapier integration uses the Brightdeck MCP API — the same API behind Brightdeck’s Claude, ChatGPT, and n8n integrations. It consists of an OAuth 2.1 authorization server and a Model Context Protocol (Streamable HTTP) endpoint that exposes tools as JSON-RPC 2.0 calls over HTTPS. There is no separate REST surface: every trigger, action, and search in the Zapier app is one MCP tool call.
1. Endpoint summary
| Endpoint | Method | Purpose |
|---|---|---|
/oauth/authorize | GET | User sign-in and consent (Authorization Code + PKCE) |
/oauth/token | POST | Exchange authorization code / refresh tokens |
/oauth/userinfo | GET | Identity of the connected account (Zapier connection test) |
/mcp/ | POST | All operations, as MCP JSON-RPC 2.0 (initialize, notifications/initialized, tools/call) |
/.well-known/oauth-authorization-server | GET | OAuth server metadata (RFC 8414) |
/.well-known/oauth-protected-resource | GET | Protected-resource metadata (RFC 9728) |
Export downloads additionally use time-limited signed URLs on Google Cloud Storage — see §5.
2. Authentication (OAuth 2.1)
The integration is a public OAuth client (no client secret) using the Authorization Code flow with PKCE (S256, mandatory). Access tokens are Bearer tokens sent as Authorization: Bearer <token> on every API request.
GET /oauth/authorize
| Query parameter | Required | Description |
|---|---|---|
response_type | yes | Must be code. |
client_id | yes | The registered client identifier. |
redirect_uri | yes | Must match a URI registered for the client. |
state | yes | Opaque CSRF value, echoed back on redirect. |
code_challenge | yes | PKCE challenge, 43–128 characters. |
code_challenge_method | yes | Must be S256 (the only supported method). |
scope | no | Space-separated scopes (see below). Defaults to presentation:read presentation:write. |
resource | no | RFC 8707 target resource; must be https://api.brightdeck.ai/mcp when present. |
Renders a hosted Brightdeck sign-in and consent page. On success the browser is redirected to redirect_uri?code=<code>&state=<state>. Authorization codes are single-use and expire after 5 minutes.
POST /oauth/token
Body is application/x-www-form-urlencoded. Public clients authenticate with a form-encoded client_id and no secret.
| Field | Grant | Description |
|---|---|---|
grant_type | both | authorization_code or refresh_token. |
code | authorization_code | The code from the redirect. |
redirect_uri | authorization_code | Exact match of the URI used at /oauth/authorize. |
code_verifier | authorization_code | PKCE verifier for the challenge. |
refresh_token | refresh_token | The most recently issued refresh token. |
client_id | both | The client identifier. |
Success response (both grants):
{
"access_token": "<bearer token>",
"token_type": "Bearer",
"expires_in": 600,
"refresh_token": "<new refresh token>",
"scope": "presentation:read presentation:write agent:run"
}
- Access tokens live 10 minutes (
expires_in: 600). - Refresh tokens rotate on every refresh — always store the newly returned
refresh_token. Unused refresh tokens expire after 30 days. Reusing an already-consumed refresh token revokes the grant, requiring the user to reconnect. - Failures return HTTP 400 with a JSON body
{"code": "oauth.invalid_grant", "message": "..."}(codes:oauth.invalid_request,oauth.invalid_grant,oauth.invalid_scope,oauth.unsupported_grant,oauth.invalid_client).
GET /oauth/userinfo
Bearer-authenticated identity probe; accepts any valid access token regardless of scope. Zapier uses it as the connection test and account label.
{ "sub": "0198f2f3-5a6b-7c8d-9e0f-112233445566", "email": "ada@example.com", "name": "Ada Lovelace" }
Returns 401 with a WWW-Authenticate: Bearer header when the token is missing, invalid, or expired. Any HTTP 401 from the API means the access token should be refreshed and the request retried — the Zapier platform does this automatically.
Scopes
| Scope | Grants |
|---|---|
presentation:read | List and view presentations; create export links. |
presentation:write | Create and edit presentations; share them. |
agent:run | Run AI deck generation and check its status. |
The Zapier integration requests all three.
3. Calling tools (MCP over HTTPS)
All operations are JSON-RPC 2.0 messages POSTed to https://api.brightdeck.ai/mcp/ with headers:
Authorization: Bearer <access token> Content-Type: application/json Accept: application/json, text/event-stream
The server is stateless: each request is self-contained, no session ID is issued, and no session termination is required. A tool invocation is this sequence:
initialize— negotiate the protocol version (the integration uses2025-06-18; the server echoes it when supported):POST /mcp/ {"jsonrpc": "2.0", "id": 1, "method": "initialize", "params": {"protocolVersion": "2025-06-18", "capabilities": {}, "clientInfo": {"name": "zapier-brightdeck", "version": "1.0.1"}}}notifications/initialized— a notification (noid); the server replies202. This and later requests include the headerMCP-Protocol-Version: <negotiated version>.tools/call— the actual operation:POST /mcp/ {"jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": {"name": "deck_create_presentation", "arguments": {"prompt": "A 10-slide investor update for Q3", "mode": "yolo"}}}
Responses are either application/json or a text/event-stream body whose single event: message frame carries the same JSON-RPC response. A successful tool result looks like:
{"jsonrpc": "2.0", "id": 2,
"result": {
"content": [{"type": "text", "text": "<human-readable summary>"}],
"structuredContent": { ... } // typed payload, documented per tool below
}}
Tool failures set result.isError: true with the message text [error.code] Human-readable message — see §6 for the codes. Both /mcp and /mcp/ are accepted.
4. Tools
All fields below describe each tool’s arguments and its structuredContent result. Timestamps are ISO 8601 with timezone offset. A presentation’s title is its filename field.
The Presentation object
Returned by the list, get, and find operations:
| Field | Type | Description |
|---|---|---|
id | string (UUID) | Presentation identifier. |
filename | string | null | The presentation title. |
visibility | string | e.g. private. |
slide_count | integer | null | Number of slides. |
thumbnail_uri | string | null | First-slide thumbnail URL. |
view_url | string | Link to open the deck in Brightdeck. |
created_dt, modified_dt | string | null | Creation / last-modified timestamps. |
show_page_numbers | boolean | null | Whether slide numbers are shown. |
current_user_role | string | null | Caller’s role: owner, admin, editor, commenter, or viewer. |
deck_list_presentations
Lists the caller’s presentations, newest first. Backs the New Presentation trigger, the presentation dropdowns, and title search in Find Presentation. Scope: presentation:read.
| Argument | Type | Required | Description |
|---|---|---|---|
skip | integer | no | Offset for paging. ≥ 0, default 0. |
limit | integer | no | Page size, 1–50 (default 25). |
Result: items (array of Presentation objects), total (integer), skip, limit. Errors: validation.out_of_range.
deck_get_presentation
Fetches one presentation the caller can access. Backs Find Presentation ID lookup. Scope: presentation:read.
| Argument | Type | Required | Description |
|---|---|---|---|
presentation_id | string (UUID) | yes | The presentation to fetch. |
Result: a Presentation object. Errors: validation.invalid_format, presentation.not_found.
deck_create_presentation
Starts AI generation of a new deck. Backs Create AI Presentation. Scopes: agent:run and presentation:write. The integration always sends mode: "yolo" (fully automatic generation): the call returns within seconds while slides continue building in the background — poll deck_get_task_status for completion.
| Argument | Type | Required | Description |
|---|---|---|---|
prompt | string | yes | Natural-language brief, 1–4,000 characters. |
mode | string | no | The integration always sends yolo (also the server default). |
num_slides | integer | no | 1–50. Plan caps apply: Free 10, Plus 15, Pro 25, Ultra 50. Omit to let the AI decide. |
presentation_style | string | no | auto, corporate, elegant, or creative. |
content_density | string | no | concise, light, normal, dense, or extra_dense (≈3–9 key points per slide). |
Result:
{
"presentation_id": "0198f2f3-5a6b-7c8d-9e0f-112233445566",
"view_url": "https://brightdeck.ai/presentations/0198f2f3-...?ai=1",
"stage": "generating",
"agent_instructions": "Generation started in the background. ..."
}
Plan-limit refusals are returned as a successful payload with stage: "upgrade_required", a human-readable error, an error_code (billing.quota_exhausted — monthly generation quota used up — or billing.plan_limit, with slide_clamp_info: {requested, cap}), and no presentation_id (nothing was created). The Zapier integration converts these into step errors. Errors: validation.required, validation.out_of_range.
deck_get_task_status
Reports the live state of the AI generation run for a presentation. Backs Get Generation Status. Scope: agent:run.
| Argument | Type | Required | Description |
|---|---|---|---|
presentation_id | string (UUID) | yes | The presentation whose generation run to check. |
| Result field | Type | Description |
|---|---|---|
presentation_id | string | Echo of the input. |
view_url | string | Link to the deck. |
status | string | working, completed, failed, or cancelled. |
stage | string | Finer-grained phase. For runs created by this integration: generating, then completed / failed / cancelled. (Interactive runs started elsewhere can also report working, awaiting_answers, awaiting_plan_approval.) |
progress_current, progress_total | integer | Slides finished vs. planned. |
thumbnail_url | string | null | Time-limited link to the first-slide thumbnail. |
slides_failed | integer | null | Slides that failed to render (on terminal states). |
error | string | null | Failure detail when status is failed. |
agent_instructions | string | null | Suggested next step. |
Errors: validation.invalid (malformed UUID), task.not_found (no generation run exists for this presentation — the Zapier search treats this as “no match”).
deck_export_pptx_url / deck_export_pdf_url
Produces a downloadable PPTX or PDF of a presentation and returns a signed link. Backs Export PPTX / Export PDF. Scope: presentation:read; additionally the caller must hold an editor, admin, or owner role on the presentation.
| Argument | Type | Required | Description |
|---|---|---|---|
presentation_id | string (UUID) | yes | The presentation to export. |
Result:
{
"download_url": "https://storage.googleapis.com/...&X-Goog-Signature=...",
"filename": "Q3 Investor Update.pptx",
"expires_at": "2026-08-12T18:03:21.512000+00:00",
"file_size": 2481152
}
download_url expires 60 minutes after issue; file_size is in bytes and may be null. Errors: validation.invalid_format, presentation.not_found, presentation.insufficient_permissions, presentation.file_missing, presentation.download_url_failed; PDF only: presentation.pdf_generation_failed, presentation.pdf_download_url_failed.
deck_share_presentation
Shares a presentation with a person by email. Backs Share Presentation. Scope: presentation:write; the caller must hold an editor-or-higher role, and role grants respect the hierarchy — editors can grant up to editor; admin and owner grants require ownership.
| Argument | Type | Required | Description |
|---|---|---|---|
presentation_id | string (UUID) | yes | The presentation to share. |
email | string | yes | Recipient email address (3–320 characters). |
role | string | no | viewer (integration default), commenter, editor, admin, or owner. |
Result: status — one of invitation_sent (recipient has no Brightdeck account yet; the role is granted on signup, with invitation_id set), permission_created (existing user granted access, with a permission summary), or already_has_access (idempotent no-op; the existing role is never changed) — plus email and role. Errors: validation.invalid_format, validation.invalid_value, presentation.not_found, presentation.insufficient_permissions, permission.cannot_grant_role.
5. Downloading export files
The download_url from the export tools is a signed Google Cloud Storage URL. Fetch it with a plain unauthenticated GET — do not send an Authorization header (GCS rejects signed-URL requests that carry one). Links expire 60 minutes after issue; an expired link returns an error status and a new one can be minted by re-running the export tool. The Zapier integration downloads the file at Zap run time and passes it downstream as a file object.
6. Errors
Three layers, in the order a client encounters them:
- HTTP 401 on any
api.brightdeck.airequest — access token missing, invalid, or expired. Refresh the token and retry (Zapier does this automatically). - JSON-RPC
errorobject — malformed request or protocol-level failure. - Tool errors —
result.isError: truewith message text[code] Human-readable message:
| Code | Meaning |
|---|---|
auth.invalid_token | The bearer token could not be resolved to a user. |
auth.scope_required | The token lacks a scope the tool requires. |
validation.required | A required argument is missing or empty. |
validation.out_of_range | A numeric or length constraint was violated. |
validation.invalid_format / validation.invalid | An argument is malformed (e.g. not a UUID). |
validation.invalid_value | A value outside the allowed set (e.g. an unknown role). |
presentation.not_found | No accessible presentation with that ID. |
presentation.insufficient_permissions | The operation requires a higher role on the presentation. |
presentation.file_missing | The presentation has no stored file to export. |
presentation.download_url_failed / presentation.pdf_generation_failed / presentation.pdf_download_url_failed | Export or link generation failed; retry the tool. |
task.not_found | No AI generation run exists for the presentation. |
permission.cannot_grant_role | The caller’s role cannot grant the requested role. |
Billing refusals are not tool errors. deck_create_presentation reports plan limits inside a successful payload (stage: "upgrade_required" with error_code billing.quota_exhausted or billing.plan_limit) so that agent clients can relay them; the Zapier integration converts them into failed Zap steps with the billing message.
Full MCP server documentation: github.com/brightdeck/mcp · Support: support@brightdeck.ai