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

# Create submission

> Send a template to one or more submitters for signing.

**Quick Sign Mode:** Set `quick_sign_mode` to enable streamlined signing flows.
When using `confirmation_modal`, signers see a summary of pre-filled data and can
confirm with a single click. Use `review_and_sign` to show a summary on the welcome
screen.

**Default behavior:** If omitted, `quick_sign_mode` defaults to `confirmation_modal`.
`prefill_behavior` defaults to:
- `skip_if_prefilled: true`
- `editable_if_prefilled: false`
Set `quick_sign_mode: normal` to force legacy behavior.

**Auto-Generated Signatures:** When `quick_sign_mode` is not `normal` and a submitter
has a `name`, any unfilled signature fields will be automatically populated with a
typed signature image generated from the submitter's name.

**Cover Page:** Pass a `cover_page` object to generate a branded PDF cover page
prepended as page 0 of the signing package. The cover page is generated per submission
with dynamic financial data (amounts, phases, company name). All monetary values are
integers in whole dollars. Admin fees must be negative.

**Start Screen Customization:** Use template `preferences` to customize the signing
welcome screen: `disable_start_screen` (skip directly to signing),
`start_screen_title`, and `start_screen_message`.




## OpenAPI

````yaml post /api/submissions
openapi: 3.0.3
info:
  title: SpitShake API
  version: 1.0.0
  description: >
    SpitShake is a document signing and e-signature platform. This API allows
    you to

    manage templates, send documents for signing, track submissions, and
    integrate

    document signing into your applications.


    ## Authentication


    SpitShake supports the tenant authentication methods below plus an isolated
    partner credential:


    ### API Token (Recommended)

    Pass your API token in the `X-Auth-Token` header or as `Authorization:
    Bearer <token>`.

    Generate tokens at **Settings > API** with granular scopes.


    ```

    curl -H "X-Auth-Token: YOUR_TOKEN" https://your-instance.com/api/templates

    ```


    ### OAuth 2.1 (Authorization Code + PKCE)

    For connector directories and third-party agents. Discover endpoints at

    `GET /.well-known/oauth-authorization-server`. PKCE is mandatory.


    ### Session Cookie

    Automatically set when logged into the web application. Used by the
    frontend.


    ### JWT Bearer Token (Embed API only)

    For embedded forms and builders. Generate via `POST /api/embed/token`.


    ```

    curl -H "Authorization: Bearer JWT_TOKEN"
    https://your-instance.com/api/embed/submission/123

    ```


    ### Partner Bearer Key (`/api/partner/v1` only)

    Operator-issued `spk_` keys authenticate the reseller control plane. Partner
    keys and tenant

    credentials are mutually non-acceptable.


    ## Idempotency

    Create and send operations accept an `Idempotency-Key` header. A repeated

    request with the same key and body replays the original response without

    creating a duplicate. Keys expire after 24 hours.


    ## Versioning

    Tenant API responses include an `X-API-Version: v1` header. The tenant API
    is available

    at both `/api/*` and `/api/v1/*` (explicit pin). Partner responses include

    `X-API-Version: partner-v1`, and that control plane is separately pinned at

    `/api/partner/v1/*`.


    ## Pagination


    List endpoints use cursor-based pagination:


    | Parameter | Type | Description |

    |-----------|------|-------------|

    | `limit` | integer | Items per page (1-100, default 10) |

    | `after` | integer | Return items after this ID |

    | `before` | integer | Return items before this ID |


    Response includes a `pagination` object:

    ```json

    {
      "data": [...],
      "pagination": {
        "count": 10,
        "next": 456,
        "prev": 123
      }
    }

    ```


    Use `pagination.next` as the `after` parameter to get the next page.


    ## Rate Limits


    API requests are limited to 120 requests per minute per API token.

    Partner API requests are limited to 100 requests per minute per partner key.


    ## Errors


    All errors return a JSON object with an `error` field:


    ```json

    { "error": "Not found" }

    ```


    | Status | Meaning |

    |--------|---------|

    | 400 | Bad request - invalid parameters |

    | 401 | Unauthorized - invalid or missing authentication |

    | 403 | Forbidden - insufficient permissions or plan limits exceeded |

    | 404 | Not found |

    | 422 | Unprocessable entity - validation errors |

    | 500 | Internal server error (includes `detail` field with exception
    message for debugging) |


    ## Plan Limits


    Some endpoints require specific subscription plans. If your plan doesn't
    support an endpoint,

    you'll receive a 403 response with an `upgrade_url` field.
  contact:
    name: SpitShake Support
    url: https://spitshake.io
  license:
    name: Proprietary
