object/copy FormID 20506
Copy an object within or between S3 buckets without downloading to local storage.
Server-Side Operation:
object/copy is performed entirely within AWS infrastructure. No data is transferred through the workflow executor. This makes it fast, bandwidth-free, and suitable for copying large objects between buckets, including cross-region copies.
When to Use
- Archive processed files: After processing, copy files from a hot
STANDARDlanding bucket to a coldGLACIERarchive bucket without re-uploading. - CDN origin sync: Copy approved assets from an internal review bucket to a CDN origin bucket, making them publicly accessible.
- Template duplication: Copy a master document template to a tenant-specific working location before applying data merge operations.
- Storage class migration: Change the storage class of an existing object by copying it to the same bucket with a different
storageClass. - Cross-region replication trigger: Manually replicate specific objects to a disaster recovery bucket in a secondary region when automated replication is not enabled.
Configuration
Connection
| Field | Required | Description |
|---|---|---|
accessKeyId | Required | AWS Access Key ID. Store in BizFirst Credentials Manager. |
secretKey | Required | AWS Secret Access Key. Never log or expose. |
sessionToken | Optional | STS session token for temporary credentials. |
region | Required | AWS region of the destination bucket. For cross-region copies, use the destination region here. |
Operation Fields
| Field | Required | Description |
|---|---|---|
sourceBucket | Required | Name of the source bucket containing the object to copy. |
sourceKey | Required | Full key path of the source object. |
destBucket | Required | Name of the destination bucket. May be the same as sourceBucket for same-bucket copy. |
destKey | Required | Full key path for the destination object. Must be different from sourceKey if using the same bucket. |
serverSideEncryption | Optional | Encryption for the destination copy. Default: AES256. Options: aws:kms, none. |
cannedAcl | Optional | ACL for the destination object. Default: private. Options: public-read. |
Sample Configuration
{
"connection": {
"accessKeyId": "{{ $credentials.s3_prod.accessKeyId }}",
"secretKey": "{{ $credentials.s3_prod.secretKey }}",
"region": "us-east-1"
},
"operation": {
"resource": "object",
"action": "copy",
"sourceBucket": "acme-processing-queue",
"sourceKey": "incoming/{{ $node.FileRecord.output.fileName }}",
"destBucket": "acme-processed-archive",
"destKey": "archive/{{ $now | date: 'YYYY/MM/DD' }}/{{ $node.FileRecord.output.fileName }}",
"serverSideEncryption": "AES256",
"cannedAcl": "private"
}
}
Validation Errors
| Error Code | Cause & Resolution |
|---|---|
NoSuchKey | The source object does not exist. Verify the sourceBucket and sourceKey using bucket/search before copying. |
AccessDenied | The IAM identity lacks s3:GetObject on the source or s3:PutObject on the destination. Update the IAM policy to include both permissions. |
NoSuchBucket | The source or destination bucket does not exist. Create the destination bucket using bucket/create before attempting the copy. |
ObjectNotInActiveTierError | The source object is stored in GLACIER or DEEP_ARCHIVE and must be restored before it can be copied. Initiate a restore request first. |
Output
Success Port
| Field | Type | Description |
|---|---|---|
status | string | success on successful copy. |
errorCode | string | Empty string on success. |
sourceBucket | string | The source bucket. |
sourceKey | string | The source object key. |
destBucket | string | The destination bucket. |
destKey | string | The destination object key. |
eTag | string | ETag of the destination copy. |
copiedAt | string | ISO 8601 timestamp of the copy operation. |
Error Port
On failure, activates with errorCode, errorMessage, and httpStatusCode. Handle NoSuchKey to alert on missing source objects and ObjectNotInActiveTierError to trigger a GLACIER restore sub-workflow.
Sample Output
{
"status": "success",
"errorCode": "",
"sourceBucket": "acme-processing-queue",
"sourceKey": "incoming/expense-report-q2-2026.xlsx",
"destBucket": "acme-processed-archive",
"destKey": "archive/2026/05/26/expense-report-q2-2026.xlsx",
"eTag": "\"a3cce0963a6a4b4f3e09d2e1c8f2a1b7\"",
"copiedAt": "2026-05-26T12:00:44Z"
}
Expression Reference
| Expression | Result |
|---|---|
{{ $node.CopyToArchive.output.destKey }} | Destination key — store in database as the new canonical object reference. |
{{ $node.CopyToArchive.output.eTag }} | ETag of the copy — verify integrity against source ETag for audit. |
{{ $node.CopyToArchive.output.copiedAt }} | Copy timestamp — log in workflow execution audit record. |
{{ $node.CopyToArchive.output.destBucket }} | Destination bucket — update database record to reflect new object location. |
Node Policies & GuardRails
| Policy Area | Recommendation |
|---|---|
| Credential Storage | Store credentials in BizFirst Credentials Manager. Never hardcode. |
| IAM Permissions | Grant s3:GetObject on the source bucket and s3:PutObject on the destination bucket. For cross-account copies, configure bucket policies on both sides. |
| Destination Key Uniqueness | Always use expressions that generate unique destination keys — avoid copying over an existing object unless that is intentional. |
| Encryption Consistency | Apply the same or stricter encryption to the destination copy. Never downgrade from KMS to AES256 when copying regulated data. |
| Cross-Region Costs | Cross-region copies incur data transfer fees. Batch cross-region copies during off-peak hours where possible. |
| Glacier Pre-Check | Before copying, verify the source object is not in GLACIER or DEEP_ARCHIVE. Add a pre-flight bucket/search check if storage class is uncertain. |
| Audit Trail | Log sourceKey, destKey, and copiedAt in the workflow audit trail for every copy operation. |
| Move Pattern | S3 has no native move operation. To move an object: copy first, then delete the source with object/delete only after confirming copy success. |
Examples
Example 1: Archive After Processing
After an ETL workflow processes incoming files, copy them to a date-partitioned archive bucket and delete the original from the landing zone.
// Node: CopyToArchive (S3 — object/copy)
{
"sourceBucket": "acme-ingest-landing",
"sourceKey": "incoming/{{ $node.ProcessFile.output.fileName }}",
"destBucket": "acme-long-term-archive",
"destKey": "processed/{{ $now | date: 'YYYY/MM/DD' }}/{{ $node.ProcessFile.output.fileName }}",
"serverSideEncryption": "AES256"
}
// On success: object/delete source file
Example 2: CDN Publish Workflow
After an asset passes review, copy it from the review bucket to the public CDN origin bucket.
// Node: PublishAsset (S3 — object/copy)
{
"sourceBucket": "acme-review-staging",
"sourceKey": "pending/{{ $node.ApprovedAsset.output.assetKey }}",
"destBucket": "acme-cdn-origin",
"destKey": "assets/{{ $node.ApprovedAsset.output.assetKey }}",
"cannedAcl": "public-read"
}
// Next: InvalidateCloudFrontCache for destKey
Example 3: Storage Class Migration
Move objects older than 90 days from STANDARD to STANDARD_IA by copying to the same key with a different storage class.
// Node: MigrateStorageClass (S3 — object/copy, inside Loop)
{
"sourceBucket": "acme-documents",
"sourceKey": "{{ $loop.currentItem.objectKey }}",
"destBucket": "acme-documents",
"destKey": "{{ $loop.currentItem.objectKey }}",
"serverSideEncryption": "AES256",
"storageClass": "STANDARD_IA"
}
// Note: copying to same key/bucket changes the storage class