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

# Generate presigned URL for model upload

> Generate a presigned URL for uploading a custom model archive.

This is step 1 of the presigned URL workflow:
1. POST /models/uploads → Returns presigned_url + upload_id
2. PUT presigned_url with model archive (client uploads directly to S3)
3. POST /models/uploads/{upload_id}/confirm → Validates and creates model

The model will be stored at the organization level and can be enabled
in any namespace within the organization.

**Availability**: custom model upload is an **enterprise-tier** feature —
requests from other account tiers receive a 403. Contact support or
upgrade your plan to enable it (this gate was previously
undocumented and only discoverable by hitting the 403).



## OpenAPI

````yaml post /v1/models/uploads
openapi: 3.1.0
info:
  title: Mixpeek API
  description: >-
    This is the Mixpeek API, providing access to various endpoints for data
    processing and retrieval.
  termsOfService: https://mixpeek.com/terms
  contact:
    name: Mixpeek Support
    url: https://mixpeek.com/contact
    email: info@mixpeek.com
  version: '0.82'
servers:
  - url: https://api.mixpeek.com
    description: Production
security:
  - BearerAuth: []
paths:
  /v1/models/uploads:
    post:
      tags:
        - Models
      summary: Generate presigned URL for model upload
      description: >-
        Generate a presigned URL for uploading a custom model archive.


        This is step 1 of the presigned URL workflow:

        1. POST /models/uploads → Returns presigned_url + upload_id

        2. PUT presigned_url with model archive (client uploads directly to S3)

        3. POST /models/uploads/{upload_id}/confirm → Validates and creates
        model


        The model will be stored at the organization level and can be enabled

        in any namespace within the organization.


        **Availability**: custom model upload is an **enterprise-tier** feature
        —

        requests from other account tiers receive a 403. Contact support or

        upgrade your plan to enable it (this gate was previously

        undocumented and only discoverable by hitting the 403).
      operationId: generate_upload_url_v1_models_uploads_post
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateModelUploadRequest'
        description: >-
          Keys this body does not declare are refused with 422 extra_forbidden
          naming the accepted keys (since 2026-11-02).
        x-unknown-keys:
          until: '2026-11-02'
          then: 422 extra_forbidden
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ModelPresignedURLResponse'
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '422':
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: Too Many Requests
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '503':
          description: Service Unavailable
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      security:
        - BearerAuth: []
