---
title: UploadPartCopy · S3 API
description: Copies a byte range of an object into one part of a multipart upload.
doc_version: 0.1.0-preview
last_updated: 2026-09-14
---

# UploadPartCopy

`PUT /{bucket}/{key}?partNumber&uploadId` with the `x-amz-copy-source` header

Copies a byte range of an object into one part of a multipart upload.

Use it to build a large object from objects that you already stored, with no download.

- Role: Editor or higher.
- Support: partial.
- Auth: AWS Signature Version 4 with your API key. See [S3 API](/api/s3.md).
- The source must be in the same bucket. One byte range per part.

## Example request

```http
PUT /support-tickets/big.bin?partNumber=2&uploadId=VXBsb2FkIGZvciBiaWcuYmlu HTTP/1.1
Host: wspq7ws2np5l8z4.storage.graphon.sh
x-amz-date: 20261007T093000Z
x-amz-content-sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
Authorization: AWS4-HMAC-SHA256 Credential=<ACCESS_KEY_ID>/20261007/us-east-1/s3/aws4_request, SignedHeaders=host;x-amz-content-sha256;x-amz-date, Signature=<SIGNATURE>
x-amz-copy-source: support-tickets/archive.bin
x-amz-copy-source-range: bytes=0-104857599
```

## Path parameters

- `bucket` (string, required): The bucket name.
- `key` (string, required): The object key. Keep each `/` as it is. Percent-encode the other reserved characters.

## Query parameters

- `partNumber` (integer, required): The part number, from 1 through 10,000.
- `uploadId` (string, required): The upload ID from CreateMultipartUpload.

## Headers

- `x-amz-copy-source` (string, required): The source object, as `{bucket}/{key}`, URL-encoded. Add `?versionId=` to copy one version.
- `x-amz-copy-source-range` (string, optional): One byte range of the source, for example `bytes=0-104857599`. Without it, storage copies the whole source.
- `x-amz-expected-bucket-owner` (string, optional): The workspace ID that must own the bucket. Another owner returns `403 AccessDenied`.

## Responses

### 200 · OK

Storage copied the part.

Response body:

- `CopyObjectResult` (object, required): The root element.
  - `LastModified` (string, optional): When storage copied the part.
  - `ETag` (string, optional): The entity tag of the part. Send it to CompleteMultipartUpload.

```http
HTTP/1.1 200 OK
Content-Type: application/xml
x-amz-request-id: 4F8A2C7D1E6B4093A5C2D8E1F7B3A960

<?xml version="1.0" encoding="UTF-8"?>
<CopyObjectResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
  <LastModified>2026-10-07T09:30:00.000Z</LastModified>
  <ETag>"0cc175b9c0f1b6a831c399e269772661"</ETag>
</CopyObjectResult>
```

## Errors

Any request can also get the common errors on [S3 API](/api/s3.md).

### 404 · `NoSuchUpload`

The upload ID is not known for this key. The upload was completed or aborted.

Start a new upload with CreateMultipartUpload.

### 400 · `InvalidArgument`

The partNumber is not an integer from 1 through 10,000.

Number the parts from 1 through 10,000.

### 404 · `NoSuchKey`

The source has no object at this key or version.

Check the key and the versionId.

### 501 · `NotImplemented`

The source is in another bucket.

Copy parts from objects in the same bucket only.

### 400 · `InvalidRequest`

The `x-amz-copy-source` value is not `{bucket}/{key}`.

Send the source as `{bucket}/{key}`, URL-encoded.

### 503 · `SlowDown`

The bucket has too many writes in progress. The response has `Retry-After: 1`.

Wait for the Retry-After time, then send the request again. SDKs retry by themselves.

### 403 · `QuotaExceeded`

The workspace stores twice its plan's storage limit, so storage refuses writes. Reads, lists, and deletes still work.

Delete objects, or ask an Admin to upgrade the plan. Then send the write again.

### 404 · `NoSuchBucket`

No bucket has this name, or the bucket was deleted.

Check the bucket name. ListBuckets shows the buckets of the workspace.

### 403 · `AccessDenied`

The key does not have the role for this operation, or the bucket is in another workspace.

Use a key of the workspace that owns the bucket, with the role above.

## Other request languages

### aws CLI

```bash
# The graphon profile from the S3 API overview.
export AWS_PROFILE=graphon

UPLOAD_ID="VXBsb2FkIGZvciBiaWcuYmlu"  # The UploadId from create-multipart-upload
aws s3api upload-part-copy \
  --bucket support-tickets \
  --key big.bin \
  --part-number 2 \
  --upload-id "$UPLOAD_ID" \
  --copy-source support-tickets/archive.bin \
  --copy-source-range bytes=0-104857599
```

### Python (boto3)

```python
# Replace wspq7ws2np5l8z4 with your workspace ID.
import os

import boto3
from botocore.config import Config

api_key = os.environ["GRAPHON_API_KEY"]
access_key_id = api_key.split("_", 1)[1].split(".")[0]

s3 = boto3.client(
    "s3",
    endpoint_url="https://wspq7ws2np5l8z4.storage.graphon.sh",
    region_name="us-east-1",
    aws_access_key_id=access_key_id,
    aws_secret_access_key=api_key,
    config=Config(signature_version="s3v4", s3={"addressing_style": "path"}),
)

upload_id = "VXBsb2FkIGZvciBiaWcuYmlu"  # The UploadId from create_multipart_upload
response = s3.upload_part_copy(
    Bucket="support-tickets",
    Key="big.bin",
    PartNumber=2,
    UploadId=upload_id,
    CopySource="support-tickets/archive.bin",
    CopySourceRange="bytes=0-104857599",
)
print(response["CopyPartResult"]["ETag"])
```

### JavaScript (AWS SDK)

```javascript
// Replace wspq7ws2np5l8z4 with your workspace ID.
import { S3Client, UploadPartCopyCommand } from '@aws-sdk/client-s3';

const apiKey = process.env.GRAPHON_API_KEY;
if (!apiKey) throw new Error('Set GRAPHON_API_KEY.');
const accessKeyId = apiKey.split('_')[1].split('.')[0];

const s3 = new S3Client({
  endpoint: 'https://wspq7ws2np5l8z4.storage.graphon.sh',
  region: 'us-east-1',
  forcePathStyle: true,
  credentials: { accessKeyId, secretAccessKey: apiKey },
});

const uploadId = 'VXBsb2FkIGZvciBiaWcuYmlu'; // The UploadId from CreateMultipartUpload
const response = await s3.send(new UploadPartCopyCommand({
  Bucket: 'support-tickets',
  Key: 'big.bin',
  PartNumber: 2,
  UploadId: uploadId,
  CopySource: 'support-tickets/archive.bin',
  CopySourceRange: 'bytes=0-104857599',
}));
console.log(response.CopyPartResult?.ETag);
```

## Sitemap

See the full [sitemap](/sitemap.md) for all pages.
