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

# Create a media upload session

> Step one of three. Returns an upload token and a direct upload URL; send the file bytes to that URL with the returned headers, then attach the token to a product. The URL points at object storage, not at this API. A token is consumed by a successful attach and cannot be reused; a rejected attach leaves it usable.



## OpenAPI

````yaml /api-reference/commerce-v1.openapi.json post /v1/commerce/uploads
openapi: 3.0.3
info:
  description: >-
    Public REST API for COPE vendor integrations. Authenticate with a COPE API
    key or Clerk bearer token and call the endpoints described below.
  title: COPE Public API
  version: v1
servers:
  - description: Production
    url: https://api.cope.com
security:
  - cope_sk: []
paths:
  /v1/commerce/uploads:
    post:
      tags:
        - Products
      summary: Create a media upload session
      description: >-
        Step one of three. Returns an upload token and a direct upload URL; send
        the file bytes to that URL with the returned headers, then attach the
        token to a product. The URL points at object storage, not at this API. A
        token is consumed by a successful attach and cannot be reused; a
        rejected attach leaves it usable.
      operationId: product_media.uploads.create
      requestBody:
        content:
          application/json:
            examples:
              product_image:
                summary: Open a session for a cover image — step one of three
                value:
                  blob:
                    byte_size: 184320
                    checksum: FjvIv22QWqc6IUNr/yWgkw==
                    content_type: image/png
                    filename: quiet-launch-cover.png
              downloadable_file:
                summary: >-
                  Open a session for a file the buyer downloads — step one of
                  three
                value:
                  blob:
                    byte_size: 2097152
                    checksum: w2cuKIKdgxG8bCxlSz84nw==
                    content_type: application/pdf
                    filename: quiet-launch-playbook.pdf
            schema:
              properties:
                blob:
                  properties:
                    byte_size:
                      description: Exact size of the file in bytes, at most 104857600.
                      maximum: 104857600
                      minimum: 1
                      type: integer
                    checksum:
                      description: >-
                        Base64-encoded MD5 digest of the file, the Active
                        Storage convention: `openssl dgst -md5 -binary FILE |
                        base64`. It is not validated here — a wrong value is
                        rejected by storage when the bytes are uploaded.
                      type: string
                    content_type:
                      description: >-
                        Media type of the file. Each attach endpoint checks it
                        again against its own allow-list: images accept image
                        types only, downloadable files accept the full list.
                      enum:
                        - image/png
                        - image/jpeg
                        - image/gif
                        - image/webp
                        - application/pdf
                        - text/plain
                        - application/rtf
                        - text/rtf
                        - video/mp4
                        - video/quicktime
                        - video/webm
                        - audio/mpeg
                        - audio/mp4
                        - audio/aac
                        - audio/wav
                        - audio/x-wav
                        - audio/flac
                        - audio/ogg
                        - audio/x-ms-wma
                        - application/epub+zip
                        - application/x-mobipocket-ebook
                        - application/vnd.amazon.ebook
                        - application/x-fictionbook+xml
                        - image/vnd.djvu
                        - application/x-ibooks+zip
                        - application/zip
                        - application/x-zip-compressed
                      type: string
                    filename:
                      description: File name, including its extension.
                      type: string
                  required:
                    - filename
                    - content_type
                    - byte_size
                    - checksum
                  type: object
              required:
                - blob
              type: object
      responses:
        '201':
          content:
            application/json:
              schema:
                additionalProperties: false
                properties:
                  data:
                    additionalProperties: false
                    properties:
                      direct_upload:
                        additionalProperties: false
                        properties:
                          headers:
                            additionalProperties:
                              type: string
                            description: >-
                              Send every returned header verbatim with the
                              upload request. The set depends on the storage
                              service: Content-Type is always present, and
                              object storage adds headers such as Content-MD5
                              that are signed into the URL, so a request without
                              them is refused.
                            properties:
                              Content-Type:
                                type: string
                            required:
                              - Content-Type
                            type: object
                          url:
                            type: string
                        required:
                          - url
                          - headers
                        type: object
                      upload_token:
                        type: string
                    required:
                      - upload_token
                      - direct_upload
                    type: object
                required:
                  - data
                type: object
          description: Successful response
        '400':
          content:
            application/problem+json:
              examples:
                missing_parameter:
                  summary: Missing required parameter
                  value:
                    code: invalid_request
                    detail: null
                    errors:
                      - code: missing
                        detail: 'param is missing or the value is empty: blob'
                        param: blob
                    request_id: req_123
                    status: 400
                    title: Invalid Request
                    type: https://docs.cope.com/errors/invalid_request
                unparsable_request:
                  summary: Unparsable request
                  value:
                    code: invalid_request
                    detail: >-
                      The request could not be parsed. Check the query string
                      and the request body.
                    request_id: req_123
                    status: 400
                    title: Invalid Request
                    type: https://docs.cope.com/errors/invalid_request
              schema:
                $ref: '#/components/schemas/PublicProblemDetail'
          description: Invalid request
        '401':
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/PublicProblemDetail'
          description: Missing or invalid bearer token
        '403':
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/PublicProblemDetail'
          description: Bearer token is not authorized for this route
        '422':
          content:
            application/problem+json:
              examples:
                validation_failed:
                  summary: Validation failed
                  value:
                    code: validation_failed
                    detail: null
                    errors:
                      - code: blank
                        detail: Name can't be blank
                        param: name
                    request_id: req_123
                    status: 422
                    title: Validation Failed
                    type: https://docs.cope.com/errors/validation_failed
              schema:
                $ref: '#/components/schemas/PublicProblemDetail'
          description: Public commerce validation problem
      security:
        - cope_sk: []
components:
  schemas:
    PublicProblemDetail:
      additionalProperties: false
      properties:
        code:
          type: string
        detail:
          nullable: true
          type: string
        errors:
          items:
            additionalProperties: false
            properties:
              code:
                type: string
              detail:
                type: string
              param:
                type: string
            required:
              - code
              - detail
            type: object
          type: array
        request_id:
          type: string
        status:
          type: integer
        title:
          type: string
        type:
          type: string
      required:
        - type
        - title
        - status
        - code
        - request_id
      type: object
  securitySchemes:
    cope_sk:
      description: >-
        Bearer credential for the public API. Vendor integrations should send a
        live COPE API key (`ck_live_*`; keys issued earlier as `cope_sk_live_*`
        keep working). Clerk bearer tokens are also accepted when paired with
        `X-Cope-Business-Id`.
      scheme: bearer
      type: http

````