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

# Upload a Compliance Document

> Put a PDF into one of the four compliance slots

Uploads a PDF into one of the four compliance slots for one of your entities, and queues it for data extraction. Send it as `multipart/form-data` with the file in the `file` part.

## A category is a slot, not a folder

An entity holds **one** errors-and-omissions document, one cyber, one W9, one crime-and-fidelity. Uploading into a slot the entity already fills **adds a version to that document and returns the same `fileDocumentId`** — which is what a renewal should do.

If your client expects a new id per upload, this is the one thing to change. Read `fileDocumentId` from the response rather than assuming it is new.

## Limits

<CardGroup cols={2}>
  <Card title="PDF only" icon="file-pdf">
    Anything else is rejected with **400** before the body is buffered.
  </Card>

  <Card title="10 MB maximum" icon="weight-scale">
    A larger file returns **413**.
  </Card>
</CardGroup>

## Visibility

A document uploaded here is visible to **you** and not to your carriers. The agency application's "share with all markets" switch is deliberately not exposed: it fans ownership out to every carrier from a single flag, and this API has no way to undo that.

## Extraction

Turris reads the policy details out of the PDF after upload. That runs asynchronously, so the fields it populates are not on the response to this request — poll [List Documents](/api-reference/v2/downstream/documents/list-documents) or check the [compliance status](/api-reference/v2/downstream/documents/document-compliance) shortly afterwards.

Send an `Idempotency-Key` header. See [Idempotency](/guides/idempotency).


## OpenAPI

````yaml openapi/v2.json POST /v2/downstream/documents
openapi: 3.0.0
info:
  title: Turris Public API
  description: API for managing insurance compliance data
  version: 2.0.0
  contact: {}
servers:
  - url: https://public.api.live.turrisfi.com
    description: Production
  - url: https://public.api.sandbox.turrisfi.com
    description: Sandbox
