Skip to content
FULLTime eCommerce

Cart Upload Store API – Headless & PWA (Shopware 6)

Note: Available from version 2.4.0

If you run your shop with your own frontend instead of the Shopware storefront – a PWA, a Next.js or Nuxt project – the complete upload flow is available through the Store API.

Every endpoint expects the sw-access-key header of your sales channel and the customer's sw-context-token.

Endpoint overview

MethodPathPurpose
HEAD/POST/PATCH/DELETE/store-api/checkout/item-upload/{id}tus upload (create, send data, abort)
GET/store-api/checkout/item-upload/{id}/getStatus of an ongoing upload
POST/store-api/checkout/upload-deleteRemove an uploaded file

How the upload works

Uploads use the tus protocol for resumable transfers. The flow has two steps.

1. Create the upload

A POST without file content announces the file. Cart and line item are declared through the Upload-Metadata header — each value Base64 encoded:

curl -X POST https://your-shop.com/store-api/checkout/item-upload/1 \
  -H "sw-access-key: YOUR-ACCESS-KEY" \
  -H "sw-context-token: YOUR-CONTEXT-TOKEN" \
  -H "Tus-Resumable: 1.0.0" \
  -H "Upload-Length: 20480" \
  -H "Upload-Metadata: cartToken <base64>,lineItemId <base64>,name <base64>"

The response is 201 Created with a Location header. That URL is the target for step two.

Important: cartToken has to be the token of the calling context — the same value you send as sw-context-token. A foreign cart is rejected with 403.

2. Send the data

curl -X PATCH <Location-URL> \
  -H "sw-access-key: YOUR-ACCESS-KEY" \
  -H "sw-context-token: YOUR-CONTEXT-TOKEN" \
  -H "Tus-Resumable: 1.0.0" \
  -H "Upload-Offset: 0" \
  -H "Content-Type: application/offset+octet-stream" \
  --data-binary @file.pdf

The response is 204 No Content. Large files can be sent in several PATCH calls with an increasing Upload-Offset; an interrupted upload resumes at the same position.

Reading uploaded files

There is no separate endpoint for this — the files arrive with the cart itself. Fetch /store-api/checkout/cart and every line item carries its uploads in the uploads extension:

{
  "lineItems": [
    {
      "id": "…",
      "extensions": {
        "uploads": [
          { "id": "…", "fileName": "artwork.pdf", "fileSize": 20480, "qquuid": "…" }
        ]
      }
    }
  ]
}

Removing a file

curl -X POST https://your-shop.com/store-api/checkout/upload-delete \
  -H "sw-access-key: YOUR-ACCESS-KEY" \
  -H "sw-context-token: YOUR-CONTEXT-TOKEN" \
  -d "cartUploadId=<id from the uploads extension>"

Response on success:

{ "apiAlias": "futi_cart_upload_delete", "success": true, "id": "…" }

If the file belongs to another cart the route responds with 403; an unknown id returns 404.

What you still build in your frontend

The Store API covers the server side. What remains in the frontend:

  • the picker and progress UI (the storefront uses Uppy with its tus plugin — that works the same way in any JavaScript frontend)
  • checking allowed file types and maximum size before sending, so customers do not see an error only after the upload
  • rendering the already uploaded files from the uploads extension

Allowed file types and size limits are still maintained in the plugin configuration, see Plugin Configuration.

Order and administration

Nothing changes after checkout: files are linked to the order line item and remain accessible on the order in the administration. The email templates work unchanged as well.

Next step: Changelog →

Was this page helpful?

Support

Rented Plugins (Shopware Store)

For support with plugins rented from the Shopware Store, please open a support ticket in your Shopware account.

Create Shopware Ticket

General Inquiries

For general questions or purchase licenses, reach us by email.

Send Email
Cart Upload Store API – Headless & PWA (Shopware 6) | FULLTime eCommerce