Examples
Four examples: invoice upload, pre-signed download URL, customer direct-upload URL, and partner file ingestion pipeline.
Example 1 — Upload Invoice PDF
After generating an invoice PDF (base64-encoded), upload it to S3 with a structured key path and custom metadata.
| Property | Value |
|---|---|
| operation | upload |
| credential_id | aws-prod |
| bucket | bizfirst-invoices |
| key | invoices/$ctx.year/$ctx.month/$ctx.invoice_id.pdf |
| content | $ctx.pdf_base64 |
| content_encoding | base64 |
| content_type | application/pdf |
| acl | private |
| metadata | {"invoice-id": "$ctx.invoice_id", "customer-id": "$ctx.customer_id"} |
object_url — store this in your database and include in the invoice email to the customer.Example 2 — Generate Pre-Signed Download URL
Generate a 24-hour download link for a private contract PDF. The link is emailed to the customer for temporary access.
| Property | Value |
|---|---|
| operation | getPresignedUrl |
| credential_id | aws-prod |
| bucket | bizfirst-contracts |
| key | contracts/$ctx.contract_id/signed.pdf |
| url_action | get |
| expires_in | 86400 (24 hours) |
The url field in the success output is sent via an Email node. When the 24-hour window expires, the link returns a 403 — enforcing the access window without any additional access management.
Example 3 — Customer Direct Upload URL
Generate a PUT pre-signed URL so a customer can upload a file directly to S3 from their browser — without the file passing through your servers.
| Property | Value |
|---|---|
| operation | getPresignedUrl |
| credential_id | aws-prod |
| bucket | bizfirst-uploads |
| key | uploads/$ctx.customer_id/$ctx.timestamp/$ctx.filename |
| url_action | put |
| expires_in | 900 (15 minutes) |
| content_type | application/pdf |
// Downstream: return URL to the API caller for direct browser upload
{
"upload_url": "$ctx.url",
"expires_at": "$ctx.expires_at",
"instructions": "PUT your file to this URL with Content-Type: application/pdf"
}
Example 4 — Partner File Ingestion Pipeline
A scheduled workflow lists new files in a partner's S3 prefix, downloads each one, processes the data, then moves the file to an archive prefix.
- ScheduledTrigger — runs every 15 minutes
- S3 (list) — bucket:
partner-drops, prefix:incoming/, max_keys:50 - Loop — iterates over
$ctx.objects - S3 (download) — key:
$loop.key, output_format:text - CodeExecute — parse CSV rows, validate, insert into database
- S3 (copy) — source_key:
$loop.key, destination:archive/processed/ - S3 (delete) — delete original from
incoming/after copy
Example 5 — Backup Before Overwrite
Before overwriting an existing file (e.g. a configuration or template), copy the current version to a versioned backup path, then upload the new version. This gives you a complete history without needing S3 object versioning enabled.
- WebhookTrigger — receives new template file content
- S3 (copy) — back up the existing file:
source_bucket: bizfirst-assets
source_key: templates/email-welcome.html
bucket: bizfirst-assets
dest_key: templates/backups/email-welcome-$ctx.timestamp.html - S3 (upload) — upload new version:
key: templates/email-welcome.html
file_data: $ctx.new_content
content_type: text/html - MongoDB (insert) — log the version event with backup key and author
Example 6 — Store AI-Generated Report
After a FlowAiAgent node generates a weekly business summary, upload it to S3, then generate a pre-signed URL and include it in a management email.
- ScheduledTrigger — Monday 08:00
- FlowAiAgent — generate weekly management summary (markdown format)
- S3 (upload):
bucket: bizfirst-reports
key: reports/$ctx.year/$ctx.month/weekly-summary-$ctx.date.md
file_data: $node.reportAgent.result
content_type: text/markdown
acl: private - S3 (getPresignedUrl):
key: $node.uploadReport.key
method: GET
expires_in: 604800(7 days) - EmailSmtp — send to management team with download link
- Slack — post notification in #management channel with URL
// Email body snippet Weekly summary is ready: Download Report Generated: {@ $ctx.date } | Valid until: {@ $node.presign.expires_at }
IAM Policy for This Workflow (Principle of Least Privilege)
For a workflow that only needs to upload and generate pre-signed download URLs, use this minimal IAM policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:PutObject", "s3:GetObject"],
"Resource": "arn:aws:s3:::bizfirst-reports/*"
}
]
}
Do not grant s3:* or bucket-level access. Scope permissions to the specific bucket and only the actions the workflow actually needs.
Key Pattern Summary
| Pattern | Operations Used | Notes |
|---|---|---|
| Upload and share | upload → getPresignedUrl | Always store to private, share via time-limited URL |
| Customer upload | getPresignedUrl (PUT) | 15-30 min expiry; enforce content-type to prevent arbitrary uploads |
| List and process | list → Loop → download | Use continuation_token for buckets with >1000 objects |
| Archive and delete | copy → delete | Always copy first — verify success before deleting source |
| Version before overwrite | copy → upload | Use timestamp in backup key for a sortable version history |