servers:
  - url: /
    description: Current instance
security:
  - ApiToken: []
  - SessionCookie: []
tags:
  - name: Templates
    description: Manage document templates with fields, submitters, and documents
  - name: Submissions
    description: Create and manage document signing submissions
  - name: Submitters
    description: Manage individual submitters (signers) within submissions
  - name: Users
    description: Manage account users and team members
  - name: Access Tokens
    description: Manage API tokens for programmatic access (requires Pro plan)
  - name: Webhooks
    description: Configure webhook endpoints for event notifications (requires Pro plan)
  - name: Settings
    description: Account settings, SMTP, storage, certificates, and email configuration
  - name: Audit Events
    description: View audit log of account activities (requires Pro plan)
  - name: Subscriptions
    description: View current plan, usage, and manage billing
  - name: Plans
    description: List available subscription plans (public)
  - name: Payments
    description: Process payments within signing flows via Stripe
  - name: Verification
    description: SMS OTP phone verification for signing sessions
  - name: KBA
    description: Knowledge-Based Authentication for identity verification
  - name: AI
    description: AI-powered document analysis and field detection
  - name: Embed
    description: Embed signing forms and template builders in your application
  - name: Custom Domains
    description: >-
      Manage custom signing domains with automatic SSL provisioning via
      Cloudflare
  - name: Teams
    description: Team management and template access control
  - name: Health
    description: System health check endpoints (public)
  - name: MFA
    description: Multi-Factor Authentication setup, management, and verification
  - name: BAA
    description: Business Associate Agreement acceptance and management (HIPAA)
  - name: Security Events
    description: Security event monitoring and breach detection dashboard (admin only)
  - name: Thumbnails
    description: Template document thumbnail generation and retrieval
  - name: Partner API
    description: >-
      Versioned reseller control plane for provisioning and metering isolated
      tenant accounts
