API

Storage

cloudlayer.io supports three storage modes for generated files. You can use the built-in cloud storage (default), skip storage entirely, or connect your own S3-compatible bucket for direct delivery.

Storage Types

TypeDescriptionAvailability
No StorageGenerated files are returned in the HTTP response only. No files are stored on cloudlayer.io servers.All plans
Cloud StorageGenerated files are stored on cloudlayer.io’s managed cloud storage and accessible via the Assets API. This is the default in v2.Included with all v2 plans
User StorageGenerated files are delivered directly to your own S3-compatible storage bucket (AWS S3, Google Cloud Storage, DigitalOcean Spaces, MinIO, Backblaze B2, etc.).Professional and Enterprise plans

No Storage

When you make a synchronous API request, the generated file is returned directly in the HTTP response body. If you do not need to retrieve the file later via the Assets API, no storage configuration is required.

For synchronous requests, the file is always included in the response regardless of storage settings.


Cloud Storage (Default)

Cloud storage is enabled by default for all v2 API requests. Generated files are automatically stored and accessible via the Assets endpoint. No configuration is needed.

  • Files are stored securely on cloudlayer.io infrastructure
  • Each file is accessible via a pre-authenticated download URL
  • Retention period depends on your subscription plan
  • Monitor usage via the Account endpoint (bytesUsed)

User Storage (S3-Compatible)

Connect your own S3-compatible storage bucket to have generated files delivered directly to your infrastructure. This gives you full control over file retention, access policies, and geographic placement.

Endpoints

POST   /v2/storage
GET    /v2/storage
DELETE /v2/storage

Create or Update Storage Configuration

Configure your S3-compatible storage bucket.

POST /v2/storage

Request Body

FieldTypeRequiredDefaultDescription
bucketstringYesThe S3 bucket name (e.g., "my-company-pdfs").
regionstringYesThe AWS region or equivalent (e.g., "us-east-1", "eu-west-1").
accessKeyIdstringYesThe access key ID for your S3-compatible storage.
secretAccessKeystringYesThe secret access key for your S3-compatible storage.
endpointstringNoCustom endpoint URL for non-AWS S3-compatible services (e.g., "https://nyc3.digitaloceanspaces.com", "https://s3.eu-central-1.wasabisys.com"). Omit for AWS S3.
prefixstringNo""A path prefix for all uploaded files (e.g., "cloudlayer/" or "generated/pdfs/"). Files are stored at {prefix}{filename}.
aclstringNo"private"The ACL (access control list) to apply to uploaded files. Common values: "private", "public-read", "authenticated-read".

Examples

cURL (AWS S3)

curl -X POST "https://api.cloudlayer.io/v2/storage" \
  -H "X-API-Key: your-api-key-here" \
  -H "Content-Type: application/json" \
  -d '{
    "bucket": "my-company-pdfs",
    "region": "us-east-1",
    "accessKeyId": "AKIAIOSFODNN7EXAMPLE",
    "secretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
    "prefix": "cloudlayer/",
    "acl": "private"
  }'

cURL (DigitalOcean Spaces)

curl -X POST "https://api.cloudlayer.io/v2/storage" \
  -H "X-API-Key: your-api-key-here" \
  -H "Content-Type: application/json" \
  -d '{
    "bucket": "my-space-name",
    "region": "nyc3",
    "accessKeyId": "your-spaces-access-key",
    "secretAccessKey": "your-spaces-secret-key",
    "endpoint": "https://nyc3.digitaloceanspaces.com",
    "prefix": "generated/",
    "acl": "private"
  }'

cURL (Google Cloud Storage)

curl -X POST "https://api.cloudlayer.io/v2/storage" \
  -H "X-API-Key: your-api-key-here" \
  -H "Content-Type: application/json" \
  -d '{
    "bucket": "my-gcs-bucket",
    "region": "us-central1",
    "accessKeyId": "GOOGTS7C7FUP3AIRVJTE2BCDKINBTES3HC2GY5CBFJDCQ2SYHIPAQKT6EXAMPLE",
    "secretAccessKey": "your-hmac-secret-key",
    "endpoint": "https://storage.googleapis.com",
    "prefix": "cloudlayer-output/"
  }'

JavaScript (fetch)

const response = await fetch("https://api.cloudlayer.io/v2/storage", {
  method: "POST",
  headers: {
    "X-API-Key": "your-api-key-here",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    bucket: "my-company-pdfs",
    region: "us-east-1",
    accessKeyId: "AKIAIOSFODNN7EXAMPLE",
    secretAccessKey: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
    prefix: "cloudlayer/",
    acl: "private",
  }),
});

const result = await response.json();
console.log(result);

Python (requests)

import requests

