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

EndpointMethodPurpose
/oauth/authorizeGETUser sign-in and consent (Authorization Code + PKCE)
/oauth/tokenPOSTExchange authorization code / refresh tokens
/oauth/userinfoGETIdentity of the connected account (Zapier connection test)
/mcp/POSTAll operations, as MCP JSON-RPC 2.0 (initialize, notifications/initialized, tools/call)
/.well-known/oauth-authorization-serverGETOAuth server metadata (RFC 8414)
/.well-known/oauth-protected-resourceGETProtected-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 parameterRequiredDescription
response_typeyesMust be code.
client_idyesThe registered client identifier.
redirect_uriyesMust match a URI registered for the client.
stateyesOpaque CSRF value, echoed back on redirect.
code_challengeyesPKCE challenge, 43–128 characters.
code_challenge_methodyesMust be S256 (the only supported method).
scopenoSpace-separated scopes (see below). Defaults to presentation:read presentation:write.
resourcenoRFC 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.

FieldGrantDescription
grant_typebothauthorization_code or refresh_token.
codeauthorization_codeThe code from the redirect.
redirect_uriauthorization_codeExact match of the URI used at /oauth/authorize.
code_verifierauthorization_codePKCE verifier for the challenge.
refresh_tokenrefresh_tokenThe most recently issued refresh token.
client_idbothThe 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

ScopeGrants
presentation:readList and view presentations; create export links.
presentation:writeCreate and edit presentations; share them.
agent:runRun 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:

  1. initialize — negotiate the protocol version (the integration uses 2025-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"}}}
  2. notifications/initialized — a notification (no id); the server replies 202. This and later requests include the header MCP-Protocol-Version: <negotiated version>.
  3. 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:

FieldTypeDescription
idstring (UUID)Presentation identifier.
filenamestring | nullThe presentation title.
visibilitystringe.g. private.
slide_countinteger | nullNumber of slides.
thumbnail_uristring | nullFirst-slide thumbnail URL.
view_urlstringLink to open the deck in Brightdeck.
created_dt, modified_dtstring | nullCreation / last-modified timestamps.
show_page_numbersboolean | nullWhether slide numbers are shown.
current_user_rolestring | nullCaller’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.

ArgumentTypeRequiredDescription
skipintegernoOffset for paging. ≥ 0, default 0.
limitintegernoPage 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.

ArgumentTypeRequiredDescription
presentation_idstring (UUID)yesThe 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.

ArgumentTypeRequiredDescription
promptstringyesNatural-language brief, 1–4,000 characters.
modestringnoThe integration always sends yolo (also the server default).
num_slidesintegerno1–50. Plan caps apply: Free 10, Plus 15, Pro 25, Ultra 50. Omit to let the AI decide.
presentation_stylestringnoauto, corporate, elegant, or creative.
content_densitystringnoconcise, 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.

ArgumentTypeRequiredDescription
presentation_idstring (UUID)yesThe presentation whose generation run to check.
Result fieldTypeDescription
presentation_idstringEcho of the input.
view_urlstringLink to the deck.
statusstringworking, completed, failed, or cancelled.
stagestringFiner-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_totalintegerSlides finished vs. planned.
thumbnail_urlstring | nullTime-limited link to the first-slide thumbnail.
slides_failedinteger | nullSlides that failed to render (on terminal states).
errorstring | nullFailure detail when status is failed.
agent_instructionsstring | nullSuggested 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.

ArgumentTypeRequiredDescription
presentation_idstring (UUID)yesThe 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.

ArgumentTypeRequiredDescription
presentation_idstring (UUID)yesThe presentation to share.
emailstringyesRecipient email address (3–320 characters).
rolestringnoviewer (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 GETdo 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.ai request — access token missing, invalid, or expired. Refresh the token and retry (Zapier does this automatically).
  • JSON-RPC error object — malformed request or protocol-level failure.
  • Tool errorsresult.isError: true with message text [code] Human-readable message:
CodeMeaning
auth.invalid_tokenThe bearer token could not be resolved to a user.
auth.scope_requiredThe token lacks a scope the tool requires.
validation.requiredA required argument is missing or empty.
validation.out_of_rangeA numeric or length constraint was violated.
validation.invalid_format / validation.invalidAn argument is malformed (e.g. not a UUID).
validation.invalid_valueA value outside the allowed set (e.g. an unknown role).
presentation.not_foundNo accessible presentation with that ID.
presentation.insufficient_permissionsThe operation requires a higher role on the presentation.
presentation.file_missingThe presentation has no stored file to export.
presentation.download_url_failed / presentation.pdf_generation_failed / presentation.pdf_download_url_failedExport or link generation failed; retry the tool.
task.not_foundNo AI generation run exists for the presentation.
permission.cannot_grant_roleThe 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