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

# Prepare a model upload

> Request presigned PUT URLs for a new model's reference images (two-step upload).

Step one of the presigned upload flow for large files. Send the model `name`,
`category`, and metadata for the 1–10 `files` you will upload (the **first** file is
the cover). The response returns a model `id` and one presigned PUT `upload_url` per
file. `PUT` each file to its URL, then call
[`POST /models/{id}/complete`](/api-reference/model-training/complete) with the
uploaded keys to start processing. Requires the `models.write` scope.

<Note>
  Use this two-step flow when images are too large to send inline. For small images
  or remote URLs, [`POST /models`](/api-reference/model-training/create) is simpler.
  Each file's `content_type` is one of `image/jpeg`, `image/png`, `image/webp`;
  provide `size` (≤ 10 MB) when you know it.
</Note>


## OpenAPI

````yaml api-reference/openapi.json POST /models/prepare
openapi: 3.1.0
info:
  title: Samsa API
  description: >-
    The Samsa public REST API. Authenticate with an organization API key as a
    bearer token (`Authorization: Bearer samsa_sk_...`). Errors follow a single
    envelope shape; every response carries an `X-Request-ID`.
  version: 1.0.0
servers:
  - url: https://api.samsa.ai/public/v1
security:
  - BearerAuth: []
paths:
  /models/prepare:
    post:
      tags:
        - Models
      summary: Request presigned upload URLs for a new model's images
      description: >-
        Two-step upload for large files: `prepare` returns presigned PUT URLs
        (one per file, first = cover), you PUT each file, then call `POST
        /models/{id}/complete`. Requires the `models.write` scope.
      operationId: prepare_model_models_prepare_post
      parameters:
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: 'null'
            title: Authorization
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PublicModelPrepareRequest'
      responses:
        '202':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicModelPrepareResponse'
        '401':
          description: Missing, invalid, expired, or revoked API key.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '402':
          description: The organization has no usable subscription.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '403':
          description: The API key lacks the required scope.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '404':
          description: >-
            Model not found (unknown id, another organization, deleted, or not
            public).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '422':
          description: Request validation failed.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '429':
          description: Rate limit exceeded.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '500':
          description: Internal server error.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '503':
          description: Model creation is disabled on this deployment.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
components:
  schemas:
    PublicModelPrepareRequest:
      properties:
        name:
          type: string
          maxLength: 100
          minLength: 1
          title: Name
          examples:
            - Acme Brand Style
        category:
          $ref: '#/components/schemas/PublicModelCategory'
          description: Model category — one of `style`, `object`, `person`, `setting`.
          examples:
            - style
        files:
          items:
            $ref: '#/components/schemas/PublicModelFileMeta'
          type: array
          maxItems: 10
          minItems: 1
          title: Files
          description: Metadata for the 1-10 files you will upload (first = cover).
        instruction:
          anyOf:
            - type: string
              maxLength: 8000
            - type: 'null'
          title: Instruction
          description: Optional free-text guidance for how to use the model.
      type: object
      required:
        - name
        - category
        - files
      title: PublicModelPrepareRequest
      description: >-
        `POST /models/prepare` body — request presigned PUT URLs for large
        files.
    PublicModelPrepareResponse:
      properties:
        id:
          type: string
          format: uuid
          title: Id
          description: The PENDING model's id (send to `/complete`).
        uploads:
          items:
            $ref: '#/components/schemas/PublicUploadSlot'
          type: array
          title: Uploads
        expires_in:
          type: integer
          title: Expires In
          description: Presigned URL lifetime in seconds.
          examples:
            - 3600
      type: object
      required:
        - id
        - uploads
        - expires_in
      title: PublicModelPrepareResponse
      description: '`202` body for `POST /models/prepare` — presigned upload slots.'
    ErrorEnvelope:
      properties:
        error:
          $ref: '#/components/schemas/ErrorDetail'
      type: object
      required:
        - error
      title: ErrorEnvelope
      description: The complete public error body — an ``error`` object wrapper (ADR §5).
    PublicModelCategory:
      type: string
      enum:
        - style
        - object
        - person
        - setting
      title: PublicModelCategory
      description: >-
        Public model category (ADR §8.2).


        Maps to the internal ``ModelType`` stored in ``models.type`` (NOT the
        separate

        ``models.category`` column). ``setting`` is the public name for internal

        ``SCENE``; the others are a straight upper/lower-case swap. Internal
        ``BASE`` is

        never exposed publicly.
    PublicModelFileMeta:
      properties:
        filename:
          anyOf:
            - type: string
            - type: 'null'
          title: Filename
          description: Original filename (informational).
          examples:
            - logo.png
        content_type:
          type: string
          title: Content Type
          description: >-
            MIME type of the file to upload — one of: image/jpeg, image/png,
            image/webp.
          default: image/webp
          examples:
            - image/png
        size:
          anyOf:
            - type: integer
              minimum: 0
            - type: 'null'
          title: Size
          description: File size in bytes (optional; must be ≤ 10 MB when provided).
          examples:
            - 204800
      type: object
      title: PublicModelFileMeta
      description: One presigned-upload slot request (`POST /models/prepare`).
    PublicUploadSlot:
      properties:
        key:
          type: string
          title: Key
          description: R2 object key to send back in `uploaded_keys`.
        upload_url:
          type: string
          title: Upload Url
          description: Presigned PUT URL (expires with `expires_in`).
        index:
          type: integer
          title: Index
          description: Slot index (0 = primary/cover).
      type: object
      required:
        - key
        - upload_url
        - index
      title: PublicUploadSlot
      description: A presigned PUT slot returned by `POST /models/prepare`.
    ErrorDetail:
      properties:
        type:
          type: string
          title: Type
          examples:
            - authentication_error
        code:
          type: string
          title: Code
          examples:
            - invalid_api_key
        message:
          type: string
          title: Message
          examples:
            - The provided API key is invalid, expired, or revoked.
        request_id:
          type: string
          title: Request Id
          examples:
            - 8f14e45fceea167a5a36dedd4bea2543
        param:
          anyOf:
            - type: string
            - type: 'null'
          title: Param
          description: Present on validation errors — names the offending field.
          examples:
            - aspect_ratio
      type: object
      required:
        - type
        - code
        - message
        - request_id
      title: ErrorDetail
      description: The ``error`` object of the public envelope (ADR §5).
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      description: >-
        Organization API key as a bearer token: `Authorization: Bearer
        samsa_sk_...`.

````