Tutorializer for developers

Drive tutorial video production from your own code: a REST API with scoped keys and per-key rate limits over your projects, tutorials, rendered videos and synthesized voice-overs, and signed webhooks when something changes.

AI connector

Connect Tutorializer to Claude, ChatGPT and MCP clients

Tutorializer provides one hosted Model Context Protocol endpoint for AI assistants. It uses OAuth, so every person signs in with their own Tutorializer account and can only reach projects in organizations where they have a live role.

Ask an assistant to inspect projects, tutorial definitions, rendered videos and voiceover segments; audit locale and device coverage; or show the interactive project and tutorial cards. Write tools can create a project, maintain pronunciation rules, or delete one speech or video.

{
  "mcpServers": {
    "tutorializer": {
      "type": "http",
      "url": "https://mcp.tutorializer.com/mcp"
    }
  }
}

Use the production URL above in any client that accepts a remote Streamable HTTP MCP server. OAuth discovery, dynamic client registration and PKCE are handled during connection; do not paste an API key into the MCP configuration.

Read tools use the tutorializer:read scope. State-changing tools use tutorializer:write and declare whether they are destructive and idempotent so compatible hosts can request approval. Deletion removes stored media, so review the exact target before approving it. AI speech and video generation remain in the Tutorializer dashboard and publishing CLI rather than this public connector.

The connector returns bounded projections rather than raw database documents. It never exposes organization ownership fields, vendor dictionary handles, speech alignment arrays, credentials or tokens.

API keys

Get a key and authenticate

The Tutorializer REST API lets your own backend work with the same content the dashboard does: the projects you record tutorials for, the tutorials themselves, the videos rendered from them and the speech clips their voice-overs are synthesized from.

Open the Tutorializer dashboard and create an API key under API keys. The secret is shown when the key is created and is never returned by the endpoints that list or read keys — an organization admin can reveal it again from the dashboard, but only after re-entering their password. A key belongs to a single organization, so the organization is implied by the key and never has to be sent.

Authenticate every request with HTTP Basic auth carrying only the key secret, base64-encoded, in the Authorization header.

# The Authorization header is HTTP Basic auth carrying only the key secret,
# with no username and no colon.
Authorization: Basic $(printf %s YOUR_API_KEY_SECRET | base64)

Every endpoint lives under https://api.tutorializer.com. Requests made with a key are rate limited per key; going over the limit returns 429.

Quick start

Your first three calls

List your projects, read the tutorials of one of them, then read the videos rendered for a single tutorial.

# List the projects of your organization
curl https://api.tutorializer.com/api/projects \
  -H "Authorization: Basic $(printf %s YOUR_API_KEY_SECRET | base64)"

# List the tutorials of one of those projects
curl "https://api.tutorializer.com/api/tutorials?projectId=PROJECT_ID" \
  -H "Authorization: Basic $(printf %s YOUR_API_KEY_SECRET | base64)"

# List the rendered videos of a single tutorial
curl "https://api.tutorializer.com/api/videos?projectId=PROJECT_ID&tutorialId=TUTORIAL_ID" \
  -H "Authorization: Basic $(printf %s YOUR_API_KEY_SECRET | base64)"

Browse the full API reference — every endpoint with its parameters, request body, responses and required scope.

CLI

Command-line interface

The same projects, tutorials, rendered videos and voiceover speeches are available from your terminal through the tutorializer CLI. Install it globally with npm, or run it ad hoc with npx.

Authentication is one command: tutorializer login opens your browser to sign in to your Tutorializer account and stores a session for later commands — no API key to paste.

# Install once, globally
npm install -g tutorializer
# or run it ad hoc without installing
npx tutorializer --help

# Log in — opens your browser to sign in and stores a session
tutorializer login

# List the projects of your organization
tutorializer projects list

# List the videos rendered for one of them
tutorializer videos list --projectId PROJECT_ID

# Inspect a voiceover speech, then fix how a word is pronounced
tutorializer speeches read SPEECH_ID
tutorializer projects pronunciation add "Acme" "ˈækmi" --projectId PROJECT_ID

