FileHutch
Documentation

Getting started

TypeScript

No runtime dependencies — the global fetch on Node 18 and up, and any runtime that provides one.

The key is scoped to a project and can upload, sign and delete. Keep it on your server. Browsers upload through your own endpoints — see Browser uploads.

Install#

Terminal

npm install @filehutch/sdk

TypeScript

import { FileHutch } from "@filehutch/sdk"

const hutch = new FileHutch({ apiKey: process.env.FILE_HUTCH_API_KEY })

Upload#

TypeScript

// One call: request, PUT to storage, complete.
const file = await hutch.upload(bytes, { policy: "avatars", filename: "me.png" })

file.id                 // "file_abc123" — the only thing you store
file.transforms.avatar  // already on the payload for public images

Takes a Uint8Array, ArrayBuffer, Blob or a string. Content type comes from the option, then the filename.

The rest of it#

TypeScript

await hutch.project()
await hutch.transforms()
await hutch.file(id)
await hutch.signedUrl(id, { expiresIn: 3600, disposition: "attachment" })
await hutch.transformUrl(id, { transform: "avatar" })
await hutch.deleteFile(id)

Responses are plain typed objects in camelCase — with two exceptions. metadata and the keys of file.transforms are yours, not ours, so they come back exactly as you wrote them.

Errors#

The API's error codes are the contract, so they map to classes ahead of status. Match on a class or a code, never a message.

TypeScript

import { PolicyError, PlanLimitError } from "@filehutch/sdk"

try {
  await hutch.upload(bytes, { policy: "avatars", filename: "huge.png" })
} catch (error) {
  if (error instanceof PolicyError) return reply(422, error.message)
  if (error instanceof PlanLimitError) return nudgeToUpgrade()
  throw error
}