Signup gives you an API key. The key gets you an upload. The upload gives you a handle, and the handle is the only thing you need for every transformation and delivery URL after that. Those four steps are the whole first session with Filestack, and each one takes minutes rather than hours. The walkthrough below runs all four and shows what each returned.
Get a key
Sign up at dev.filestack.com. The form asks for a name, a company email and a password, and it shows the free plan allowance next to the fields you are filling in.
Your API key appears in the developer portal as soon as the account exists. It is about 20 characters, it identifies your application, and it is not a secret in the way a password is. It goes in client-side JavaScript on purpose, because that is how browser uploads reach us without a round trip through your server first.
The app secret is different. It stays on your server, it signs security policies, and nothing in this walkthrough needs it.
Your first upload
Two paths get a file in. Pick the one that matches where you are sitting.
Uploading from a browser
The picker is a hosted upload interface. Loading the script and calling picker() is the shortest route to a working upload, and it handles the retry and chunking work that hand-rolled <input type="file"> code usually skips.
<script src="https://static.filestackapi.com/filestack-js/3.x.x/filestack.min.js"></script>
<button id="pick">Upload a file</button>
<script>
const client = filestack.init('YOUR_API_KEY');
document.getElementById('pick').onclick = () => {
client.picker({
accept: ['image/*'],
maxFiles: 5,
onUploadDone: ({ filesUploaded }) => console.log(filesUploaded[0].handle),
}).open();
};
</script>
Click the button and the picker opens over your page. My Device is the local file system. The icons down the left are the other sources the free plan includes, so a multi file upload UI with Google Drive and a URL tab costs you nothing beyond the fromSources array.
Choose a file and it appears in a review list with its size before anything is sent. Nothing uploads until you press Upload, which is worth knowing when you are testing against a quota.
Press it and onUploadDone fires with one entry in filesUploaded. The handle field on that entry is what every URL below uses.
Uploading without a browser
If you are on a server or just want to see the response shape, one POST does it:
curl -X POST -F "fileUpload=@photo.jpg" \
"https://www.filestackapi.com/api/store/S3?key=YOUR_API_KEY"
which returns:
{
"url": "https://cdn.filestackcontent.com/0J0PpoBYScqJrHF8lbrO",
"size": 107013,
"type": "image/jpeg",
"filename": "photo.jpg"
}
That is the same REST API upload file endpoint the SDKs sit on top of, so the handle it returns behaves identically. The 20 characters at the end of that URL are the handle.
What the handle is for
The handle is the file. Every delivery and processing URL is the handle with tasks in front of it:
https://cdn.filestackcontent.com/TASK/HANDLE
Your API key does not go in that URL. The handle already identifies the application that owns the file, so adding the key puts a credential in front of your users for nothing.
Your first transformation
Put a task in front of the handle and the file changes on the way out. Resize is the one to try first, because the result is obvious:
https://cdn.filestackcontent.com/resize=width:300/0J0PpoBYScqJrHF8lbrO
The 107,013 byte original came back as 42,214 bytes at 300 pixels wide. Nothing was stored to produce that. The transformation ran at request time and the result was cached, which is why you never generate thumbnail variants ahead of time or keep them anywhere.
Tasks chain left to right. Adding a format change on the end took the same request to 32,854 bytes:
https://cdn.filestackcontent.com/resize=width:300/output=format:webp/0J0PpoBYScqJrHF8lbrO
Order matters, because each task acts on what the previous one produced. Resize first and the encoder is working on a smaller image. The reasoning behind picking a format at all is in the guide to convert to webp, and the full parameter set for every task is in the processing API reference.
Crop, rotate, watermark, compress and quality all work the same way on a free key, as does face detection, so you can blur faces in a URL without training anything. The image editing api guide covers how the tasks combine.
Where the file lives now
At the CDN, already, on a public URL. There is no publish step and no bucket to configure. The default response carries cache-control: public, max-age=2667950, so once an edge has served a transformation it keeps serving it without rerunning anything.
Set your own expiry when you need a shorter one:
https://cdn.filestackcontent.com/cache=expiry:3600/resize=width:300/0J0PpoBYScqJrHF8lbrO
The Filestack CDN then answers that URL with cache-control: public, max-age=3600. How the edges pick up files and how long they hold them is covered in file delivery.
Public by default matters for the next thing you build. Anyone with the handle can read the file, which is right for a portfolio and wrong for invoices, and the fix is a signed policy rather than a different upload call. A secure file upload service is a configuration you turn on later, not a separate product.
When something comes back wrong
Every failure here answers in plain text, so read the body rather than guessing from the status code.
| What you sent | Status | Body |
|---|---|---|
| A handle that does not exist | 400 | Bad Request |
| A task name with a typo | 400 | validation error: task not found: “resiz” |
| A parameter name with a typo | 400 | validation error: invalid parameter widht for resize task |
| An operation your plan does not include | 403 | You don’t have permission to perform this task: ocr. Please check your access settings |
That last one is the boundary worth knowing early. Operations that read and interpret a file, such as optical character recognition, tagging, captioning and enhancement, run on the higher plans. Everything that changes a file’s shape, size or format runs on the free plan, which is most of what a first project needs.
What to try next
The quotas are 500 uploads, 1,000 transformations, 1 GB of bandwidth and 1 GB of storage a month, checked on the free plan page on 6 August 2026. A prototype does not come near them.
Three directions from here, depending on what you are building:
Wire it into your framework. The same three lines work in a React file upload component or behind an ordinary HTML form, with import * as filestack from 'filestack-js' instead of the script tag. In Next.js the component needs 'use client', because the picker needs a browser.
Chain transformations. Crop, then resize, then encode, in one URL, is the pattern behind every responsive image you will serve. Order matters, because resizing first means the encoder has fewer pixels to work on.
Take the whole lifecycle seriously. Once uploads are real user files, storage, transformation and delivery become one system. The image upload service guide covers how those pieces fit together.
Joshua is a web developer with over 4 years of experience building responsive, high-performance websites and web applications. Currently working as an AI Automation Specialist, he combines modern web development with automation to create efficient, scalable digital solutions. He shares practical insights on WordPress, web development, and emerging technologies.
Read More →