Storage

Signed Uploads

Introduction

When uploading files from a client app, you can't safely include your API Key in the request.

You could post the file to your server, and then upload from there. However, this adds latency and needless extra bandwidth costs.

So ittybit allows you to create a signed upload url for the file, then upload the file direct from your client to that url.

If you're uploading directly from a server, serverless function, or other secure environment, then you may want to look at simple uploads.


How it works

A signed upload url is includes a valid signature which will grant access to your project for a limited time.

Once you have the signed url, you make a PUT request with the file in the request body.

When the upload completes, ittybit will return a File object in the response.


Signed urls

A signed url looks like this:

https://example.ittybit.net/image.png?expiry=1765432100&signature=1234abcd5678efgh9012

The domain is your project's delivery domain (see Domains for info on setting up custom domains) e.g. https://example.ittybit.net.

The filename is the name of the file you want to upload e.g. image.png.

You can optionally include a folder to upload the file to a specific folder e.g. nested/folders/image.png.

The expiry is a unix timestamp for some time in the near future. The url will stop working after this time e.g. expiry=1765432100.

The signature is a base64 encoded string. The string that is encoded is the domain, folder, filename, and expiry values, signed with your project's API key.


1. Get a signed url

To get a valid signed url, you will need to make a request to your server, get the url, and return it to your client.

If you're using a REST API for data fetching (could be powered by Express/Node, Laravel, Rails, or similar) then this would probably be an API route.

// Example fetch request to your API server
const response = await fetch('https://yourapi.com/upload-url', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    // Add your authentication headers
  },
  body: JSON.stringify({
    filename: 'image.png',
  }),
});
const { url } = await response.json();

Next.js, SvelteKit, and similar frontend frameworks can use server actions to generate or fetch a signed url directly.

Generate a signature yourself

[Guide coming soon!]

Use the /signatures endpoint

If you can't generate a signature yourself, then you can create a signed url using our signatures API endpoint.


2. Upload the file

Once you have the signed url, you can upload the file to ittybit.

const response = await fetch(url, {
  method: 'PUT',
  body: file,
});

3. Handle the response

When your upload completes, ittybit will return a File object in the response.

const { meta, data, error } = await response.json();

The meta object contains information about the request.

The data object contains the file object.

The error object will only be present if the upload failed.


File object

{
  "id": "file_abcdefgh1234",
  "kind": "image",
  "type": "image/png",
  "width": 3000,
  "height": 2000,
  "filesize": 12345678,
  "url": "https://example.ittybit.net/image.png",
  "created": "2025-01-01T01:23:45Z",
  "updated": "2025-01-01T01:23:45Z"
}

You can persist this info to your database, and use it to serve the file to your users.


On this page