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

# Prepara un upload di immagine

> Passaggio 1 dell'upload di immagini: ottieni un image_id e un URL PUT presigned per un file locale.

Passaggio uno del [caricamento di immagini](/it/api-reference/uploads/overview.md). Invia
il `filename`, il `content_type` (`image/jpeg`, `image/png` o `image/webp`) e la
dimensione **esatta** del file in `size_bytes`. La risposta restituisce
**`201 Created`** con il nuovo `image_id`, un `upload_url` presigned (valido **1
ora**), il suo `expires_at`, il limite `max_bytes` e gli `allowed_content_types`.

Poi fai il `PUT` dei byte grezzi del file su `upload_url` con lo stesso
`Content-Type` e senza header `Authorization`:

```bash theme={null}
curl -X PUT -H "Content-Type: image/png" --data-binary @photo.png "<upload_url>"
```

Poi chiama [`POST /images/uploads/{image_id}/complete`](/it/api-reference/uploads/complete).

> [!NOTE]
>
> `size_bytes` è obbligatorio e deve essere la dimensione esatta del file (al massimo
> 10,485,760 byte): è firmata in `upload_url`, quindi un `PUT` di qualsiasi altra
> lunghezza viene rifiutato. Puoi avere al massimo **20** upload in attesa di
> completamento; oltre, prepare restituisce
> [`429 too_many_pending_uploads`](/it/guides/errors#too_many_pending_uploads).
> Richiede uno qualsiasi degli scope `images.edit`, `images.transform` o
> `videos.generate`. Gratuito.


## OpenAPI

````yaml api-reference/openapi.json POST /images/uploads/prepare
openapi: 3.1.0
info:
  title: Samsa API
  description: >-
    The Samsa public REST API. Authenticate with an organization API key
    (`Authorization: Bearer samsa_sk_...`) or an OAuth 2.1 access token
    (`Authorization: Bearer samsa_at_...`). 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:
  /images/uploads/prepare:
    post:
      tags:
        - Images
      summary: Start an image upload (get a presigned PUT URL)
      description: >-
        Step 1 of 3 to give a local image file an `image_id`. Send the file's
        EXACT `size_bytes`; it is signed into `upload_url` (valid 1 hour), so a
        PUT of any other length is rejected. Step 2: PUT the raw file bytes to
        it with the same `Content-Type` you send here, for example `curl -X PUT
        -H "Content-Type: image/png" --data-binary @photo.png "<upload_url>"`.
        Step 3: call `POST /images/uploads/{image_id}/complete` within the hour
        — the `image_id` cannot be used anywhere before that, and an upload
        never completed is discarded. Limits: image/jpeg, image/png, image/webp;
        at most 10 MB (10485760 bytes) and 32 megapixels; at most 20 uploads
        awaiting completion per user (`429 too_many_pending_uploads` above
        that). The image belongs to the calling user (the API key's creator, or
        the OAuth user). Free: uploads cost no credits. Requires any one of the
        `images.edit`, `images.transform` or `videos.generate` scopes.
      operationId: prepare_image_upload_images_uploads_prepare_post
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PublicImageUploadPrepareRequest'
        required: true
      responses:
        '201':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicImageUploadPrepareResponse'
        '401':
          description: Missing, invalid, expired, or revoked API key.
          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: Resource not found.
          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'
components:
  schemas:
    PublicImageUploadPrepareRequest:
      properties:
        filename:
          type: string
          maxLength: 255
          minLength: 1
          title: Filename
          description: >-
            Original filename. Stored as the image name; never used as the
            storage key.
        content_type:
          type: string
          title: Content Type
          description: >-
            MIME type of the file — one of: image/jpeg, image/png, image/webp.
            Send the SAME value as the `Content-Type` header of the PUT;
            `complete` refuses bytes that are a different format.
        size_bytes:
          type: integer
          maximum: 10485760
          minimum: 1
          title: Size Bytes
          description: >-
            The EXACT size of the file in bytes (at most 10485760). It is signed
            into `upload_url`: a PUT of any other length is rejected by storage.
            `curl --data-binary @file` sends the file's real length.
        width:
          anyOf:
            - type: integer
              minimum: 1
            - type: 'null'
          title: Width
          description: >-
            Optional width in pixels. Only used to refuse an image over the 32
            MP limit early; the stored dimensions are measured from the uploaded
            bytes at `complete`.
        height:
          anyOf:
            - type: integer
              minimum: 1
            - type: 'null'
          title: Height
          description: Optional height in pixels (see `width`).
      type: object
      required:
        - filename
        - content_type
        - size_bytes
      title: PublicImageUploadPrepareRequest
      description: '`POST /images/uploads/prepare` body — describe the file you will PUT.'
      examples:
        - content_type: image/png
          filename: christmas-card.png
          size_bytes: 4718592
        - content_type: image/jpeg
          filename: product.jpg
          height: 2000
          size_bytes: 1843200
          width: 3000
    PublicImageUploadPrepareResponse:
      properties:
        image_id:
          type: string
          format: uuid
          title: Image Id
          description: >-
            The new image's id. Send it to `POST
            /images/uploads/{image_id}/complete` after the PUT.
        upload_url:
          type: string
          title: Upload Url
          description: >-
            Presigned URL. PUT the raw file bytes here with the header
            `Content-Type: <content_type>` (no Authorization header).
        expires_at:
          type: string
          title: Expires At
          description: >-
            UTC instant (ISO 8601) after which `upload_url` stops accepting the
            PUT (1 hour after prepare).
        max_bytes:
          type: integer
          title: Max Bytes
          description: >-
            Largest accepted file size in bytes; `complete` refuses a bigger
            file.
        allowed_content_types:
          items:
            type: string
          type: array
          title: Allowed Content Types
          description: The accepted MIME types.
      type: object
      required:
        - image_id
        - upload_url
        - expires_at
        - max_bytes
        - allowed_content_types
      title: PublicImageUploadPrepareResponse
      description: >-
        `201` body for `POST /images/uploads/prepare` — where and how to PUT the
        file.
      examples:
        - allowed_content_types:
            - image/jpeg
            - image/png
            - image/webp
          expires_at: '2026-10-08T12:00:00Z'
          image_id: 3f1c2b7e-8d4a-4c1e-9b2f-5a6d7e8f9a0b
          max_bytes: 10485760
          upload_url: >-
            https://<account>.r2.cloudflarestorage.com/user-<id>/3f1c2b7e-8d4a-4c1e-9b2f-5a6d7e8f9a0b.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Signature=...
    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).
    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 (`Authorization: Bearer samsa_sk_...`) or OAuth 2.1
        access token (`Authorization: Bearer samsa_at_...`).

````

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