---
openapi: 3.0.1
info:
  title: Storydoc API V2
  description: |-
    # Overview
    The Storydoc API V2 provides capabilities for automating Storydoc version creation and management. Create personalized versions of your Storydoc templates with custom data, password protection, and gated content.

    ## Key Features
    - **Version Management**: Create and update personalized versions of your Storydoc templates
    - **Dynamic Variables**: Support for text, numbers, links, dates, arrays, and logo variables
    - **Access Control**: Password protection and gated content forms

    ## Rate Limits
    **Version Endpoints**: 150 requests per minute per IP address

    **Rate Limit Headers**: Every response includes the following headers to help you monitor usage:
    - `x-rate-limit-counter`: Current number of requests made
    - `x-rate-limit-maximum`: Maximum allowed requests per minute

    **Rate Limit Exceeded**: When the limit is exceeded, you'll receive a 429 status code with the error message "Too many requests". Wait for the rate limit window to reset before making additional requests.
  contact:
    email: support@storydoc.com
  version: 2.1.0
tags:
- name: versions
  description: Manage story versions
- name: account
  description: Account/Organization information
- name: stories
  description: Manage and retrieve stories
- name: analytics
  description: Query engagement analytics
security:
- bearerAuth: []
servers:
- url: https://api.storydoc.com
  description: Production API server
