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

# Attach a downloadable file

> Step three of three. A product holds at most 5 downloadable files. The content type is checked again here against the file allow-list. Attaching media returns an approved product to review, taking it off sale until it is approved again.



## OpenAPI

````yaml /api-reference/commerce-v1.openapi.json post /v1/commerce/products/{product_id}/attachments
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/products/{product_id}/attachments:
    post:
      tags:
        - Products
      summary: Attach a downloadable file
      description: >-
        Step three of three. A product holds at most 5 downloadable files. The
        content type is checked again here against the file allow-list.
        Attaching media returns an approved product to review, taking it off
        sale until it is approved again.
      operationId: product_media.attachments.create
      parameters:
        - description: product_id public identifier.
          example: prod_A1b2C3d4
          in: path
          name: product_id
          required: true
          schema:
            example: prod_A1b2C3d4
            pattern: ^prod_[A-Za-z0-9]{8,32}$
            type: string
      requestBody:
        content:
          application/json:
            examples:
              attach_file:
                summary: >-
                  Attach the uploaded file, renamed, and open it to buyers
                  already in their trial
                value:
                  access_pending: false
                  access_trial: true
                  filename: Quiet Launch Playbook.pdf
                  upload_token: <upload_token from POST /v1/commerce/uploads>
            schema:
              properties:
                access_pending:
                  description: >-
                    Grants buyers access to this file while their payment is
                    still pending.
                  type: boolean
                access_trial:
                  description: Grants buyers access to this file during a trial period.
                  type: boolean
                filename:
                  description: Overrides the file name stored with the upload.
                  type: string
                upload_token:
                  description: >-
                    Token returned by the upload session, after the bytes have
                    been uploaded.
                  type: string
              required:
                - upload_token
              type: object
      responses:
        '201':
          content:
            application/json:
              schema:
                additionalProperties: false
                properties:
                  data:
                    additionalProperties: false
                    properties:
                      access_pending:
                        type: boolean
                      access_trial:
                        type: boolean
                      byte_size:
                        nullable: true
                        type: integer
                      content_type:
                        nullable: true
                        type: string
                      filename:
                        type: string
                      id:
                        example: att_A1b2C3d4E5f6G7h8
                        pattern: ^att_[A-Za-z0-9]{8,32}$
                        type: string
                      kind:
                        type: string
                      url:
                        nullable: true
                        type: string
                    required:
                      - id
                      - kind
                      - filename
                      - content_type
                      - byte_size
                      - url
                      - access_trial
                      - access_pending
                    type: object
                required:
                  - data
                type: object
          description: Successful response
        '400':
          content:
            application/problem+json:
              examples:
                upload_token_rejected:
                  summary: Rejected upload token
                  value:
                    code: invalid_request
                    detail: null
                    errors:
                      - code: invalid
                        detail: upload_token has already been consumed
                        param: upload_token
                    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
        '404':
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/PublicProblemDetail'
          description: Resource not found
        '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

````