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

# Upload a file

> Upload a file to attach elsewhere by id. Send `multipart/form-data` with a `file` part and a `purpose`. `identity_document` uploads are an owner's passport or government ID: attach one to a `document` requirement (`document` on fulfill) or directly at company create (`shareholders[].passport`). `additional_document` uploads answer a form's file field: pass the file id as that field's value on fulfill. Uploads are single-use and write-only - the response carries no download URL and the contents can never be read back through the API. PDF, JPEG or PNG, 10MB max, and images at most 8000px per side. Content is verified against the declared type.



## OpenAPI

````yaml /partner/openapi.yaml post /files
openapi: 3.1.0
info:
  title: Clemta Partner API
  description: |
    The Clemta partner surface. Authenticate with your API key as a bearer
    token (`Authorization: Bearer clmt_live_` or `clmt_test_`). Keys with
    the `clmt_test_` prefix operate in sandbox mode (`livemode: false`): test
    data never reaches fulfillment or billing.

    Versioning is date-based: pass `Clemta-Version` to pin a
    version, omit it to run on your account's pinned default. The effective
    version is echoed back on every response.
  version: '2026-08-13'
servers:
  - url: https://api.clemta.com/v1
    description: >
      Single host for both modes: `clmt_test_` keys operate in sandbox mode,
      `clmt_live_` keys in live mode.
security:
  - apiKey: []
