For AI agents: a documentation index is available at the root level at /llms.txt and /llms-full.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
LoginGet Started
DocsAPI ReferenceChangelog
DocsAPI ReferenceChangelog
    • Home
  • Getting Started
  • Infrastructure
    • GPU VMs
    • Cloud VMs
    • Object Storage
      • Core Concepts
      • Upload Your First Object
      • Buckets
      • Objects
        • Object Locking
        • Presigned URLs
      • Mount a Bucket as a Filesystem
      • Metrics
      • API Tokens
      • Static Site Hosting
      • CDN integration
      • Pricing
      • Limits
    • Block Storage
  • Network & Security
    • Load Balancer
    • DNS
    • CDN
    • Firewalls
    • SSL Certificates
  • Tools
    • Backups
    • Snapshots
    • ISOs
    • SSH Keys
    • API Tokens
    • Secret Manager
    • Container Registry
  • Platform Fundamentals
    • Projects and tenancy model
    • IAM
    • Networking overview
    • Billing and usage
    • Limits and quotas
    • SLA and reliability
  • Tutorials
    • Deploy a web app
    • Host a static website with object storage
    • Run an AI model on a GPU VM
    • Set up a load-balanced architecture
    • Backup and disaster recovery
    • Multi-region deployment
  • Migration Guides
    • Migrate from AWS
    • Migrate from GCP
    • Migrate from Vultr and Linode
    • Move S3 workloads to IBEE Object Storage
    • VM image migration
  • Reference
    • Pricing
    • Regions
    • Limits
    • Error codes
    • Service level agreement
  • Support
    • Contact Support
    • Create a request
    • Troubleshooting guides
    • Visit ibee.ai
LogoLogo
LoginGet Started
On this page
  • Before you begin
  • Generate a download URL with the AWS CLI
  • Generate from an SDK
  • Presigned uploads (PUT)
  • Presigned POST (browser uploads with form data)
  • Best practices
  • Limitations
  • Related
InfrastructureObject StorageObjects

Presigned URLs

Was this page helpful?
Edit this page
Previous

Mount a Bucket as a Filesystem

Next
Built with

A presigned URL is a regular HTTPS URL with an embedded signature that grants temporary access to a single object — no Access Key required by the recipient.

Use presigned URLs to:

  • Let a user download a private object from a browser, without giving them credentials.
  • Let a client upload a file directly to your bucket, bypassing your backend.
  • Hand a third-party system temporary access to a single file.

The URL stops working when its expiry passes.

Before you begin

  • A bucket (Create a bucket)
  • An API token with at least Object Read & Write scope on the target bucket — used to sign URLs

The S3 endpoint for your project is https://{project_id}.blob.ibeestorage.com.

Generate a download URL with the AWS CLI

$aws --endpoint-url https://{project_id}.blob.ibeestorage.com \
> --profile ibee \
> s3 presign s3://my-bucket/reports/2026-05.pdf \
> --expires-in 3600

The command prints a URL with embedded signature parameters:

https://{project_id}.blob.ibeestorage.com/my-bucket/reports/2026-05.pdf?
X-Amz-Algorithm=AWS4-HMAC-SHA256
&X-Amz-Credential=...
&X-Amz-Date=...
&X-Amz-Expires=3600
&X-Amz-SignedHeaders=host
&X-Amz-Signature=...

Anyone with the URL can GET the object until the expiry passes.

Generate from an SDK

1from datetime import timedelta
2import boto3
3
4s3 = boto3.client(
5 "s3",
6 endpoint_url="https://{project_id}.blob.ibeestorage.com",
7 aws_access_key_id="AKIA...",
8 aws_secret_access_key="<your-secret-access-key>",
9)
10
11url = s3.generate_presigned_url(
12 "get_object",
13 Params={"Bucket": "my-bucket", "Key": "reports/2026-05.pdf"},
14 ExpiresIn=int(timedelta(hours=1).total_seconds()),
15)
16print(url)

Presigned uploads (PUT)

Generate a URL the client can PUT to directly:

1url = s3.generate_presigned_url(
2 "put_object",
3 Params={
4 "Bucket": "my-bucket",
5 "Key": "uploads/avatar.png",
6 "ContentType": "image/png",
7 },
8 ExpiresIn=600,
9)

The client uploads with a single HTTP request:

$curl -X PUT "$URL" \
> -H "Content-Type: image/png" \
> --data-binary @avatar.png

Presigned POST (browser uploads with form data)

POST policies are the right fit for browser-based form uploads — they let you constrain the upload (key prefix, max size, content type) before the file is sent.

1post = s3.generate_presigned_post(
2 Bucket="my-bucket",
3 Key="uploads/${filename}",
4 Conditions=[
5 ["content-length-range", 0, 10 * 1024 * 1024], # 10 MB max
6 ["starts-with", "$Content-Type", "image/"],
7 ],
8 ExpiresIn=600,
9)
10print(post) # url + fields

Best practices

  • Use the shortest expiry that works. Don’t issue a long-lived URL when 5 minutes is enough.
  • Bind to content type and size for upload URLs to prevent abuse.
  • Don’t log presigned URLs — anyone who reads the log gets the same access.
  • Treat them as one-time secrets — regenerate per request rather than caching.

Limitations

  • The URL stops working if the API token used to sign it is revoked.
  • Each presigned URL is valid for one HTTP method on one key. Different operations need different URLs.

Related

  • Objects
  • API Tokens
  • Bucket policies
  • CORS