> ## 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.

# AI-powered field detection

> Automatically detect and create form fields from a document using AI.

Accounts on the v2 detection pipeline receive additional response metadata
(see `pipeline` property) and richer `preferences` on each field (canonical
`key`, per-field `confidence`, `anchor_text`, and `anchor_method`). See the
[AI Field Detection Pipeline guide](/guides/ai-field-detection-pipeline)
for details. Existing consumers are unaffected — the new fields are
additive. On v2, callers may optionally send `context` to provide
advisory hints and expected canonical fields; legacy v1 silently ignores it.




## OpenAPI

````yaml post /api/templates/{template_id}/ai/smart_create
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/templates/{template_id}/ai/smart_create:
    post:
      tags:
        - AI
      summary: AI-powered field detection
      description: >
        Automatically detect and create form fields from a document using AI.


        Accounts on the v2 detection pipeline receive additional response
        metadata

        (see `pipeline` property) and richer `preferences` on each field
        (canonical

        `key`, per-field `confidence`, `anchor_text`, and `anchor_method`). See
        the

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

        for details. Existing consumers are unaffected — the new fields are

        additive. On v2, callers may optionally send `context` to provide

        advisory hints and expected canonical fields; legacy v1 silently ignores
        it.
      operationId: aiSmartCreate
      parameters:
        - name: template_id
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                detection_mode:
                  type: string
                  enum:
                    - all
                    - library_only
                  default: all
                  description: >-
                    library_only restricts detection to canonical field-library
                    keys (no new keys are minted from labels).
                context:
                  $ref: '#/components/schemas/AiAutoMapContext'
            example:
              detection_mode: all
              context:
                document_hint: Customs POA; signer is the importer of record.
                instructions: Skip the notary section.
                expected_fields:
                  - key: importer_name
                    name: Importer Name
                    type: text
                merge_mode: extend
                per_document:
                  550e8400-e29b-41d4-a716-446655440000:
                    document_hint: CBP 4811 form
      responses:
        '200':
          description: Detected fields
          content:
            application/json:
              schema:
                type: object
                properties:
                  fields:
                    type: array
                    items:
                      $ref: '#/components/schemas/FieldSchema'
                  count:
                    type: integer
                  pipeline:
                    $ref: '#/components/schemas/AiPipelineMetadata'
        '422':
          description: Invalid v2 context, AI not configured, or no document found
components:
  schemas:
    AiAutoMapContext:
      type: object
      additionalProperties: false
      properties:
        document_hint:
          type: string
          maxLength: 500
        instructions:
          type: string
          maxLength: 500
        expected_fields:
          type: array
          maxItems: 50
          items:
            type: object
            additionalProperties: false
            required:
              - key
            properties:
              key:
                type: string
                pattern: ^[a-z][a-z0-9_]{0,49}$
              name:
                type: string
                maxLength: 100
              type:
                type: string
                enum:
                  - signature
                  - initials
                  - text
                  - date
                  - checkbox
                  - number
                  - phone
                  - image
        merge_mode:
          type: string
          enum:
            - extend
            - replace
          default: extend
        per_document:
          type: object
          additionalProperties:
            type: object
            additionalProperties: false
            properties:
              document_hint:
                type: string
                maxLength: 500
    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'
    AiPipelineMetadata:
      type: object
      description: |
        Telemetry metadata attached to v2 AI field detection responses.
        Accounts on the legacy (v1) pipeline do not receive this block.
      properties:
        version:
          type: string
          example: v2
          description: Pipeline version that processed this request
        request_id:
          type: string
          format: uuid
          description: >-
            Stable per-request identifier — correlates the response to the
            `ai_pipeline_runs` diagnostic row
        latency_ms:
          type: integer
          description: Total pipeline wall time in milliseconds
        anchor_hits:
          type: integer
          description: Count of fields successfully snapped to PDF text-layer anchors
        anchor_misses:
          type: integer
          description: >-
            Count of fields that fell back to pure-LLM placement (scanned PDFs
            or text not found)
        corrections_applied:
          type: integer
          description: >-
            Total deterministic corrections applied by the Normalizer stage
            (size bounds, key dedup, overlap drops, etc.)
        critic_ran:
          type: boolean
          description: Whether the confidence-gated self-critique pass was invoked
        documents_scanned:
          type: integer
          description: >-
            Number of documents scanned in this request (multi-doc templates
            scan all documents in one call)
        verifier_ran:
          type: boolean
          description: >-
            Whether the visual verification pass reviewed field positions
            against rendered page images
    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)

````