components:
  schemas:
    CreateModelUploadRequest:
      properties:
        name:
          type: string
          pattern: ^[a-zA-Z][a-zA-Z0-9_]{2,63}$
          title: Name
          description: >-
            Model name: 3-64 chars, letters/numbers/underscores, starts with a
            letter (no hyphens or spaces)
          examples:
            - custom_embedder
            - sentiment_model
            - image_classifier
        version:
          type: string
          pattern: ^\d+\.\d+\.\d+$
          title: Version
          description: Semantic version string
          examples:
            - 1.0.0
            - 2.1.3
            - 0.0.1
        model_format:
          type: string
          enum:
            - safetensors
            - onnx
            - pytorch
            - huggingface
          title: Model Format
          description: Format of the model weights
          examples:
            - safetensors
            - onnx
            - pytorch
            - huggingface
        description:
          anyOf:
            - type: string
              maxLength: 500
            - type: 'null'
          title: Description
          description: Optional description of the model
        file_size_bytes:
          anyOf:
            - type: integer
              maximum: 5368709120
              exclusiveMinimum: 0
            - type: 'null'
          title: File Size Bytes
          description: Expected file size in bytes for quota validation
        presigned_url_expiration:
          type: integer
          maximum: 86400
          minimum: 60
          title: Presigned Url Expiration
          description: Presigned URL expiration time in seconds (1-24 hours)
          default: 3600
        resource_requirements:
          $ref: '#/components/schemas/ModelResourceRequirements'
          description: Resource requirements for model deployment
        framework:
          anyOf:
            - type: string
            - type: 'null'
          title: Framework
          description: ML framework (e.g., sentence-transformers, transformers)
        task_type:
          anyOf:
            - type: string
            - type: 'null'
          title: Task Type
          description: Task type (e.g., embedding, classification, generation)
        source:
          type: string
          enum:
            - customer
            - mixpeek
            - system
          title: Source
          description: >-
            Who is uploading: 'customer' (default) or 'mixpeek' (professional
            services). Mixpeek-sourced models are non-exportable by default.
          default: customer
      type: object
      required:
        - name
        - version
        - model_format
      title: CreateModelUploadRequest
      description: >-
        Request to generate a presigned URL for model archive upload.


        This is step 1 of the presigned URL workflow:

        1. POST /models/uploads → Returns presigned_url + upload_id

        2. PUT presigned_url with model archive (client uploads directly to S3)

        3. POST /models/uploads/{upload_id}/confirm → Validates and creates
        model


        Requirements:
            - name: Model name (e.g., 'my_custom_embedder')
            - version: Semantic version (e.g., '1.0.0')
            - model_format: Format of the model weights
            - file_size_bytes: Expected archive size for quota validation
    ModelPresignedURLResponse:
      properties:
        upload_id:
          type: string
          title: Upload Id
          description: Upload ID to use when confirming
        presigned_url:
          type: string
          title: Presigned Url
          description: S3 presigned URL for PUT upload
        required_content_type:
          type: string
          title: Required Content Type
          description: >-
            Content-Type the presigned PUT is signed with. Send this exact value
            as the Content-Type header on the upload PUT, or object storage
            rejects it with 403 SignatureDoesNotMatch. Parity with the extractor
            upload.
          default: application/gzip
        s3_key:
          type: string
          title: S3 Key
          description: S3 object key where file will be stored
        expires_at:
          type: string
          format: date-time
          title: Expires At
          description: When the presigned URL expires
        organization_id:
          type: string
          title: Organization Id
          description: Organization ID
        name:
          type: string
          title: Name
          description: Model name
        version:
          type: string
          title: Version
          description: Model version
        model_format:
          type: string
          enum:
            - safetensors
            - onnx
            - pytorch
            - huggingface
          title: Model Format
          description: Model format
      type: object
      required:
        - upload_id
        - presigned_url
        - s3_key
        - expires_at
        - organization_id
        - name
        - version
        - model_format
      title: ModelPresignedURLResponse
      description: >-
        Response containing presigned URL for model upload.


        After receiving this response:

        1. PUT the model archive to `presigned_url` with the
        `required_content_type`
           header (the value the URL is signed with)
        2. Call POST /models/uploads/{upload_id}/confirm to finalize
    ErrorResponse:
      properties:
        success:
          type: boolean
          title: Success
          description: Always false for error responses
          default: false
        status:
          type: integer
          title: Status
          description: HTTP status code for this error
        error:
          $ref: '#/components/schemas/ErrorDetail'
          description: Error details payload
      type: object
      required:
        - status
        - error
      title: ErrorResponse
      description: Error response model.
      examples:
        - error:
            details:
              id: ns_123
              resource: namespace
            message: Namespace not found
            type: NotFoundError
          status: 404
          success: false
    ModelResourceRequirements:
      properties:
        num_cpus:
          type: number
          maximum: 64
          minimum: 0.1
          title: Num Cpus
          description: Number of CPUs
          default: 1
        num_gpus:
          type: integer
          maximum: 8
          minimum: 0
          title: Num Gpus
          description: Number of GPUs
          default: 0
        memory:
          type: integer
          title: Memory
          description: Memory in bytes (default 4GB)
          default: 4294967296
      type: object
      title: ModelResourceRequirements
      description: Resource requirements for model deployment.
    ErrorDetail:
      properties:
        message:
          type: string
          title: Message
          description: Human-readable error message
        type:
          type: string
          title: Type
          description: Stable error type identifier (machine-readable)
        code:
          anyOf:
            - type: string
            - type: 'null'
          title: Code
          description: >-
            Fine-grained error code for programmatic handling (e.g.,
            namespace_name_taken, feature_extractor_not_found). Present only
            when consumers may need to branch on a specific error condition.
        details:
          anyOf:
            - additionalProperties: true
              type: object
            - type: 'null'
          title: Details
          description: >-
            Optional structured details to help debugging (validation errors,
            IDs, etc.)
      type: object
      required:
        - message
        - type
      title: ErrorDetail
      description: Error detail model.
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      description: >-
        Mixpeek API key, sent as `Authorization: Bearer mxp_sk_...`. Create one
        in Studio under Settings → API Keys, or with an admin key via `POST
        /v1/organizations/users/{user_email}/api-keys`. A missing, malformed,
        unknown, revoked, inactive or expired key returns 401; a key without the
        permission, scope or plan an operation needs returns 403.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.