response = requests.post(
    "https://api.cloudlayer.io/v2/storage",
    headers={
        "X-API-Key": "your-api-key-here",
        "Content-Type": "application/json",
    },
    json={
        "bucket": "my-company-pdfs",
        "region": "us-east-1",
        "accessKeyId": "AKIAIOSFODNN7EXAMPLE",
        "secretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
        "prefix": "cloudlayer/",
        "acl": "private",
    },
)

result = response.json()
print(result)

Response

{
  "message": "Storage configuration saved successfully.",
  "bucket": "my-company-pdfs",
  "region": "us-east-1",
  "prefix": "cloudlayer/"
}

Get Storage Configuration

Retrieve your current storage configuration. Sensitive fields (secretAccessKey) are masked in the response.

GET /v2/storage

Examples

cURL

curl -X GET "https://api.cloudlayer.io/v2/storage" \
  -H "X-API-Key: your-api-key-here"

JavaScript (fetch)

const response = await fetch("https://api.cloudlayer.io/v2/storage", {
  headers: {
    "X-API-Key": "your-api-key-here",
  },
});

const config = await response.json();
console.log(config);

Python (requests)

import requests

response = requests.get(
    "https://api.cloudlayer.io/v2/storage",
    headers={"X-API-Key": "your-api-key-here"},
)

config = response.json()
print(config)

Response

{
  "bucket": "my-company-pdfs",
  "region": "us-east-1",
  "accessKeyId": "AKIA...MPLE",
  "secretAccessKey": "****",
  "endpoint": null,
  "prefix": "cloudlayer/",
  "acl": "private"
}

Delete Storage Configuration

Remove your user storage configuration and revert to the default cloud storage.

DELETE /v2/storage

Examples

cURL

curl -X DELETE "https://api.cloudlayer.io/v2/storage" \
  -H "X-API-Key: your-api-key-here"

JavaScript (fetch)

const response = await fetch("https://api.cloudlayer.io/v2/storage", {
  method: "DELETE",
  headers: {
    "X-API-Key": "your-api-key-here",
  },
});

const result = await response.json();
console.log(result);

Python (requests)

import requests

response = requests.delete(
    "https://api.cloudlayer.io/v2/storage",
    headers={"X-API-Key": "your-api-key-here"},
)

result = response.json()
print(result)

Response

{
  "message": "Storage configuration deleted. Reverting to default cloud storage."
}

S3-Compatible Services

The following S3-compatible storage services have been tested and are fully supported:

ProviderEndpoint FormatNotes
AWS S3Omit endpoint (default)Standard S3 service. Use IAM credentials with s3:PutObject permission on the target bucket.
Google Cloud Storagehttps://storage.googleapis.comRequires HMAC keys for interoperability access.
DigitalOcean Spaceshttps://{region}.digitaloceanspaces.comSpaces API keys from the DO control panel.
Backblaze B2https://s3.{region}.backblazeb2.comB2 application keys with write access.
MinIOhttps://your-minio-server.comSelf-hosted S3-compatible storage.
Wasabihttps://s3.{region}.wasabisys.comHot storage with no egress fees.
Cloudflare R2https://{account-id}.r2.cloudflarestorage.comNo egress fees. Use R2 API tokens.

IAM Policy for AWS S3

If using AWS S3, create an IAM user with the minimum required permissions:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:PutObject",
        "s3:PutObjectAcl"
      ],
      "Resource": "arn:aws:s3:::my-company-pdfs/cloudlayer/*"
    }
  ]
}

Security tip: Scope the IAM policy to the specific bucket and prefix. Do not grant s3:* or access to other buckets. Use a dedicated IAM user for cloudlayer.io, not your root account credentials.


How User Storage Works

When user storage is configured:

  1. You make an API request to generate a PDF or image (e.g., POST /v2/html/pdf).
  2. cloudlayer.io generates the file as usual.
  3. The file is uploaded to your S3-compatible bucket at {prefix}{filename}.
  4. The API response includes the file as usual (for sync requests).
  5. The Assets endpoint reflects the file’s location in your bucket.

Files are uploaded with the configured acl. If you set acl: "public-read", the file will be publicly accessible via the S3 URL. If acl: "private" (default), you will need to generate presigned URLs or use your own access controls to serve the files.


Tips

  • CORS: If you need to access files from a browser, configure CORS on your S3 bucket to allow requests from your domain.
  • Prefix organization: Use the prefix field to organize files by environment, project, or date (e.g., "production/invoices/2024/", "staging/reports/").
  • Credentials rotation: Rotate your S3 access keys periodically. Update the storage configuration via POST /v2/storage with new credentials.
  • Testing: After configuring user storage, generate a test file and verify it appears in your bucket at the expected location.
  • Fallback: If the upload to your bucket fails (e.g., invalid credentials, bucket does not exist), the API request will still succeed and the file will be available via cloudlayer.io cloud storage. Check your storage configuration if files are not appearing in your bucket.
  • Reverting: Delete your storage configuration (DELETE /v2/storage) at any time to revert to the default cloud storage.