tags:
  - name: Identity
    description: Identify the calling API key.
  - name: Accounts
    description: >-
      Create and read customer accounts - the incorporators companies are
      created under.
  - name: Companies
    description: Create and read client companies.
  - name: Service orders
    description: Order services against a company and follow their fulfilment.
  - name: Products
    description: The catalog you can offer, at your wholesale prices.
  - name: Tax filings
    description: >-
      Federal and state tax filings on your companies, opened by your client
      against the company's entitlements and worked by Clemta. Read-only. Follow
      them with the tax_filing.* events.
  - name: Files
    description: >-
      Documents Clemta publishes on your companies - formation deliverables,
      filed forms, letters. Read-only. Client KYC uploads are write-only and
      never listed.
  - name: Requirements
    description: >-
      Everything needed from you or your client - identity documents,
      service-order forms, Clemta's asks - as one resolvable resource. Fulfill
      over the API or hand your client a hosted link.
  - name: Status tracking
    description: >-
      End-customer status links - keyless, read-only access to a company's live
      status.
  - name: Events
    description: Poll the partner event stream.
  - name: Webhooks
    description: >-
      Events we deliver to your endpoint, and how to verify them. Each webhook
      below is a request WE send to you. Respond 2xx to acknowledge. Deliveries
      are signed and retried with exponential backoff over multiple days until
      acknowledged. Answer `410 Gone` to have the endpoint disabled and
      deliveries stopped. A `Retry-After` header on a `429` or `503` pushes the
      next attempt back. An endpoint that fails continuously for days is
      disabled automatically and the workspace owner is emailed - no events are
      lost, the stream stays available on `GET /v1/events`.


      ## Verifying a delivery


      Deliveries are signed per the [Standard
      Webhooks](https://www.standardwebhooks.com) specification, carrying BOTH
      schemes in one header: a symmetric `v1` HMAC (verify with your endpoint
      secret and any standardwebhooks library) and an asymmetric `v1a` ed25519
      signature (verify with the endpoint's public key, no shared secret held).
      Use whichever suits your setup.


      Every endpoint has its OWN signing secret (`whsec_...`), shown once when
      you create the endpoint. Each delivery carries three headers:


      - `Clemta-Webhook-Id` - the event id. Stable across retries: use it as an
      idempotency key so a redelivered event is processed once.

      - `Clemta-Webhook-Timestamp` - unix seconds of THIS attempt (a retry
      carries a fresh one).

      - `Clemta-Webhook-Signature` - a space-delimited list of `v1,<base64>`
      signatures. More than one while a secret rotation's overlap window is
      open, one per active secret.


      Each is also sent under its bare Standard Webhooks name (`webhook-id`,
      `webhook-timestamp`, `webhook-signature`) with the same value, which is
      what off-the-shelf standardwebhooks libraries look up.


      To verify by hand:


      1. Build the signed content by joining the id, the timestamp, and the raw
      request body with literal `.` separators: `{id}.{timestamp}.{body}`. Use
      the body exactly as received - do not re-serialize the JSON.

      2. Base64-decode your endpoint secret after the `whsec_` prefix. That is
      the HMAC key.

      3. Compute HMAC-SHA256 over the signed content, base64 encode it, and
      compare it against each `v1,` entry in constant time. Accept if any
      matches, otherwise reject.

      4. Check the timestamp is within 5 minutes of now, to reject replays.


      Because the secret is unique to your endpoint, a signature can only be
      verified by you - a delivery meant for another endpoint cannot be made to
      verify here. Keep the secret confidential. If it leaks, roll the
      endpoint's secret from the Webhooks page of your partner dashboard.
  - name: Sandbox
    description: >-
      Test-key-only endpoints for rehearsing event flows. Trigger a lifecycle
      transition on a test company and receive the matching webhook, without
      waiting for a real formation to progress.
paths:
  /files:
    post:
      tags:
        - Files
      summary: Upload a file
      description: >-
        Upload a file to attach elsewhere by id. Send `multipart/form-data` with
        a `file` part and a `purpose`. `identity_document` uploads are an
        owner's passport or government ID: attach one to a `document`
        requirement (`document` on fulfill) or directly at company create
        (`shareholders[].passport`). `additional_document` uploads answer a
        form's file field: pass the file id as that field's value on fulfill.
        Uploads are single-use and write-only - the response carries no download
        URL and the contents can never be read back through the API. PDF, JPEG
        or PNG, 10MB max, and images at most 8000px per side. Content is
        verified against the declared type.
      operationId: createFile
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              required:
                - file
                - purpose
              properties:
                file:
                  type: string
                  format: binary
                purpose:
                  type: string
                  enum:
                    - identity_document
                    - formation_document
                    - additional_document
                    - tax_form_1099
                    - business_logo
                    - business_icon
      responses:
        '201':
          description: The uploaded file.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/File'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/RateLimited'
components:
  schemas:
    File:
      type: object
      description: >-
        A file: either a document Clemta published on one of your companies
        (`source: operations` - Articles, an EIN letter, a filed form - download
        the bytes from the content endpoint) or one you uploaded (`source:
        upload` - write-only, attach it by id). Nothing about storage is ever
        exposed - no URLs, no keys. Uploaded contents cannot be read back.
      required:
        - object
        - id
        - name
        - livemode
        - created_at
      properties:
        object:
          type: string
          enum:
            - file
          description: Entity name.
        id:
          type: string
          pattern: ^file_[0-9A-Za-z]{22}$
          example: file_0346sFPEvSkJvY8vt14NNw
        company:
          type: string
          pattern: ^cmp_[0-9A-Za-z]{22}$
          description: >-
            The company this document belongs to. Absent on an upload not yet
            attached.
        name:
          type: string
          description: The document's filename, extension included.
          example: Articles_of_Incorporation.pdf
        content_type:
          type: string
          example: application/pdf
        size:
          type: integer
          format: int64
          description: Size in bytes, when known.
        purpose:
          type: string
          enum:
            - identity_document
            - formation_document
            - additional_document
            - tax_form_1099
            - business_logo
            - business_icon
          description: What an uploaded file is for. Absent on documents Clemta published.
        source:
          type: string
          enum:
            - operations
            - upload
          description: >-
            Who put the file here. `operations` - a deliverable we published,
            its bytes downloadable from the content endpoint. `upload` - you
            sent it (POST /v1/files), write-only: reference it by id, its
            contents can never be read back.
        url:
          type: string
          description: >-
            Where the file's contents can be downloaded, with your API key.
            Present only when the purpose allows downloading - Clemta-published
            deliverables, never your own uploads.
        consumed:
          type: boolean
          description: True once an upload has been attached. Uploads are single-use.
        livemode:
          type: boolean
        created_at:
          type: string
          format: date-time
    Error:
      type: object
      description: >-
        Error response: a stable machine-readable `code`, human-readable
        `title`/`detail`, and for validation failures an `errors` array naming
        every violating field.
      required:
        - type
        - title
        - status
        - code
      additionalProperties: false
      properties:
        type:
          type: string
          description: Link to the error reference entry for this code.
          example: https://docs.clemta.com/partner/errors#resource_already_exists
        title:
          type: string
          description: Short human summary of the error class.
        status:
          type: integer
          format: int32
          minimum: 100
          maximum: 599
          description: HTTP status code, also included in the body.
        code:
          type: string
          enum:
            - api_key_invalid
            - api_key_expired
            - insufficient_scope
            - ip_address_not_allowed
            - invalid_request
            - invalid_api_version
            - resource_missing
            - method_not_allowed
            - test_mode_only
            - resource_already_exists
            - idempotency_key_mismatch
            - idempotency_key_in_use
            - request_too_large
            - billing_account_inactive
            - entitlement_required
            - rate_limit
            - api_error
          description: Stable machine-readable code - branch on this, never on `detail`.
        detail:
          type: string
          description: Human-readable specifics of this occurrence, wording may change.
        request_id:
          type: string
          description: >-
            Identifier of this request. Quote it in a support request so we can
            trace the failure.
        errors:
          type: array
          description: 'Present on validation failures: one entry per violating field.'
          items:
            type: object
            required:
              - reason
            additionalProperties: false
            properties:
              reason:
                type: string
              location:
                type: string
                description: JSONPath of the failing field, e.g. `$.name`.
              validation_type:
                type: string
                description: Schema keyword that failed.
              how_to_fix:
                type: string
  responses:
    BadRequest:
      description: Malformed request (e.g. unknown `Clemta-Version`).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Unauthorized:
      description: Missing, invalid, revoked, or grace-expired API key.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    RateLimited:
      description: Rate limit exceeded, retry after the `Retry-After` header.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  securitySchemes:
    apiKey:
      type: http
      scheme: bearer
      description: >
        Your API key, e.g. `Authorization: Bearer clmt_test_`. Live keys use the
        `clmt_live_` prefix.

````