Work with files

Files in Commerce are durable assets with stable file_... IDs. Instead of scattering raw storage URLs across your products and support flows, you upload bytes once, keep the returned file ID, and let Commerce control access, sharing, and lifecycle. This guide shows you when to upload directly, when to delegate uploads, how to share files safely, and which file-specific failures you should plan for.

Prerequisites

  • A file purpose chosen before upload:
    • product_download for downloadable product assets.
    • product_image for product images.
    • product_video for product videos.
    • products_import for product-catalog CSV imports with the required import schema and no more than 10,000 data rows.
    • support_document for support attachments and evidence.
  • A plan for where the resulting file ID will live. Product media should store returned file IDs via Create a product or Update a product, not raw third-party URLs.

Choose the right workflow

NeedUseWhy
Your backend already has the bytesUpload a fileMultipart upload from your server.
A customer, supplier, or reviewer should send the file themselvesCreate an upload requestCommerce returns a purpose-bound upload URL for one delegated upload.
You need revocable public access to a stored fileCreate a file linkCommerce gives you a time-boxed or access-limited public URL.

Use Download file contents when delivery should stay behind your own server. Stream delivery returns the bytes in the authenticated response; redirect delivery returns a short-lived download URL in the Location header. This is the right delivery path for product_download, products_import, and support_document, because file links only support product_image and product_video.

Send bytes to Commerce

Choose the upload path that matches who is actually holding the file.

Use direct upload when your backend already has the bytes—for example, when an internal admin tool uploads product artwork or when your own service is syncing downloadable assets.

Upload from your server

POST
/files/create
curl https://api.zebo.dev/files/create \
  -H "Authorization: Bearer $COMMERCE_API_KEY" \
  -H "Idempotency-Key: upload-hero-image-001" \
  -F "purpose=product_image" \
  -F "title=Hero image" \
  -F 'custom_data={"product_ref":"SKU-12345"}' \
  -F "file=@./hero.png;type=image/png"

Use custom_data for your own string key-value data. metadata is returned by the API and cannot be supplied.

The response gives you a stable file.id. Store that ID on the Commerce resource that needs the asset, and reuse idempotency keys when retries might happen.

Share files safely

File links are for controlled public access. They work for product_image and product_video, and they let you set delivery behavior, expiry, and access limits.

The inline example keeps allow_download: true because attachment disposition is valid only when downloads are allowed. File links expire after 24 hours by default, and max_accesses: 0 means unlimited successful opens.

Create a public file link

POST
/file_links/create
curl https://api.zebo.dev/file_links/create \
  -H "Authorization: Bearer $COMMERCE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "file_id": "file_4q6YcQk1RzPv2mDa8nFw0sHu",
    "delivery": {
      "mode": "inline"
    },
    "access": {
      "allow_download": true,
      "max_accesses": 25
    },
    "expires_at": "2026-06-06T12:30:00Z"
  }'

Give the returned top-level url to the consumer. They open that URL via Open a file link. If access should end early, revoke it with Revoke a file link.

Attach file IDs to products

Treat Commerce file IDs as the contract between your product catalog and stored media.

  • Use product_image for hero images and galleries.
  • Use product_video for product videos you may want to share publicly.
  • Use product_download for downloadable assets delivered after purchase.
  • Use products_import only for CSV product-catalog imports. The file must follow the required import schema, contain no more than 10,000 data rows, and stay within 32 MiB.

Store the returned file IDs on your product records through Create a product or Update a product. Do not save temporary upload URLs, local filenames, or third-party CDN URLs as your source of truth. That breaks lifecycle controls, makes deletions harder, and bypasses the purpose validation you applied at upload time.

Handle file-specific failures

File APIs return stable error codes. Use Error Codes to decide whether to ask for a different file, retry later, refresh an expired public URL, or clean up the resource that still references the file.

Was this page helpful?