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

# Complete an upload

> Finalize an image upload after the file has been uploaded to the pre-signed URL.



## OpenAPI

````yaml /openapi.json post /v1/uploads/{emailAssetId}/complete
openapi: 3.1.0
info:
  title: Loops OpenAPI Spec
  description: This is the OpenAPI Spec for the [Loops API](https://loops.so/docs/api).
  version: 1.21.0
servers:
  - url: https://app.loops.so/api
security: []
tags:
  - name: API key
  - name: Audience segments
    description: View audience segments
  - name: Campaigns
    description: Create and manage email campaigns
  - name: Campaign groups
    description: Organize campaigns into groups
  - name: Components
    description: View email components
  - name: Configuration
    description: View configuration settings
  - name: Contacts
    description: Manage contacts in your audience
  - name: Contact properties
    description: Manage contact properties
  - name: Email messages
    description: Manage email message content for campaigns
  - name: Events
    description: Trigger workflows with events
  - name: Event patterns
    description: View workflow event patterns
  - name: Mailing lists
    description: View mailing lists
  - name: Themes
    description: View email themes
  - name: Transactional emails
    description: Create, manage, and send transactional emails
  - name: Transactional groups
    description: Organize transactional emails into groups
  - name: Uploads
    description: Upload image assets
  - name: Workflows
    description: View and mutate workflow graphs
  - name: Workflow nodes
    description: View and mutate workflow nodes
paths:
  /v1/uploads/{emailAssetId}/complete:
    parameters:
      - name: emailAssetId
        in: path
        required: true
        description: >-
          The `emailAssetId` returned when the upload was created via `POST
          /v1/uploads`.
        schema:
          type: string
    post:
      tags:
        - Uploads
      summary: Complete an upload
      description: >-
        Finalize an image upload after the file has been uploaded to the
        pre-signed URL. Returns the public URL of the uploaded image asset.
      responses:
        '200':
          description: Upload completed.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CompleteUploadResponse'
        '400':
          description: >-
            Upload id is missing or the uploaded file has an unsupported content
            type.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UploadFailureResponse'
        '401':
          description: Invalid API key or content API not enabled for this team.
        '404':
          description: Upload not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UploadFailureResponse'
        '405':
          description: Wrong HTTP request method.
        '429':
          description: Upload limit exceeded.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UploadLimitExceededFailureResponse'
      security:
        - apiKey: []
components:
  schemas:
    CompleteUploadResponse:
      type: object
      properties:
        emailAssetId:
          type: string
          description: The ID of the created asset.
        finalUrl:
          type: string
          description: The public URL of the uploaded asset.
      required:
        - emailAssetId
        - finalUrl
    UploadFailureResponse:
      type: object
      properties:
        message:
          type: string
        supportedContentTypes:
          type: array
          description: >-
            Present when the request was rejected for an unsupported
            `contentType`. Lists the accepted MIME types.
          items:
            type: string
        maxBytes:
          type: integer
          description: >-
            Present when the upload exceeds the size limit. The maximum allowed
            size in bytes.
      required:
        - message
    UploadLimitExceededFailureResponse:
      type: object
      properties:
        message:
          type: string
          examples:
            - >-
              Upload limit exceeded: max 50 uploads per 24 hours. Please contact
              support if you need to increase your upload limit.
        maxUploads:
          type: integer
          description: The maximum number of uploads allowed per window.
          examples:
            - 50
        windowHours:
          type: integer
          description: The number of hours in the upload limit window.
          examples:
            - 24
  securitySchemes:
    apiKey:
      type: http
      scheme: bearer

````

## Related topics

- [API Introduction](/docs/api-reference/intro.md)
- [Campaigns API examples](/docs/api-reference/examples/campaigns.md)
- [Transactional email API examples](/docs/api-reference/examples/transactional-emails.md)
- [Create an upload](/docs/api-reference/create-upload.md)
- [Uploading a custom email](/docs/creating-emails/uploading-custom-email.md)
