> ## Documentation Index
> Fetch the complete documentation index at: https://developers.demosmith.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Check a task before creating a demo (free)



## OpenAPI

````yaml /openapi.json post /demos/check
openapi: 3.1.0
info:
  title: Demosmith API
  version: 1.0.0
  description: >-
    Create narrated product demo videos from your own code. You send a URL and a
    task in plain words; an

    agent records a real browser walkthrough of your product, then the video is
    edited, narrated and

    rendered — about 5–20 minutes later you get a video link.


    ## Authentication

    Create an API key on the **Developers** page of the Demosmith app (owners
    and admins, paid plans).

    Send it as a bearer token:


    ```

    Authorization: Bearer dsk_live_…

    ```


    A key acts as the person who created it, inside their organization, and uses
    that plan's minutes.

    Keys are shown once; revoke one from the same page. AI assistants (Claude,
    ChatGPT, Cursor, Claude

    Code) connect through the MCP server at `https://mcp.demosmith.ai/mcp`
    instead.


    ## How a demo runs

    1. Optional: `POST /demos/check` refines your task and asks questions when
    something is unclear. It
       is free and creates nothing.
    2. `POST /demos` creates and starts the demo and returns at once with
    `status: queued`. If the task
       still needs answers you get `422 needs_answers` with a `check_id` and the questions; send the same
       request again with `check_id` and `answers`.
    3. Follow it with **webhooks** (below), or poll `GET /demos/{id}` and wait
    `check_again_in_seconds`
       between requests.
    4. When `status` is `completed`, `video.url` plays the video and
    `video.download_url` downloads it.
       Both expire after 2 hours — fetch the demo again for fresh links.

    Statuses: `queued` → `in_progress` (with `stage`: recording, analyzing,
    narrating, editing,

    rendering) → `completed`, or `failed` / `canceled`. `input_required` means
    the recorder is waiting

    for you (see below).


    ## Logins for the site you record

    Send `site_login: {"username", "password"}` with `POST /demos` (or
    `/demos/check`). It is

    encrypted on arrival, used only by the recorder, never logged and never
    returned. If you send none

    and the recorder reaches a sign-in page, the demo pauses with `status:
    input_required` and an

    `input_request` of kind `login` or `verification_code`. Answer it with

    `POST /demos/{id}/input-requests/{request_id}/answer`, or have a person open
    `answer_url` (the

    demo's page in the app). Answers are single use; an unanswered request
    expires (`expires_at`).


    ## Webhooks

    Register endpoints on the Developers page or with `/webhooks`, or pass
    `callback_url` when you create

    a demo (a callback gets every event except `demo.progress`). Each request is
    a JSON `POST`, signed in

    the [Standard Webhooks](https://www.standardwebhooks.com/) format with your
    organization's signing

    secret (`whsec_…`, on the Developers page):


    ```

    webhook-id: evt_…            # the same on every retry — use it to ignore
    duplicates

    webhook-timestamp: 1767225600

    webhook-signature: v1,<base64 HMAC-SHA256 of "{id}.{timestamp}.{body}">

    ```


    Verify with any Standard Webhooks library, for example in Python:


    ```python

    from standardwebhooks import Webhook

    Webhook(signing_secret).verify(raw_body, headers)

    ```


    Answer with any 2xx within 10 seconds. Failures are retried for about a day
    (30 s, 2 min, 10 min,

    30 min, 1 h, 3 h, 6 h, 12 h). An endpoint that keeps failing for days is
    turned off and the

    organization's admins get an email. `data.demo` is the demo as it is when
    the event is sent.


    ## Errors

    Every error has the same shape: `{"error": {"code", "message",
    "details"?}}`. Codes:

    `invalid_request` 400, `unauthorized` 401, `paid_plan_required` 402,
    `limit_reached` 402 (with

    `details.limit_code`), `forbidden` 403, `not_found` 404, `conflict` 409,
    `gone` 410,

    `needs_answers` / `not_feasible` 422, `rate_limited` 429 (`Retry-After`),
    `unavailable` 503.

    Rate limits: 300/minute requests per key, 20/minute demo checks or
    creations.
  contact:
    name: Demosmith
    url: https://demosmith.ai
servers:
  - url: https://platform.demosmith.ai/v1
security: []
tags:
  - name: Account
  - name: Demos
  - name: Webhooks
  - name: Webhook events
paths:
  /demos/check:
    post:
      tags:
        - Demos
      summary: Check a task before creating a demo (free)
      operationId: checkDemo
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CheckRequest'
            example:
              url: https://cal.com
              task: Show how to book a 30-minute meeting from a public booking page
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CheckResult'
              example:
                status: ready
                check_id: Jq3x9VfT2bLm8RkQ0aZy1w
                questions: []
                warnings: []
                estimate:
                  recording_seconds: 120
                message: null
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Missing or invalid API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '402':
          description: Paid plan required, or a plan limit reached
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          description: Rate limited
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '503':
          description: Temporarily unavailable
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      security:
        - apiKey: []
components:
  schemas:
    CheckRequest:
      type: object
      required:
        - url
        - task
      additionalProperties: false
      properties:
        url:
          type: string
          format: uri
          maxLength: 2048
        task:
          type: string
          minLength: 5
          maxLength: 8000
        check_id:
          type: string
        answers:
          type: array
          items:
            $ref: '#/components/schemas/Answer'
        site_login:
          $ref: '#/components/schemas/SiteLogin'
    CheckResult:
      type: object
      properties:
        status:
          type: string
          enum:
            - ready
            - needs_answers
            - not_feasible
        check_id:
          type: string
          description: Send it back with answers, or with POST /demos. Valid for 1 hour.
        questions:
          type: array
          items:
            $ref: '#/components/schemas/Question'
        warnings:
          type: array
          items:
            type: object
            properties:
              code:
                type: string
              message:
                type: string
              suggestion:
                type:
                  - string
                  - 'null'
        estimate:
          type:
            - object
            - 'null'
          properties:
            recording_seconds:
              type: integer
        message:
          type:
            - string
            - 'null'
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              examples:
                - needs_answers
            message:
              type: string
            details:
              type: object
              additionalProperties: true
    Answer:
      type: object
      required:
        - question_id
        - choice_id
      additionalProperties: false
      properties:
        question_id:
          type: string
        choice_id:
          type: string
        fields:
          type: object
          additionalProperties:
            type: string
    SiteLogin:
      type: object
      required:
        - username
        - password
      additionalProperties: false
      description: >-
        Login for the site being recorded. Encrypted on arrival; never logged or
        returned.
      properties:
        username:
          type: string
          maxLength: 320
        password:
          type: string
          maxLength: 512
          writeOnly: true
    Question:
      type: object
      properties:
        id:
          type: string
          examples:
            - q1
        question:
          type: string
        reason:
          type:
            - string
            - 'null'
        required:
          type: boolean
        kind:
          type: string
          enum:
            - choice
            - login
        choices:
          type: array
          items:
            $ref: '#/components/schemas/Choice'
    Choice:
      type: object
      properties:
        id:
          type: string
          description: '"a", "b", … — or "later" on a login question.'
        text:
          type: string
        is_login:
          type: boolean
        needs_input:
          type: boolean
        input_prompt:
          type:
            - string
            - 'null'
        fields:
          type: array
          items:
            type: object
            properties:
              name:
                type: string
              label:
                type: string
              type:
                type: string
              required:
                type: boolean
  securitySchemes:
    apiKey:
      type: http
      scheme: bearer
      bearerFormat: dsk_live_…
      description: An API key from the Developers page.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.