paths:
  "/v2/versions":
    post:
      tags:
      - versions
      summary: Create a new story version
      description: Creates a personalized version of an existing story template with
        custom data. Each version gets a unique URL and can be tracked independently.
      operationId: createStoryVersion
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/CreateVersionRequest"
            examples:
              simple:
                summary: 1. Simple Version
                description: Basic personalized version with just the required fields
                value:
                  storyId: 61b1e50223b713000a41ca74
                  senderEmail: sender@company.com
                  data:
                    title: Sales Presentation for ACME Corp
                    company: ACME Corporation
                    first_name: John
                    last_name: Doe
              withAutomatedLogo:
                summary: 2. Automated Logo Generation
                description: Automatically fetch and apply company logos based on
                  domain
                value:
                  storyId: 61b1e50223b713000a41ca74
                  senderEmail: sender@company.com
                  data:
                    title: Partnership Proposal
                    company: ACME Corporation
                    first_name: John
                    last_name: Doe
                    partner_logo:
                      theme: dark
                      domain: microsoft.com
              withExpiry:
                summary: 3. Time-Limited Version
                description: Version that automatically expires after 30 days
                value:
                  storyId: 61b1e50223b713000a41ca74
                  senderEmail: sender@company.com
                  daysToExpire: 30
                  data:
                    title: Sales Presentation for ACME Corp
                    company: ACME Corporation
                    first_name: John
                    last_name: Doe
              withPassword:
                summary: 4. Password Protected
                description: Secure version requiring password access
                value:
                  storyId: 61b1e50223b713000a41ca74
                  senderEmail: sender@company.com
                  data:
                    title: Sales Presentation for ACME Corp
                    company: ACME Corporation
                    first_name: John
                    last_name: Doe
                    password: SecurePass123
              withGatedContent:
                summary: 5. Lead Capture Form
                description: Collect visitor information before showing content
                value:
                  storyId: 61b1e50223b713000a41ca74
                  senderEmail: sender@company.com
                  data:
                    title: Product Demo - Lead Generation
                    company: ACME Corporation
                    offer: Free 30-day trial included
                    gatedContent:
                      gatedContent: true
                      name: true
                      nameRequired: true
                      logo: true
                      logoSRC: https://www.storydoc.com/assets/images/branding/og-storydoc.gif
                      title: Get instant access to our product demo
              withArrayOfObjects:
                summary: 6. Dynamic Data Lists
                description: Version with product catalogs, pricing tables, or team
                  rosters
                value:
                  storyId: 61b1e50223b713000a41ca74
                  senderEmail: sender@company.com
                  data:
                    title: 2025 Product Catalog
                    company: ACME Corporation
                    launch_date: January 2025
                    products:
                    - name: Enterprise Suite
                      price: 15000
                      custom_field1: 24/7 Support
                    - name: Professional Plan
                      price: 3000
                      custom_field1: Business Hours Support
                    - name: Starter Package
                      price: 500
                      custom_field1: Email Support
                    team_contacts:
                    - name: Sarah Johnson
                      role: Sales Director
                      email: sarah@acme.com
                    - name: Mike Chen
                      role: Product Manager
                      email: mike@acme.com
              withPreviewImage:
                summary: 7. Set Thumbnail
                description: Set a custom preview thumbnail image for the version
                value:
                  storyId: 61b1e50223b713000a41ca74
                  senderEmail: sender@company.com
                  data:
                    title: Visual Impact Report
                    company: ACME Corporation
                    tagline: Results that speak for themselves
                    highlight: 300% ROI in 6 months
                    ogImage: https://www.storydoc.com/assets/images/branding/og-storydoc.gif
              completeExample:
                summary: 8. Complete Example
                description: 'Comprehensive example combining all features: expiration,
                  password protection, gated content, arrays, and custom preview'
                value:
                  storyId: 61b1e50223b713000a41ca74
                  senderEmail: sender@company.com
                  daysToExpire: 30
                  data:
                    title: Enterprise Sales Proposal - Q1 2025
                    company: ACME Corporation
                    first_name: John
                    last_name: Doe
                    email: john.doe@acme.com
                    phone: "+1-555-0123"
                    date: January 15, 2025
                    password: SecureProposal2025
                    ogImage: https://www.storydoc.com/assets/images/branding/og-storydoc.gif
                    logo1:
                      domain: acme.com
                      theme: dark
                    products:
                    - name: Enterprise Suite
                      price: 15000
                      features: Unlimited users, 24/7 support
                      discount: 20%
                    - name: Professional Plan
                      price: 3000
                      features: 50 users, Business hours support
                      discount: 10%
                    - name: Starter Package
                      price: 500
                      features: 10 users, Email support
                      discount: 5%
                    team_contacts:
                    - name: Sarah Johnson
                      role: Sales Director
                      email: sarah@acme.com
                      phone: "+1-555-0124"
                    - name: Mike Chen
                      role: Product Manager
                      email: mike@acme.com
                      phone: "+1-555-0125"
                    milestones:
                    - phase: Discovery
                      timeline: Week 1-2
                      deliverable: Requirements document
                    - phase: Implementation
                      timeline: Week 3-6
                      deliverable: System deployment
                    - phase: Training
                      timeline: Week 7-8
                      deliverable: User certification
                    gatedContent:
                      gatedContent: true
                      name: true
                      nameRequired: true
                      logo: true
                      logoSRC: https://www.storydoc.com/assets/images/branding/og-storydoc.gif
                      title: Get instant access to your personalized enterprise proposal
                    custom_field_1: Premium Support Included
                    custom_field_2: ROI Calculator Available
                    custom_field_3: Free 30-day Trial
      responses:
        '200':
          description: Version created successfully
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/VersionResponse"
        '400':
          description: Invalid request parameters
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error400"
              examples:
                missingTitle:
                  summary: Missing data.title
                  description: The required title field is missing from the data object
                  value:
                    error: Missing data.title in request body.
                senderNotFound:
                  summary: Sender email not found
                  description: The sender email is not registered in the organization
                  value:
                    error: senderEmail email@domain.com not found in this organization
                storyNotFound:
                  summary: Story not found
                  description: The specified story ID does not exist
                  value:
                    error: Story 67c8451e37c1f5065165c08b3 not found.
                storyNotLive:
                  summary: Story not published
                  description: The story exists but has not been published yet
                  value:
                    error: Story status is not Live, click Share to set it to Live,
                      https://editor.storydoc.com/pages/editor/6776560c218435d60586da69
        '403':
          description: 'Authentication failed or token outdated, or the story uses
            variables above the account''s plan (`code: VARIABLES_PLAN_REQUIRED`)'
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error403"
        '429':
          description: Rate limit exceeded
          headers:
            x-rate-limit-counter:
              description: Current request count
              schema:
                type: integer
            x-rate-limit-maximum:
              description: Maximum allowed requests
              schema:
                type: integer
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error429"
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error500"
  "/v2/versions/{versionId}":
    post:
      tags:
      - versions
      summary: Update an existing version
      description: 'Updates the data in an existing version, keeping the same version
        and the same link. By default the version''s own content is preserved - including
        any manual edits made to it in the editor - and only the fields you send in
        `data` are changed. Pass `force: true` only to DISCARD those edits and re-render
        the version from the master story template.'
      operationId: updateStoryVersion
      parameters:
      - name: versionId
        in: path
        required: true
        description: The ID of the version to update
        schema:
          type: string
          example: 61b1f40a3a86b7a96d0d8ccc
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/UpdateVersionRequest"
            example:
              senderEmail: sender@company.com
              data:
                title: Updated Sales Presentation
                company: ACME Corporation
                first_name: John
                last_name: Doe
      responses:
        '200':
          description: Version updated successfully
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/VersionResponse"
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error400"
              examples:
                missingTitle:
                  summary: Missing data.title
                  description: The required title field is missing from the data object
                  value:
                    error: Missing data.title in request body.
                senderNotFound:
                  summary: Sender email not found
                  description: The sender email is not registered in the organization
                  value:
                    error: senderEmail email@domain.com not found in this organization
                scopedToOtherStory:
                  summary: Token scoped to a different story
                  description: The API key is limited to one story and the version
                    belongs to another
                  value:
                    error: Token is scoped to storyId 61b1f40a3a86b7a96d0d8ccc, but
                      version 61b1f40a3a86b7a96d0d8ddd belongs to storyId 61b1f40a3a86b7a96d0d8eee
        '403':
          description: 'Authentication failed or token outdated, or the story uses
            variables above the account''s plan (`code: VARIABLES_PLAN_REQUIRED`)'
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error403"
        '404':
          description: Version not found
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error404"
        '429':
          description: Rate limit exceeded
          headers:
            x-rate-limit-counter:
              description: Current request count
              schema:
                type: integer
            x-rate-limit-maximum:
              description: Maximum allowed requests
              schema:
                type: integer
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error429"
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error500"
  "/v2/account":
    get:
      tags:
      - account
      summary: Get account details
      description: Retrieves basic information about the authenticated account/organization
      operationId: getAccount
      responses:
        '200':
          description: Account details retrieved successfully
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/AccountResponse"
              example:
                orgId: 60d5eca77a2d1a001c4d9f7e
                title: ACME Corporation
        '403':
          description: Authentication failed or missing token
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error403"
              example:
                error: Missing authorization token
        '404':
          description: Account not found
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error404"
              example:
                error: Account not found.
        '429':
          description: Rate limit exceeded
          headers:
            x-rate-limit-counter:
              description: Current request count
              schema:
                type: integer
            x-rate-limit-maximum:
              description: Maximum allowed requests
              schema:
                type: integer
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error429"
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error500"
  "/v2/stories/{storyId}":
    get:
      tags:
      - stories
      summary: Get story details
      description: Retrieves detailed information about a specific story including
        its settings and dynamic variables
      operationId: getStory
      parameters:
      - name: storyId
        in: path
        required: true
        description: The ID of the story to retrieve
        schema:
          type: string
          example: 61b1e50223b713000a41ca74
      responses:
        '200':
          description: Story details retrieved successfully
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/StoryResponse"
              example:
                id: 61b1e50223b713000a41ca74
                status: Live
                previewUrl: https://view.storydoc.com/preview/abc123
                createdAt: '2024-01-15T10:30:00.000Z'
                title: Sales Presentation Template
                dynamicVariables:
                  first_name:
                    type: input
                    name: first_name
                    title: Prospect's first name
                    default: ''
                    tip: Prospect's first name
                    validation:
                      required: true
                      errorMessage: Required
                    mapping: FirstName
                  company:
                    type: input
                    name: company
                    title: Company name
                    default: ''
                    tip: Enter the company name
                    validation:
                      required: false
                    mapping: CompanyName
        '400':
          description: Missing or invalid storyId parameter
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error400"
              example:
                error: Missing storyId
        '403':
          description: Authentication failed or missing token
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error403"
              example:
                error: Access denied
        '404':
          description: Story not found
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error404"
              example:
                error: Story not found
        '429':
          description: Rate limit exceeded
          headers:
            x-rate-limit-counter:
              description: Current request count
              schema:
                type: integer
            x-rate-limit-maximum:
              description: Maximum allowed requests
              schema:
                type: integer
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error429"
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error500"
  "/v2/stories/{storyId}/variables":
    get:
      tags:
      - stories
      summary: Get all variables of a story
      description: 'Everything needed to fill a story''s variables when creating versions:
        the dynamic variables manifest, the story''s repeatable-content groups (as
        a tree of fields with example rows), and a ready-to-edit `payloadExample`
        for the `data` object of POST /v2/versions. A repeatable group is sent as
        an array of row objects under its `key`; nested groups sit inside their parent
        row under the child key. Fields flagged `generated: true` (AI, calculations)
        are produced by Storydoc and should not be sent.'
      operationId: getStoryVariables
      parameters:
      - name: storyId
        in: path
        required: true
        description: The ID of the story
        schema:
          type: string
          example: 61b1e50223b713000a41ca74
      responses:
        '200':
          description: Variables retrieved successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  storyId:
                    type: string
                  title:
                    type: string
                  dynamicVariables:
                    type: array
                    description: The story's variables manifest (same shape as `dynamicVariables`
                      on GET /v2/stories/{storyId})
                    items:
                      type: object
                  repeatables:
                    type: array
                    description: Root repeatable-content groups; each group's rows
                      are sent as `data[key] = [row, …]`
                    items:
                      "$ref": "#/components/schemas/RepeatableGroup"
                  payloadExample:
                    type: object
                    description: 'A complete example `data` object for POST /v2/versions:
                      variable defaults plus two example rows per group'
                    additionalProperties: true
              example:
                storyId: 61b1e50223b713000a41ca74
                title: Sales Presentation Template
                dynamicVariables:
                - type: input
                  name: company
                  title: Company name
                  default: ''
                  validation:
                    required: false
                repeatables:
                - key: team
                  name: Team members
                  fields:
                  - key: name
                    name: Name
                    type: input
                  - key: photo
                    name: Photo
                    type: image
                  - key: pitch
                    name: Pitch
                    type: ai
                    generated: true
                  children: []
                  exampleRow:
                    name: Name 1
                    photo: https://example.com/photo-1.png
                payloadExample:
                  title: Version title
                  company: ''
                  team:
                  - name: Name 1
                    photo: https://example.com/photo-1.png
                  - name: Name 2
                    photo: https://example.com/photo-2.png
        '400':
          description: Missing storyId, or the API token is invalid, revoked or inactive
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error400"
        '403':
          description: Authentication failed, missing token, or token scoped to another
            story
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error403"
        '404':
          description: Story not found
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error404"
        '429':
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error429"
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error500"
  "/v2/stories":
    get:
      tags:
      - stories
      summary: List all stories
      description: Retrieves a list of all stories in the organization with optional
        status filtering
      operationId: getStories
      parameters:
      - name: status
        in: query
        required: false
        description: Filter stories by status
        schema:
          type: string
          enum:
          - Draft
          - Live
          - Archived
          example: Live
      responses:
        '200':
          description: Stories retrieved successfully
          content:
            application/json:
              schema:
                type: array
                items:
                  "$ref": "#/components/schemas/StoryResponse"
              example:
              - id: 61b1e50223b713000a41ca74
                status: Live
                previewUrl: https://view.storydoc.com/preview/abc123
                createdAt: '2024-01-15T10:30:00.000Z'
                title: Sales Presentation Template
                dynamicVariables:
                  first_name:
                    type: input
                    name: first_name
                    title: Prospect's first name
                    default: ''
                    tip: Prospect's first name
                    validation:
                      required: true
                      errorMessage: Required
                    mapping: FirstName
                  company:
                    type: input
                    name: company
                    title: Company name
                    default: ''
                    tip: Enter the company name
                    validation:
                      required: false
                    mapping: CompanyName
              - id: 61b1e50223b713000a41ca75
                status: Draft
                previewUrl:
                createdAt: '2024-01-20T14:45:00.000Z'
                title: Product Demo Template
                dynamicVariables:
                  product_name:
                    type: input
                    name: product_name
                    title: Product Name
                    default: ''
                    tip: Enter the product name
                    validation:
                      required: true
                      errorMessage: Product name is required
                    mapping: ProductName
                  features:
                    type: array
                    name: features
                    title: Product Features
                    default: []
                    tip: List of product features
                    validation:
                      required: false
                    mapping: Features
        '403':
          description: Authentication failed or missing token
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error403"
              example:
                error: Access denied
        '404':
          description: No stories found
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error404"
              example:
                error: Stories not found
        '429':
          description: Rate limit exceeded
          headers:
            x-rate-limit-counter:
              description: Current request count
              schema:
                type: integer
            x-rate-limit-maximum:
              description: Maximum allowed requests
              schema:
                type: integer
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error429"
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error500"
  "/v2/stories/generate":
    post:
      tags:
      - stories
      summary: Generate a new story from a prompt
      description: |-
        Generates a brand-new presentation from a natural-language prompt using AI. The endpoint runs a 3-step pipeline (outline → slide layouts → per-slide content), optionally derives a brand color palette and fonts from the supplied `website`, persists the page in **Live** status, and creates its live link.

        The response includes the live URL, short URL, editor URL, and the `pageId` / `versionId` you can pass to other v2 endpoints (e.g. use `pageId` as `storyId` in `POST /v2/versions` to create personalized variants of the generated story).

        ## Rate Limit
        150 requests per minute per organization. Every response includes `x-rate-limit-counter` and `x-rate-limit-maximum` headers.

        ## Latency
        Generation is synchronous and typically takes 30–90 seconds depending on slide count and brand pipeline. Use a long-running HTTP client and set a generous read timeout (≥ 180s).
      operationId: generateStory
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/GenerateStoryRequest"
            examples:
              minimal:
                summary: 1. Minimal request
                description: Only the required fields — the generator picks a default
                  presentation type and skips the brand pipeline.
                value:
                  prompt: A sales deck pitching our analytics product to enterprise
                    marketing teams. Highlight ROI, ease of integration, and customer
                    success stories.
                  senderEmail: sender@company.com
              withBrand:
                summary: 2. With brand context
                description: Supplying `company` and `website` lets the generator
                  fetch brand colors, fonts, and logo via Brandfetch + website scrape
                  and apply them to the story's design system. If the brand pipeline
                  fails or returns unusable data, the story falls back to scaffold
                  defaults (no error).
                value:
                  prompt: 'A pitch deck for our seed round: founding team, the problem,
                    our unique solution, traction, and the ask.'
                  senderEmail: sender@company.com
                  company: ACME Corporation
                  website: acme.com
              withPresentationType:
                summary: 3. With a specific presentation type
                description: "`presentation type` selects an AI template tuned for
                  that document class. Must be one of the supported classifications
                  — see the enum on `GenerateStoryRequest`."
                value:
                  prompt: 'Quarterly business review for our key enterprise account:
                    revenue trends, product adoption, support metrics, and roadmap
                    for next quarter.'
                  senderEmail: sender@company.com
                  company: ACME Corporation
                  website: https://acme.com
                  presentation type: Quarterly Business Review
      responses:
        '200':
          description: Story generated and published successfully
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/GenerateStoryResponse"
              example:
                url: https://www.storydoc.com/5d7d8922e00d9265/2e91b144-092f-456b-8f2e-0bae9f7f3355
                shortUrl: https://view.storydoc.com/4GdDGt
                pageId: 672a1c50223b713000a41ca74
                versionId: 672a1f40a3a86b7a96d0d8ccc
                editorUrl: https://app.storydoc.com/pages/editor/672a1c50223b713000a41ca74/672a1f40a3a86b7a96d0d8ccc
                versionUrl: https://app.storydoc.com/pages/editor/672a1c50223b713000a41ca74/versions/672a1f40a3a86b7a96d0d8ccc
        '400':
          description: Invalid request body or unsupported presentation type
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error400"
              examples:
                missingPrompt:
                  summary: Missing or empty prompt
                  value:
                    error: Missing or empty "prompt" in request body
                invalidSender:
                  summary: Missing or invalid senderEmail
                  value:
                    error: Missing or invalid "senderEmail" in request body
                senderNotInOrg:
                  summary: Sender email not in organization
                  value:
                    error: senderEmail "sender@company.com" not found in this organization
                invalidPresentationType:
                  summary: Unsupported presentation type
                  description: When the supplied `presentation type` is not in the
                    allowed list, the response body includes the full list under `allowedPresentationTypes`.
                  value:
                    error: Invalid "presentation type". Must be one of the supported
                      classifications.
                    allowedPresentationTypes:
                    - Agency pitch deck
                    - Sales deck
                    - Quarterly Business Review
                    - "..."
                invalidTokenOrgId:
                  summary: Token missing orgId
                  value:
                    error: 'Invalid token: missing orgId'
        '403':
          description: Missing or invalid authorization token
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error403"
              examples:
                missingToken:
                  summary: Missing token
                  value:
                    error: Missing authorization token
                invalidToken:
                  summary: Invalid or expired token
                  value:
                    error: Access denied
        '404':
          description: Account not found for the authenticated organization
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error404"
              example:
                error: Account not found
        '429':
          description: Rate limit exceeded
          headers:
            x-rate-limit-counter:
              description: Current request count
              schema:
                type: integer
            x-rate-limit-maximum:
              description: Maximum allowed requests per minute
              schema:
                type: integer
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error429"
        '500':
          description: Generation pipeline failed
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error500"
              example:
                error: Failed to generate story
                errorId: a1b2c3d4e5f60718
  "/v2/analytics/events":
    get:
      tags:
      - analytics
      summary: Query analytics events
      description: |-
        Returns paginated raw engagement events (views and clicks) for the authenticated organization, filtered by date range and optional storyId / versionId / userEmail.

        ## Plan
        This endpoint is available on the **Team** plan only.

        ## Date Range
        Both `dateFrom` and `dateTo` are required ISO 8601 strings. The `dateTo` boundary is inclusive (events on the supplied day are returned). The maximum range is 92 days (3 months).

        ## Pagination
        Results are paginated with a fixed page size of 1000. Pages are 1-indexed. Use the `pagination.hasMore` flag to determine whether to request the next page.

        ## Filtering by user
        Pass `userEmail` to restrict results to events on versions created by that user. The email is resolved to a user in the authenticated organization before querying.
      operationId: getAnalyticsEvents
      parameters:
      - name: dateFrom
        in: query
        required: true
        description: Inclusive start of the date range (ISO 8601, UTC)
        schema:
          type: string
          format: date-time
          example: '2026-01-01T00:00:00Z'
      - name: dateTo
        in: query
        required: true
        description: Inclusive end of the date range (ISO 8601, UTC). Must be at most
          92 days after dateFrom.
        schema:
          type: string
          format: date-time
          example: '2026-03-31T23:59:59Z'
      - name: storyId
        in: query
        required: false
        description: Restrict events to a single story
        schema:
          type: string
          example: 61b1e50223b713000a41ca74
      - name: versionId
        in: query
        required: false
        description: Restrict events to a single version
        schema:
          type: string
          example: 65a1e50223b713000a41ca99
      - name: userEmail
        in: query
        required: false
        description: Restrict events to versions created by the user with this email.
          Must match a user in the authenticated organization.
        schema:
          type: string
          format: email
          example: sender@company.com
      - name: page
        in: query
        required: false
        description: 1-indexed page number. Defaults to 1.
        schema:
          type: integer
          minimum: 1
          default: 1
          example: 1
      responses:
        '200':
          description: Events retrieved successfully
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/AnalyticsEventsResponse"
        '400':
          description: Invalid request (missing/invalid params, range > 3 months,
            invalid token, etc.)
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error400"
              examples:
                missingDates:
                  summary: Missing required dates
                  value:
                    error: dateFrom and dateTo are required (ISO 8601, e.g. 2026-01-01
                      or 2026-01-01T00:00:00Z)
                rangeTooLarge:
                  summary: Date range exceeds 3 months
                  value:
                    error: Date range cannot exceed 3 months
                invalidEmail:
                  summary: Invalid userEmail
                  value:
                    error: userEmail must be a valid email address
                tokenRevoked:
                  summary: API token revoked
                  value:
                    error: Token has been revoked
        '403':
          description: Authentication failed, missing token, or account is not on
            the Team plan
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error403"
              examples:
                missingToken:
                  summary: Missing or invalid token
                  value:
                    error: Access denied
                notTeamPlan:
                  summary: Account is not on the Team plan
                  value:
                    error: Analytics API is available on the Team plan only
        '404':
          description: userEmail does not match any user in the organization
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error404"
              example:
                error: userEmail sender@company.com not found in this organization
        '429':
          description: Rate limit exceeded
          headers:
            x-rate-limit-counter:
              description: Current request count
              schema:
                type: integer
            x-rate-limit-maximum:
              description: Maximum allowed requests per minute
              schema:
                type: integer
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error429"
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error500"
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: |-
        JWT Bearer token authentication in the Authorization header using the format: `Bearer <your-jwt-token>`.

        **Note:** Applicable for Storydoc subscription plans that have API access.

        **Getting Your API Key:**
        1. Log into your Storydoc account
        2. Navigate to the [Integrations page](https://editor.storydoc.com/pages/profile/integrations?tab=automations)
        3. Go to the "Automations" tab
        4. Copy your API key from the displayed token

        If you encounter authentication errors, you may need to regenerate your token from the integrations page.
  schemas:
    CreateVersionRequest:
      type: object
      required:
      - storyId
      - senderEmail
      - data
      properties:
        storyId:
          type: string
          description: 'The ID of the story template. Extract this from your Storydoc
            editor URL: https://editor.storydoc.com/pages/editor/{storyId}'
          example: 61b1e50223b713000a41ca74
        senderEmail:
          type: string
          format: email
          description: Email of the sender (must exist in organization)
          example: john.doe@company.com
        daysToExpire:
          type: integer
          description: Number of days until version expires. Omit for permanent/public
            version
          minimum: 1
          example: 30
        data:
          "$ref": "#/components/schemas/VersionData"
    UpdateVersionRequest:
      type: object
      required:
      - senderEmail
      - data
      properties:
        senderEmail:
          type: string
          format: email
          description: Email of the sender (must exist in organization)
          example: john.doe@company.com
        force:
          type: boolean
          description: DESTRUCTIVE. Re-renders the version from the master story template
            and discards any manual edits made to it in the editor. Leave unset to
            update the version in place, preserving its content.
          default: false
          example: false
        data:
          "$ref": "#/components/schemas/VersionData"
    VersionData:
      type: object
      required:
      - title
      properties:
        title:
          type: string
          description: Title of the version (required)
          example: Sales Proposal - ACME Corporation
        first_name:
          type: string
          example: John
        last_name:
          type: string
          example: Doe
        company:
          type: string
          example: ACME Corporation
        email:
          type: string
          format: email
          example: john.doe@acme.com
        phone:
          type: string
          example: "+1-555-0123"
        date:
          type: string
          description: Date in any format
          example: January 15, 2025
        products:
          type: array
          description: Array of product objects
          items:
            type: object
            properties:
              name:
                type: string
                example: Enterprise Suite
              price:
                type: number
                example: 15000
        gatedContent:
          "$ref": "#/components/schemas/GatedContent"
        password:
          type: string
          description: Password required to view the version
          example: SecurePass123
        ogImage:
          type: string
          format: uri
          description: Open Graph preview image URL for the version
          example: https://www.storydoc.com/assets/images/branding/og-storydoc.gif
        logo:
          "$ref": "#/components/schemas/LogoVariable"
          description: Logo configuration for automatic logo fetching
          example:
            theme: dark
            domain: microsoft.com
      additionalProperties: true
      example:
        title: Sales Presentation
        company: ACME Corp
        custom_field_1: Any value
        custom_field_2: 12345
        logo:
          domain: acme.com
          theme: dark
        partner_logo:
          domain: microsoft.com
          theme: light
    GatedContent:
      type: object
      description: Gated content configuration for access control
      properties:
        gatedContent:
          type: boolean
          description: Enable/disable content gating
          example: true
        name:
          type: boolean
          description: Show name field in the gate form
          example: true
        nameRequired:
          type: boolean
          description: Make name field required
          example: true
        logo:
          type: boolean
          description: Show logo on the gate form
          example: true
        logoSRC:
          type: string
          format: uri
          description: URL of the logo to display on the gate form
          example: https://www.storydoc.com/assets/images/branding/og-storydoc.gif
        title:
          type: string
          description: Custom message shown on the gate form
          example: Please fill in the information below to view your proposal.
    LogoVariable:
      type: object
      description: Logo configuration object
      required:
      - domain
      properties:
        domain:
          type: string
          description: Domain to fetch logo from
          example: acme.com
        theme:
          type: string
          description: Logo theme preference
          enum:
          - dark
          - light
          default: dark
          example: dark
    VersionResponse:
      type: object
      properties:
        url:
          type: string
          format: uri
          description: Public URL for the version
          example: https://www.storydoc.com/5d7d8922e00d9265/2e91b144-092f-456b-8f2e-0bae9f7f3355
        shortUrl:
          type: string
          format: uri
          description: Shortened URL for the version
          example: https://view.storydoc.com/4GdDGt
        editorUrl:
          type: string
          format: uri
          description: URL to edit the version in Storydoc editor
          example: https://app.storydoc.com/pages/editor/61b1e50223b713000a41ca74/61b1f40a3a86b7a96d0d8ccc
        versionUrl:
          type: string
          format: uri
          description: URL to view version details in Storydoc platform
          example: https://app.storydoc.com/pages/editor/61b1e50223b713000a41ca74/versions/61b1f40a3a86b7a96d0d8ccc
        versionId:
          type: string
          description: Unique identifier for the version (only in create response)
          example: 61b1f40a3a86b7a96d0d8ccc
    AccountResponse:
      type: object
      properties:
        orgId:
          type: string
          description: Unique identifier for the organization/account
          example: 60d5eca77a2d1a001c4d9f7e
        title:
          type: string
          description: Name of the organization/account
          example: ACME Corporation
      required:
      - orgId
      - title
    RepeatableGroup:
      type: object
      description: A repeatable-content group. Send its rows as `data[key] = [row,
        …]`; a nested group's rows go inside the parent row under the child's key.
      properties:
        key:
          type: string
          example: team
        name:
          type: string
          example: Team members
        fields:
          type: array
          items:
            type: object
            properties:
              key:
                type: string
                example: name
              name:
                type: string
                example: Name
              type:
                type: string
                example: input
              generated:
                type: boolean
                description: Produced by Storydoc (AI per row, calculations) — do
                  not send
        children:
          type: array
          items:
            type: object
          description: Nested groups (same shape)
        exampleRow:
          type: object
          additionalProperties: true
    StoryResponse:
      type: object
      properties:
        repeatables:
          type: array
          description: Repeatable-content groups of the story (see RepeatableGroup);
            empty when none
          items:
            "$ref": "#/components/schemas/RepeatableGroup"
        id:
          type: string
          description: Unique identifier for the story
          example: 61b1e50223b713000a41ca74
        status:
          type: string
          description: Current status of the story
          enum:
          - Draft
          - Live
          - Archived
          example: Live
        previewUrl:
          type: string
          format: uri
          nullable: true
          description: Preview URL for the story (null if not published)
          example: https://view.storydoc.com/preview/abc123
        createdAt:
          type: string
          format: date-time
          description: Timestamp when the story was created
          example: '2024-01-15T10:30:00.000Z'
        title:
          type: string
          description: Title of the story
          example: Sales Presentation Template
        dynamicVariables:
          type: object
          description: Dynamic variables configuration for the story
          additionalProperties:
            type: object
            properties:
              type:
                type: string
                description: Type of the variable
                example: input
              name:
                type: string
                description: Variable name
                example: first_name
              title:
                type: string
                description: Display title for the variable
                example: Prospect's first name
              default:
                type: string
                description: Default value
                example: ''
              tip:
                type: string
                description: Tooltip or help text
                example: Prospect's first name
              validation:
                type: object
                properties:
                  required:
                    type: boolean
                    example: true
                  errorMessage:
                    type: string
                    example: Required
              mapping:
                type: string
                description: Field mapping
                example: FirstName
          example:
            first_name:
              type: input
              name: first_name
              title: Prospect's first name
              default: ''
              tip: Prospect's first name
              validation:
                required: true
                errorMessage: Required
              mapping: FirstName
            company:
              type: input
              name: company
              title: Company name
              default: ''
              tip: Enter the company name
              validation:
                required: false
              mapping: CompanyName
      required:
      - id
      - status
      - title
    GenerateStoryRequest:
      type: object
      required:
      - prompt
      - senderEmail
      properties:
        prompt:
          type: string
          description: Natural-language description of the presentation you want to
            generate. The more concrete the prompt (topic, audience, structure, tone,
            key points), the better the output. Cannot be empty or whitespace-only.
          example: A 6-slide sales deck pitching our analytics product to enterprise
            marketing teams. Highlight ROI, ease of integration, and customer success
            stories.
        senderEmail:
          type: string
          format: email
          description: Email of the user that owns the generated story (becomes the
            story creator and the sender on the live link). Must belong to a user
            in the authenticated organization, otherwise the request is rejected with
            400.
          example: sender@company.com
        company:
          type: string
          description: Optional company name to use as the subject of the presentation.
            If omitted and `website` is provided, the name is inferred from Brandfetch.
          example: ACME Corporation
        website:
          type: string
          description: Optional company website used to derive brand colors, fonts,
            and logo for the generated story's design system. Accepts a bare domain
            (`acme.com`) or a full URL (`https://acme.com/about`); the hostname is
            extracted automatically. If the brand pipeline fails or returns unusable
            data, the story falls back to scaffold defaults (the request still succeeds).
          example: acme.com
        presentation type:
          type: string
          description: Optional classification that selects an AI template tuned for
            that document class. Must be one of the supported subtypes (see enum).
            Defaults to `General presentation` when omitted. Unsupported values return
            400 with the full allowed list under `allowedPresentationTypes`.
          default: General presentation
          enum:
          - Agency pitch deck
          - Annual report
          - Brand guidelines
          - Brand proposal
          - Brochure
          - Business Plan
          - Business report
          - Case study one-pager
          - Company presentation
          - Construction proposal
          - Customer onboarding meeting
          - E-book
          - ESG report
          - Event proposal
          - Film pitch deck
          - Gaming pitch deck
          - General presentation
          - HR recruitment
          - Invest pitch deck
          - Investor report
          - Marketing case study
          - Marketing plan
          - Marketing proposal
          - Music event sponsorship proposal
          - NGO report
          - New employee onboarding
          - One pager
          - Partnership proposal
          - Pre-interview deck
          - Product launch
          - Product newsletter
          - Product pitch deck
          - Product roadmap
          - Project proposal
          - Quarterly Business Review
          - Quarterly report
          - Real estate listing
          - Research report
          - Restaurant proposal deck
          - Sales deck
          - Sales kickoff meeting
          - Sales proposal
          - Service pitch deck
          - Sports sponsorship
          - Startup pitch deck
          - Student case study
          - Student report
          - Video case study
          - Webinar
          - White paper
          - Workshop proposal
          example: Sales deck
    GenerateStoryResponse:
      type: object
      required:
      - url
      - shortUrl
      - pageId
      - versionId
      - editorUrl
      - versionUrl
      properties:
        url:
          type: string
          format: uri
          description: Public live URL of the generated story.
          example: https://www.storydoc.com/5d7d8922e00d9265/2e91b144-092f-456b-8f2e-0bae9f7f3355
        shortUrl:
          type: string
          format: uri
          description: Shortened share URL for the live link.
          example: https://view.storydoc.com/4GdDGt
        pageId:
          type: string
          description: ID of the underlying story (page). Use this as `storyId` in
            subsequent `POST /v2/versions` calls to create personalized variants of
            the generated story.
          example: 672a1c50223b713000a41ca74
        versionId:
          type: string
          description: ID of the generated live link. Use it as the path parameter
            for `POST /v2/versions/{versionId}` to update its data.
          example: 672a1f40a3a86b7a96d0d8ccc
        editorUrl:
          type: string
          format: uri
          description: Deep link to edit the generated version in the Storydoc editor.
          example: https://app.storydoc.com/pages/editor/672a1c50223b713000a41ca74/672a1f40a3a86b7a96d0d8ccc
        versionUrl:
          type: string
          format: uri
          description: Deep link to the version detail page in the Storydoc platform.
          example: https://app.storydoc.com/pages/editor/672a1c50223b713000a41ca74/versions/672a1f40a3a86b7a96d0d8ccc
    AnalyticsEventRow:
      type: object
      properties:
        sessionId:
          type: string
          nullable: true
          example: 1c2f0c2c-9b7e-4f4a-9f8e-3a3a3a3a3a3a
        eventId:
          type: string
          nullable: true
          example: evt_8a1c0a16d2b14e9c
        visitorId:
          type: string
          nullable: true
          example: vis_aa11bb22cc33dd44
        timestamp:
          type: string
          format: date-time
          example: '2026-04-15T14:32:11.000Z'
        storyId:
          type: string
          example: 61b1e50223b713000a41ca74
        storyTitle:
          type: string
          nullable: true
          example: Sales Presentation Template
        versionId:
          type: string
          example: 65a1e50223b713000a41ca99
        versionTitle:
          type: string
          nullable: true
          example: ACME Corp - Q2 Pitch
        versionCreatedAt:
          type: string
          nullable: true
          format: date-time
          example: '2026-04-10T09:15:00.000Z'
        prospectName:
          type: string
          nullable: true
          example: Jane Cooper
        prospectEmail:
          type: string
          nullable: true
          format: email
          example: jane.cooper@acme.com
        prospectPosition:
          type: string
          nullable: true
          example: VP Marketing
        eventName:
          type: string
          nullable: true
          description: Specific action (e.g. view_slide_3, click_cta)
          example: view_slide_3
        eventCategory:
          type: string
          nullable: true
          description: Always 'view' or 'click'
          example: view
        deviceType:
          type: string
          nullable: true
          example: desktop
        deviceTypeName:
          type: string
          nullable: true
          example: Mac
        eventUrl:
          type: string
          nullable: true
          format: uri
          example: https://view.storydoc.com/abc123
        locationCity:
          type: string
          nullable: true
          example: New York
        locationLatitude:
          type: number
          nullable: true
          format: float
          example: 40.7128
        locationLongitude:
          type: number
          nullable: true
          format: float
          example: -74.006
      required:
      - timestamp
      - storyId
      - versionId
    AnalyticsEventsResponse:
      type: object
      properties:
        data:
          type: array
          items:
            "$ref": "#/components/schemas/AnalyticsEventRow"
        pagination:
          type: object
          properties:
            page:
              type: integer
              example: 1
            pageSize:
              type: integer
              example: 1000
            total:
              type: integer
              example: 12453
            totalPages:
              type: integer
              example: 13
            hasMore:
              type: boolean
              example: true
          required:
          - page
          - pageSize
          - total
          - totalPages
          - hasMore
      required:
      - data
      - pagination
      example:
        data:
        - sessionId: 1c2f0c2c-9b7e-4f4a-9f8e-3a3a3a3a3a3a
          eventId: evt_8a1c0a16d2b14e9c
          visitorId: vis_aa11bb22cc33dd44
          timestamp: '2026-04-15T14:32:11.000Z'
          storyId: 61b1e50223b713000a41ca74
          storyTitle: Sales Presentation Template
          versionId: 65a1e50223b713000a41ca99
          versionTitle: ACME Corp - Q2 Pitch
          versionCreatedAt: '2026-04-10T09:15:00.000Z'
          prospectName: Jane Cooper
          prospectEmail: jane.cooper@acme.com
          prospectPosition: VP Marketing
          eventName: view_slide_3
          eventCategory: view
          deviceType: desktop
          deviceTypeName: Mac
          eventUrl: https://view.storydoc.com/abc123
          locationCity: New York
          locationLatitude: 40.7128
          locationLongitude: -74.006
        pagination:
          page: 1
          pageSize: 1000
          total: 12453
          totalPages: 13
          hasMore: true
    ErrorResponse:
      type: object
      properties:
        error:
          type: string
          description: Error message
        errorId:
          type: string
          description: Unique error identifier for support
      example:
        error: Error message varies by status code
    Error400:
      type: object
      properties:
        error:
          type: string
          example: Missing data.title in request body.
    Error403:
      type: object
      properties:
        error:
          type: string
          example: Access denied
        code:
          type: string
          description: "`VARIABLES_PLAN_REQUIRED` when the story uses variables above
            the account's plan; absent for authentication failures."
          example: VARIABLES_PLAN_REQUIRED
        requiredPlan:
          type: string
          enum:
          - pro
          - team
          description: 'With `VARIABLES_PLAN_REQUIRED`: the lowest plan that covers
            every blocked variable.'
        variables:
          type: array
          description: 'With `VARIABLES_PLAN_REQUIRED`: the blocked variables and
            the plan each needs.'
          items:
            type: object
            properties:
              name:
                type: string
                example: deal_value
              requiredPlan:
                type: string
                example: pro
    Error404:
      type: object
      properties:
        error:
          type: string
          example: Version not found
    Error429:
      type: object
      properties:
        error:
          type: string
          example: Too many requests
    Error500:
      type: object
      properties:
        error:
          type: string
          example: Error occured
        errorId:
          type: string
          example: 550e8400-e29b-41d4-a716-446655440000