security: []
tags: []
paths:
  /v2/downstream/documents:
    post:
      tags:
        - downstream/documents
      summary: Upload a compliance document
      description: >-
        Uploads a PDF into one of the four compliance slots — errors and
        omissions, cyber, W9, crime and fidelity — for one of your entities, and
        queues it for data extraction. A slot holds ONE document: uploading into
        a slot the entity already fills adds a version to that document and
        returns the same fileDocumentId, which is what a renewal should do. PDFs
        only, 10 MB maximum. The document is visible to you and not to your
        carriers.
      operationId: DocumentsController_uploadDocument_v2
      parameters:
        - name: idempotency-key
          in: header
          description: UUID to ensure idempotent request processing
          required: false
          schema:
            type: string
            example: 550e8400-e29b-41d4-a716-446655440000
        - name: x-idempotency-key
          in: header
          description: Alternative UUID header for idempotent request processing
          required: false
          schema:
            type: string
            example: 550e8400-e29b-41d4-a716-446655440000
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              allOf:
                - $ref: '#/components/schemas/UploadComplianceDocumentDto'
                - type: object
                  required:
                    - file
                  properties:
                    file:
                      type: string
                      format: binary
                      description: The PDF to upload. 10 MB maximum.
      responses:
        '201':
          description: The document, with its versions
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/DownstreamDocumentResponse'
                  requestId:
                    type: string
                    description: Unique request identifier
                    example: dev-2c5e7cf2-9acf-4c8c-ab2f-b81f39d775a8
                  timestamp:
                    type: string
                    description: Response timestamp
                    example: '2025-11-12T20:49:03.293Z'
                required:
                  - data
                  - requestId
                  - timestamp
        '400':
          description: Missing file, not a PDF, or invalid category
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponseDto'
        '401':
          description: Invalid or missing auth token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponseDto'
        '403':
          description: Your organization is not entitled to the public API
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponseDto'
        '404':
          description: downstreamEntityId is not in your organization
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponseDto'
        '413':
          description: The file is larger than 10 MB
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponseDto'
components:
  schemas:
    UploadComplianceDocumentDto:
      type: object
      properties:
        category:
          type: string
          description: Which compliance slot this document fills.
          enum:
            - E&O
            - Cyber
            - Crime & Fidelity
            - W9
          example: E&O
        downstreamEntityId:
          type: string
          description: >-
            Which of your entities holds this document. Defaults to your own
            organization. Compliance is tracked per legal entity, so a branch
            policy must name the branch.
          example: 6610b3d2c2e0a51b8c0d1f02
      required:
        - category
    DownstreamDocumentResponse:
      type: object
      properties:
        fileDocumentId:
          type: string
          description: Unique identifier of the document
          example: 66a1b2c3d4e5f6a7b8c9d0e3
        name:
          type: string
          description: Display name
          example: E&O Policy
        category:
          type: string
          description: Document category
          enum:
            - W9
            - E&O
            - Cyber
            - Producer Agreement
            - Crime & Fidelity
            - Other Contract
            - Other Document
            - Payment Details
            - License PDF
            - Contract Container Folder Document
            - Surplus Lines
            - custom question upload
            - market onboarding email attachment
            - market application pack source
          example: E&O
        subCategory:
          type: string
          description: Free-text refinement of the category
        versions:
          description: >-
            Stored versions, newest last. No download URL is returned and none
            can be minted.
          type: array
          items:
            $ref: '#/components/schemas/DownstreamDocumentVersionResponse'
        createdAt:
          type: string
          description: ISO 8601 creation timestamp
          example: '2025-01-15T10:30:00.000Z'
        updatedAt:
          type: string
          description: ISO 8601 last-update timestamp
          example: '2026-02-12T09:00:00.000Z'
      required:
        - fileDocumentId
        - name
        - category
        - versions
    ErrorResponseDto:
      type: object
      properties:
        statusCode:
          type: number
          description: HTTP status code
        requestId:
          type: string
          description: Unique request identifier for debugging
        errorType:
          type: string
          description: >-
            Machine-readable error classification. Branch on this rather than on
            `errorMessage`, which is prose and may change. Authentication
            failures returned by our identity provider are forwarded verbatim,
            so a 401 can carry a code outside this list; treat an unrecognised
            value as a generic failure of its HTTP status.
          enum:
            - conflict
            - contact_not_authorized
            - document_exceeds_page_limit
            - downstream_entity_member_exists
            - duplicate_external_id_error
            - duplicate_member_email
            - duplicate_producer_code_error
            - forbidden
            - gateway_timeout
            - inactive_email
            - internal_server_error
            - invalid_email
            - invalid_email_for_invites
            - invalid_organization_category
            - invalid_organization_slug
            - invalid_phone_number
            - invalid_token
            - invite_limit_reached
            - jwt_invalid
            - m2m_client_not_found
            - not_found
            - organization_already_exists
            - organization_slug_already_used
            - payment_required
            - producer_agreement_required
            - product_feature_subscription_required
            - service_unavailable
            - session_authorization_error
            - some_custom_error_string
            - throttled
            - too_many_requests
            - unauthorized
            - unauthorized_client
            - unexpected_400_stytch_error
            - unexpected_403_stytch_error
            - unexpected_404_stytch_error
            - unexpected_error
            - unexpected_stytch_error
            - unprocessable_entity
            - validation_error
          example: validation_error
        errorMessage:
          description: Array of error messages
          type: array
          items:
            type: string
        timestamp:
          type: string
          description: ISO timestamp when the error occurred
        details:
          type: object
          description: Additional error context
      required:
        - statusCode
        - requestId
        - errorType
        - errorMessage
        - timestamp
    DownstreamDocumentVersionResponse:
      type: object
      properties:
        s3VersionId:
          type: string
          description: S3 object version identifier
          example: xN3TmQ8bJ0dY5fLpQ2rV9wK1sA6cE4hZ
        metadataModel:
          type: string
          description: >-
            What kind of extracted metadata exists for this version. The values
            are not returned.
          enum:
            - EAndOPolicy
            - CyberPolicy
            - CrimeFidelity
            - W9
            - ProducerAgreement
            - OtherContract
            - OtherDocument
            - PaymentDetails
            - LicensePdf
          example: EAndOPolicy
        size:
          type: number
          description: Size in bytes
          example: 284913
        mimeType:
          type: string
          description: MIME type
          example: application/pdf
        originalFileName:
          type: string
          description: File name as uploaded
          example: example-eando-2026.pdf
      required:
        - s3VersionId

````

## Related topics

- [Upload Document](/api-reference/v2/file-documents/upload-document.md)
- [Compliance Document Status by Entity](/api-reference/v2/downstream/documents/document-compliance.md)
- [Idempotency](/guides/idempotency.md)