paths:
  /api/submissions:
    post:
      tags:
        - Submissions
      summary: Create submission
      description: >
        Send a template to one or more submitters for signing.


        **Quick Sign Mode:** Set `quick_sign_mode` to enable streamlined signing
        flows.

        When using `confirmation_modal`, signers see a summary of pre-filled
        data and can

        confirm with a single click. Use `review_and_sign` to show a summary on
        the welcome

        screen.


        **Default behavior:** If omitted, `quick_sign_mode` defaults to
        `confirmation_modal`.

        `prefill_behavior` defaults to:

        - `skip_if_prefilled: true`

        - `editable_if_prefilled: false`

        Set `quick_sign_mode: normal` to force legacy behavior.


        **Auto-Generated Signatures:** When `quick_sign_mode` is not `normal`
        and a submitter

        has a `name`, any unfilled signature fields will be automatically
        populated with a

        typed signature image generated from the submitter's name.


        **Cover Page:** Pass a `cover_page` object to generate a branded PDF
        cover page

        prepended as page 0 of the signing package. The cover page is generated
        per submission

        with dynamic financial data (amounts, phases, company name). All
        monetary values are

        integers in whole dollars. Admin fees must be negative.


        **Start Screen Customization:** Use template `preferences` to customize
        the signing

        welcome screen: `disable_start_screen` (skip directly to signing),

        `start_screen_title`, and `start_screen_message`.
      operationId: createSubmission
      parameters:
        - name: Idempotency-Key
          in: header
          required: false
          schema:
            type: string
            maxLength: 255
          description: >-
            Prevents duplicate submissions on retry. Same key + same body
            replays the original response.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - template_id
                - submitters
              properties:
                template_id:
                  type: string
                submitters:
                  type: array
                  items:
                    type: object
                    properties:
                      email:
                        type: string
                        format: email
                      name:
                        type: string
                      phone:
                        type: string
                      role:
                        type: string
                        description: Must match a submitter role from the template
                      external_id:
                        type: string
                      metadata:
                        type: object
                      values:
                        type: object
                        description: >
                          Pre-filled field values. Keys can be field UUIDs,
                          field keys, or normalized field names.


                          Repeated-name behavior:

                          - Scalar value: fan-out to all matching fields.

                          - Array value: positional distribution in document
                          order.

                          - Array length mismatch: request fails with `422
                          invalid_field_values`.


                          Mixed UUID and name keys are supported; UUID-keyed
                          values win for explicitly targeted fields.


                          Value coercion:

                          - text/phone/select/radio/cells -> string

                          - number -> numeric (rejects non-numeric strings)

                          - checkbox -> boolean (accepts
                          true/false/1/0/y/n/yes/no)

                          - date -> ISO date

                          - signature/initials -> string or `{ image: ... }`
                      preferences:
                        type: object
                      field_overrides:
                        type: object
                        description: Per-field behavior overrides
                      completed:
                        type: boolean
                        default: false
                        description: Auto-complete (auto-sign) this submitter immediately
                      fields:
                        type: array
                        description: Field value overrides by field name or key
                        items:
                          type: object
                          properties:
                            name:
                              type: string
                              description: Field name or key to match
                            default_value:
                              type: string
                              description: Value to set for the field
                send_email:
                  type: boolean
                  default: true
                  description: Send invitation emails to submitters
                send_sms:
                  type: boolean
                  default: false
                  description: Send SMS invitations instead of email
                order:
                  type: string
                  enum:
                    - preserved
                    - random
                  default: preserved
                expire_at:
                  type: string
                  format: date-time
                metadata:
                  type: object
                completed_redirect_url:
                  type: string
                reply_to:
                  type: string
                  format: email
                bcc_completed:
                  type: string
                  format: email
                message:
                  type: object
                  properties:
                    subject:
                      type: string
                    body:
                      type: string
                quick_sign_mode:
                  type: string
                  enum:
                    - normal
                    - review_and_sign
                    - auto_scroll_signature
                    - confirmation_modal
                  default: confirmation_modal
                  description: >-
                    Submission-level quick-sign mode. Set to `normal` to force
                    legacy behavior.
                prefill_behavior:
                  type: object
                  description: >-
                    Submission-level prefill behavior. Defaults to skip
                    prefilled fields and make them read-only.
                  properties:
                    skip_if_prefilled:
                      type: boolean
                      default: true
                    editable_if_prefilled:
                      type: boolean
                      default: false
                cover_page:
                  type: object
                  description: >
                    Generate a dynamic cover page and prepend it as page 0 of
                    the signing package.

                    The cover page is rendered per submission with the provided
                    financial data.

                    All monetary values are integers in whole dollars (no
                    cents). Admin fees must be negative.
                  properties:
                    company_name:
                      type: string
                      description: Importer's company name
                    entry_count:
                      type: integer
                      description: Total number of customs entries
                    entry_type:
                      type: string
                      description: Type of recovery (e.g., "IEEPA tariff recovery")
                    estimated_refund:
                      type: integer
                      description: Total estimated net refund in whole dollars
                    phase_1_amount:
                      type: integer
                      description: Phase 1 net refund amount
                    phase_1_entries:
                      type: integer
                      description: Number of entries in Phase 1
                    phase_1_label:
                      type: string
                      description: Phase 1 description (e.g., "Filing Immediately")
                    phase_2_amount:
                      type: integer
                      description: Phase 2 net refund amount
                    phase_2_entries:
                      type: integer
                      description: Number of entries in Phase 2
                    phase_2_label:
                      type: string
                      description: Phase 2 description (e.g., "After Liquidation")
                    base_interest_1:
                      type: integer
                      description: >-
                        Phase 1 estimated base refund + interest (before admin
                        fee)
                    admin_fee_1:
                      type: integer
                      description: Phase 1 admin/broker fee (must be negative)
                    base_interest_2:
                      type: integer
                      description: >-
                        Phase 2 estimated base refund + interest (before admin
                        fee)
                    admin_fee_2:
                      type: integer
                      description: Phase 2 admin/broker fee (must be negative)
                  required:
                    - company_name
                    - entry_count
                    - entry_type
                    - estimated_refund
                    - phase_1_amount
                    - phase_1_entries
                    - phase_1_label
                    - phase_2_amount
                    - phase_2_entries
                    - phase_2_label
                    - base_interest_1
                    - admin_fee_1
                    - base_interest_2
                    - admin_fee_2
                preferences:
                  type: object
      responses:
        '201':
          description: Created submission with submitters
          headers:
            X-Submission-Warning:
              description: >-
                Optional warning when name-key mapping is ambiguous (for
                example, `name_key_ambiguous:initials`)
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubmissionFull'
        '403':
          description: Plan limit reached
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '422':
          description: Invalid field values (coercion or repeated-key array mismatch)
          headers:
            X-Submission-Warning:
              description: Optional warning codes related to key mapping
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubmissionFieldValueErrorResponse'
components:
  schemas:
    SubmissionFull:
      type: object
      properties:
        id:
          type: integer
        slug:
          type: string
        source:
          type: string
        status:
          type: string
        template_id:
          type: string
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
        completed_at:
          type: string
          format: date-time
          nullable: true
        expire_at:
          type: string
          format: date-time
          nullable: true
        submitters:
          type: array
          items:
            $ref: '#/components/schemas/SubmitterDetail'
        audit_log:
          type: array
          items:
            type: object
        metadata:
          type: object
        template:
          type: object
          properties:
            id:
              type: string
            name:
              type: string
            schema:
              type: array
              items:
                $ref: '#/components/schemas/FieldSchema'
            submitters:
              type: array
              items:
                type: object
            documents:
              type: array
              items:
                $ref: '#/components/schemas/TemplateDocument'
        documents:
          type: array
          items:
            type: object
            properties:
              id:
                type: integer
              filename:
                type: string
              document_type:
                type: string
              byte_size:
                type: integer
    Error:
      type: object
      properties:
        error:
          oneOf:
            - type: string
            - type: array
              items:
                type: string
    SubmissionFieldValueErrorResponse:
      type: object
      properties:
        error:
          type: string
        code:
          type: string
          enum:
            - invalid_field_values
        errors:
          type: array
          items:
            $ref: '#/components/schemas/SubmissionFieldValueIssue'
        warnings:
          type: array
          items:
            $ref: '#/components/schemas/SubmissionFieldValueIssue'
    SubmitterDetail:
      allOf:
        - $ref: '#/components/schemas/Submitter'
        - type: object
          properties:
            phone:
              type: string
              nullable: true
            external_id:
              type: string
              nullable: true
            values:
              type: object
            metadata:
              type: object
            preferences:
              type: object
              nullable: true
            declined_at:
              type: string
              format: date-time
              nullable: true
            documents:
              type: array
              items:
                type: object
                properties:
                  name:
                    type: string
                  url:
                    type: string
            submission_events:
              type: array
              items:
                type: object
            template:
              type: object
              properties:
                id:
                  type: integer
                name:
                  type: string
            submission:
              type: object
              properties:
                id:
                  type: integer
                slug:
                  type: string
                status:
                  type: string
    FieldSchema:
      type: object
      properties:
        uuid:
          type: string
          format: uuid
        name:
          type: string
        type:
          type: string
          enum:
            - text
            - signature
            - initials
            - date
            - date_now
            - checkbox
            - select
            - radio
            - file
            - image
            - stamp
            - payment
            - phone_verification
            - cells
            - number
          description: >
            Field type. `stamp` is a read-only company signature field —
            auto-filled from

            account settings (`company_stamp_url` or `company_stamp_text`).
            Signers cannot

            edit stamps. Use for pre-executed company signature blocks.
        submitter_uuid:
          type: string
          format: uuid
        required:
          type: boolean
        readonly:
          type: boolean
        key:
          type: string
          nullable: true
        default_value:
          type: string
          nullable: true
          description: >
            Fallback value applied when a submission is created without an
            explicit value

            for this field. Supports system token expressions that resolve at
            creation time:


            - `{{$submission_id}}` — submission slug

            - `{{$submission_date}}` — ISO date (YYYY-MM-DD)

            - `{{$submitter_name}}` — submitter's name

            - `{{$submitter_email}}` — submitter's email

            - `{{$submitter_role}}` — submitter's role

            - `{{$template_name}}` — template name

            - `{{$account_name}}` — account name


            Mixed literals and tokens are supported: `CFA-{{$submission_id}}`
        placeholder:
          type: string
          nullable: true
        pattern:
          type: string
          nullable: true
          description: Custom regex pattern for field validation
        validation:
          type: string
          nullable: true
          enum:
            - ssn
            - ein
            - email
            - url
            - zip
            - zip_us
            - numeric
            - alpha
            - alphanumeric
            - phone_us
            - phone_intl
          description: Validation preset name (applies a predefined regex pattern)
        options:
          type: array
          items:
            type: string
          nullable: true
        formula:
          type: string
          nullable: true
          description: >-
            Formula expression for calculated fields (e.g. "field1 + field2 *
            0.1")
        areas:
          type: array
          items:
            type: object
            properties:
              x:
                type: number
              'y':
                type: number
              w:
                type: number
              h:
                type: number
              page:
                type: integer
              attachment_uuid:
                type: string
                format: uuid
        preferences:
          description: >
            Free-form per-field metadata. On v2 AI pipeline responses this
            object

            may include the typed keys described by `AiFieldPreferences` — see
            the

            [AI Field Detection Pipeline
            guide](/guides/ai-field-detection-pipeline).

            Legacy (v1) responses return an empty object.
          anyOf:
            - type: object
            - $ref: '#/components/schemas/AiFieldPreferences'
    TemplateDocument:
      type: object
      properties:
        id:
          type: integer
        uuid:
          type: string
          format: uuid
        filename:
          type: string
        page_count:
          type: integer
        page_dimensions:
          type: array
          items:
            type: object
            properties:
              width:
                type: number
              height:
                type: number
        url:
          type: string
    SubmissionFieldValueIssue:
      type: object
      properties:
        code:
          type: string
        key:
          type: string
        field_uuid:
          type: string
          format: uuid
        field_name:
          type: string
        field_type:
          type: string
        message:
          type: string
        expected_count:
          type: integer
        unmatched_count:
          type: integer
        received_count:
          type: integer
    Submitter:
      type: object
      properties:
        id:
          type: integer
        uuid:
          type: string
          format: uuid
        slug:
          type: string
        email:
          type: string
          format: email
          nullable: true
        name:
          type: string
          nullable: true
        role:
          type: string
        status:
          type: string
          enum:
            - waiting
            - sent
            - opened
            - completed
            - declined
            - expired
        submission_id:
          type: integer
        opened_at:
          type: string
          format: date-time
          nullable: true
        sent_at:
          type: string
          format: date-time
          nullable: true
        completed_at:
          type: string
          format: date-time
          nullable: true
    AiFieldPreferences:
      type: object
      description: |
        `preferences` payload on a field detected by the v2 AI pipeline.
        Legacy (v1) pipeline responses return `preferences: {}`.
      properties:
        key:
          type: string
          description: >-
            Canonical snake_case identifier (e.g., `full_name`, `signature`,
            `signed_date`). Stable across documents with the same semantic
            field.
          example: full_name
        confidence:
          type: number
          format: float
          minimum: 0
          maximum: 1
          description: >-
            Self-reported model confidence for both the field type AND the
            placement. Fields below ~0.85 triggered the self-critique pass.
        anchor_text:
          type: string
          description: Verbatim label text near the field as it appears in the PDF.
          example: 'Printed Name:'
        anchor_method:
          type: string
          enum:
            - snapped_to_blank
            - snapped_to_label
            - llm_only
            - no_text_layer
            - page_missing
          description: >
            How the field's position was determined:

            - `snapped_to_blank` — aligned to an underscore run in the PDF text
            layer (highest precision)

            - `snapped_to_label` — aligned to the preceding label (no underscore
            run nearby)

            - `llm_only` — kept the raw model coordinates (text layer present
            but no anchor matched)

            - `no_text_layer` — scanned PDF, no text layer available

            - `page_missing` — requested page not present in the document
  securitySchemes:
    ApiToken:
      type: apiKey
      in: header
      name: X-Auth-Token
      description: API token generated at Settings > API
    SessionCookie:
      type: apiKey
      in: cookie
      name: _docutrust_session
      description: Session cookie (automatic when logged in)

````