The CLI is open source at github.com/tutorializer/cli and published as tutorializer on npm. Run any command with --help to see its options.

Agent Skills

Teach your coding agent Tutorializer

Tutorializer ships Agent Skills — guides following the agentskills.io standard that teach coding agents how to audit and maintain your tutorial library with the tutorializer CLI and the MCP connector, instead of guessing at commands and tools.

# Install the Tutorializer skills into your coding agent
npx skills add tutorializer/skills

One command installs the skills into Claude Code, Cursor, Codex, Gemini CLI and any other agent that follows the Skills standard. The CLI also bundles the same guides, version-matched to the commands it ships: tutorializer skills get <name> prints one on demand.

The skills are open source at github.com/tutorializer/skills. Claude users can also install the Tutorializer Claude plugin, which bundles the connector together with the skills: github.com/tutorializer/claude-plugin.

Scopes

Least privilege by default

Each key carries a list of scopes, so an integration that only needs to download your finished videos never gets the ability to change them — or to spend speech-synthesis credits. New keys start read-only; widen them explicitly in the dashboard. A request whose key is missing the scope an endpoint requires is refused with 403.

  • projects:readList the projects of your organization and read a single project.
  • projects:writeCreate, update and delete projects.
  • tutorials:readRead a project's tutorials and a single tutorial.
  • tutorials:writeCreate, update and delete tutorials.
  • videos:readRead the rendered videos of a project or a tutorial.
  • videos:writeCreate, update and delete videos.
  • speeches:readRead the synthesized speech clips of a project.
  • speeches:writeSynthesize new speech clips, and update or delete existing ones.

Reading a single project, tutorial, video or speech that belongs to another organization answers 404 rather than 403, so an id cannot be probed for existence. Users, roles, invites, preferences and billing are dashboard-only and no key reaches them.

Webhooks

Signed webhooks

Add a webhook subscription to a project in the dashboard and Tutorializer POSTs the events you picked to your server as they happen. Subscriptions are managed with an operator session, not with an API key.

  • project.createdA project was created.
  • project.updatedA project was edited.
  • project.deletedA project was deleted.
  • tutorial.createdA tutorial was created.
  • tutorial.updatedA tutorial was edited.
  • tutorial.deletedA tutorial was deleted.
  • video.createdA video was added to a tutorial.
  • video.updatedA video was edited.
  • video.deletedA video was deleted.
  • speech.createdA speech clip was synthesized.
  • speech.updatedA speech clip was edited.
  • speech.deletedA speech clip was deleted.
POST https://your-server.com/tutorializer-webhook
X-Tutorializer-Event: video.created
X-Tutorializer-Signature: t=1719000000,v1=<hmac-sha256 hex>
Content-Type: application/json

{
  "event": "video.created",
  "timestamp": 1719000000,
  "data": { "...": "..." }
}

Verify the signature

Every delivery carries an X-Tutorializer-Signature header of the form t=timestamp,v1=signature, where the signature is an HMAC-SHA256 of timestamp.body keyed by the subscription secret shown to you once when the subscription was created. Recompute it over the raw body and compare before trusting the payload.

import crypto from 'node:crypto'

// body must be the RAW request body, byte for byte
function verify(header, body, secret) {
  const [t, v1] = (header || '').split(',').map(part => part.split('=')[1])
  if (!t || !v1) return false

  const expected = crypto
    .createHmac('sha256', secret)
    .update(`${t}.${body}`)
    .digest('hex')

  // timingSafeEqual throws on a length mismatch, so a malformed signature
  // has to be rejected before the comparison rather than by it.
  if (v1.length !== expected.length) return false

  return crypto.timingSafeEqual(Buffer.from(v1), Buffer.from(expected))
}

Delivery is one best-effort attempt with a five second timeout and no retries, so respond 2xx quickly and do the work asynchronously. An endpoint that fails twenty times in a row is disabled automatically and has to be re-enabled in the dashboard.

Start building