data-src=../../../../includes/saas-only.md

initiateUpload mutation

The initiateUpload mutation starts the file upload process by generating a presigned URL for uploading a file to an Amazon S3 bucket. This mutation requires the file name (key) and media resource type (media_resource_type) as input parameters. The key value cannot contain slashes. The following media resource types are supported:

You can also supply an optional checksum_sha256 value so that Amazon S3 validates the integrity of the uploaded file. See Checksum validation.

When you call this mutation, Commerce uses the AWS SDK to create a presigned URL that allows the client to upload the file directly to a temporary location in the S3 bucket. The presigned URL is valid for a limited time, specified by the expires_at field in the response.

The response includes the presigned URL, a unique key for the file, and an expiration time for the URL. The key is a hashed value that uniquely identifies the file in the S3 bucket. The client uses the presigned URL to upload the file using a standard HTTP PUT request.

Use the upload_url from the response to PUT the file directly to S3. See Upload files to Amazon S3 for an example curl.

After the file is successfully uploaded, use the finishUpload mutation to complete the upload process.

Checksum validation

To confirm that the file Amazon S3 receives matches the file the client sent, include the optional checksum_sha256 field in the initiateUpload input. Checksum validation is opt-in. If you omit the field, the upload process does not change.

The checksum_sha256 value must be the Base64-encoded raw 32-byte SHA-256 digest of the file. Do not use hexadecimal. The client must compute the value from the file before it calls the mutation. For example:

openssl dgst -sha256 -binary example.png | base64

When you supply a checksum, the upload process changes as follows:

reCAPTCHA validation

You can call the initiateUpload for many reasons, for example to attach an image to a return. To limit automated upload requests, merchants can require Google reCAPTCHA validation on this mutation. This setting is disabled by default. To enable it, set Enable for Presigned Upload in Stores > Configuration > Security > Google reCAPTCHA Storefront > Storefront.

When working with guest shoppers, call the initiateUpload mutation without a customer token.

When the setting is enabled, each initiateUpload request must include a valid reCAPTCHA token in the X-ReCaptcha HTTP header:

X-ReCaptcha: <reCAPTCHA-token>

If the token is missing or invalid, the request fails and Commerce does not issue a presigned URL. The finishUpload mutation does not require a reCAPTCHA token because it can only complete an upload that initiateUpload started.

For more information about reCAPTCHA headers, see Protected mutations.

Syntax

mutation {
    initiateUpload(input: initiateUploadInput!): initiateUploadOutput
}

Reference

The initiateUpload reference provides detailed information about the types and fields defined in this mutation.

Example usage

The following examples show how to initiate uploads for different types of files and how to supply a checksum.

Initiate an upload for a customer attribute file

The following mutation initiates an upload for a file named example.png.

Request:

mutation Initiate($input: initiateUploadInput!) {
  initiateUpload(input: $input) {
    upload_url
    key
    expires_at
  }
}

The $input variable contains:

{
  "input": {
    "key": "example.png",
    "media_resource_type": "CUSTOMER_ATTRIBUTE_FILE"
  }
}

Response:

{
  "data": {
    "initiateUpload": {
        "upload_url": "https://<bucket>.s3.<region>.amazonaws.com/<tenant-id>/example_106d42b2ee34de81db31d958.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=<value>...",
        "key": "example_106d42b2ee34de81db31d958.png",
        "expires_at": "1789433073"
    }
  }
}

Initiate an upload with a checksum

The following mutation initiates an upload for a file named example.png and supplies the Base64-encoded SHA-256 digest of the file.

Request:

mutation {
  initiateUpload(input: {
    key: "example.png",
    media_resource_type: CUSTOMER_ATTRIBUTE_FILE,
    checksum_sha256: "ABCY4JhezH9gQYqvDMWrWH9CwlcKiECVqejMrND2VFw="
  }) {
    upload_url
    key
    expires_at
  }
}

Response:

{
  "data": {
    "initiateUpload": {
      "upload_url": "https://<bucket>.s3.<region>.amazonaws.com/<tenant-id>/example_5f2b1c9e8a7d6e4f3c2b1a09.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=<value>...",
      "key": "example_5f2b1c9e8a7d6e4f3c2b1a09.png",
      "expires_at": "1789433073"
    }
  }
}

When you upload the file, send the same checksum in the x-amz-checksum-sha256 header:

curl --fail --show-error --silent -X PUT \
  --header 'x-amz-checksum-sha256: ABCY4JhezH9gQYqvDMWrWH9CwlcKiECVqejMrND2VFw=' \
  --data-binary @./example.png \
  '<upload_url>'

Initiate an upload for a negotiable quote attachment

The following mutation initiates an upload for a file named test-document1.txt.

Request:

mutation {
  initiateUpload(input: {
    key: "test-document1.txt",
    media_resource_type: NEGOTIABLE_QUOTE_ATTACHMENT
  }) {
    upload_url
    key
    expires_at
  }
}

Response:

{
  "data": {
    "initiateUpload": {
      "upload_url": "http://s3mock:9000/bucket1-presigned/tenant1/test-document1_32cb1fe50dab390be841461e.txt?X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIOSFODNN7EXAMPLE%2F20250909%2Feu-west-1%2Fs3%2Faws4_request&X-Amz-Date=20250909T160343Z&X-Amz-SignedHeaders=host&X-Amz-Expires=6600&X-Amz-Signature=5bc33cbdb2c93680a64dd9ef49d62ef34250faaafae1c6b0c17ac493f65b112d",
      "key": "test-document1_32cb1fe50dab390be841461e.txt",
      "expires_at": "1757440423"
    }
  }
}

Initiate an upload for a return item image attribute

Use the RMA_ATTRIBUTE_IMAGE and RMA_ATTRIBUTE_FILE resource types to attach an image or a file to a return request. Commerce stores these uploads under the rma_item/ media path.

The following mutation initiates an upload for an image named damage.png.

Request:

mutation {
  initiateUpload(input: {
    key: "damage.png",
    media_resource_type: RMA_ATTRIBUTE_IMAGE
  }) {
    upload_url
    key
    expires_at
  }
}

Response:

{
  "data": {
    "initiateUpload": {
      "upload_url": "https://example.com/<temp-location>?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=<value>...",
      "key": "damage_32cb1fe50dab390be841461e.png",
      "expires_at": "1757440423"
    }
  }
}

After you call the finishUpload mutation with the same key, assign the key to a return item custom attribute in the requestReturn mutation.