# colis · Deliver files to your clients, from storage you own.

> colis is a delivery tool for freelancers: send a deliverable to your own S3 or R2 bucket under an eight-character code, and your client opens it, previews it, then approves it or asks for changes. Every step fires a signed webhook. A delivery page to deploy, a CLI with French commands, an n8n node. Open source, MIT.

Canonical: https://colis-site.vercel.app/en · Markdown: https://colis-site.vercel.app/en/index.md · Français: https://colis-site.vercel.app/

colis sends your deliverable to a bucket you own under an eight-character code. Your client opens it, previews it, then approves it or asks for changes. You know when it was opened and what they answered, and every step can start an automation.

- Try the demo: https://colis-tau.vercel.app
- GitHub: https://github.com/mamadouwhile/colis

## A delivery in three steps.
The file goes from your machine to your bucket, and from your bucket to your client. Nobody else stores it, and nobody signs up for anything.

- **send** — Send it to your bucket. Drop the file on your delivery page, or send it from a terminal with colis envoyer. It lands in your bucket under a fresh code, with a lifetime, and if you want a password, a note, or burn after the first download. [The delivery page](https://colis-site.vercel.app/en/drop)
- **open** — Your client opens it. A link, a QR code, or eight characters typed on the page, typos repaired. They see the file before downloading anything: an image, a PDF, a video, audio, text. [How it works](https://colis-site.vercel.app/en/how-it-works)
- **ok** — They approve, or ask for changes. One click to approve, or a comment on what should change. The answer is final and timestamped, and it shows up on your sending page, in colis statut and in a webhook. [Webhooks and n8n](https://colis-site.vercel.app/en/webhooks)

## A page for your client, a terminal for you, a webhook for the rest.
One protocol under all three. The delivery page holds the keys to your bucket; the terminal and the automations talk to it.

### The delivery page (templates/drop)
A Next.js template you deploy on your bucket: the sending page, the pickup page with its preview and its two answers, and your tracking.

```text
https://drop.example.com/K7QP2M4X

  maquette-v2.pdf · 1.8 MB · PDF
  « La version avec le logo corrigé »
  [ the PDF, previewed in the page ]

  Le fichier correspond à ce qui était attendu ?
  [ Valider la livraison ✓ ]  [ Demander des corrections → ]
```

### From a terminal (@mdemb/colis)
`envoyer`, `recevoir`, `statut`, `annuler`, `verifier`: the commands are in French, the code alone goes to stdout so it composes, and `statut` says where a delivery stands.

```sh
# colis.config.json points at your delivery page (colis init --provider remote)
$ colis envoyer ./maquette-v2.pdf
maquette-v2.pdf · 1.8 MB · expires in 1 day
K7QP2M4X

# later: where does it stand?
$ colis statut K7QP2M4X
validé
envoyé  2026-09-22 10:00
ouvert  2026-09-22 11:00
validé  2026-09-22 12:00
```

### Automations (n8n-nodes-colis, @colis/protocol)
A signed webhook at every step, from `parcel.sent` to `parcel.approved`, and an n8n node that starts a workflow on any of them.

```ts
// app/api/colis/route.ts, on your side
import { verifyWebhook } from '@colis/protocol'

export async function POST(request: Request) {
  const body = await request.text() // the raw body, before any JSON.parse
  const result = await verifyWebhook(process.env.DROP_WEBHOOK_SECRET!, request.headers, body)
  if (!result.valid) return new Response(null, { status: 401 })

  const event = JSON.parse(body)
  if (event.type === 'parcel.approved') await sendInvoice(event.data.code) // your code
  return new Response(null, { status: 204 })
}
```

## Nobody in the middle.
colis is a thin layer over object storage you already pay for. The files stay in your bucket, and the page runs on your deployment.

- **Your bucket**: S3, R2, MinIO, Scaleway, Wasabi, or any S3-compatible storage. Your provider, your region, your bill.
- **No account for the client**: A code or a link is the whole handshake. A password on the parcel when you want one.
- **Straight to the bucket**: Above a few megabytes, the browser sends the file to the bucket itself, in parts, and resumes if the connection drops.
- **Expires on its own**: Every parcel has a lifetime, checked on every read. A lifecycle rule deletes the object, and colis verifier checks you have one.

- [Cloudflare R2: S3-compatible, the region is always "auto", and the dashboard takes the CORS rule as JSON.](https://colis-site.vercel.app/en/providers/cloudflare-r2)
- [AWS S3: Credentials come from the provider chain, so a Lambda or an ECS task needs no keys at all.](https://colis-site.vercel.app/en/providers/aws-s3)
- [MinIO: One Docker command, and the whole delivery flow runs on your laptop.](https://colis-site.vercel.app/en/providers/minio)
- [Scaleway Object Storage: European regions, S3-compatible, and the region actually means something.](https://colis-site.vercel.app/en/providers/scaleway)
- [Wasabi: S3-compatible, on a regional endpoint.](https://colis-site.vercel.app/en/providers/wasabi)

## A code your client can type.
Eight characters printed on a shipping label. Read out on a call, typed on a phone, scanned off a QR code: it still finds the parcel.

Eight characters of Crockford base32: no `I`, `L`, `O` or `U`, so a code survives paper, a phone keyboard and a phone call. What the client types stays as typed; only the lookup is repaired.

The code is also the link: `/K7QP2M4X` on your delivery page is the pickup page, and the page shows a QR code of it for a phone.

A code is a bearer token. When the file is sensitive, give the parcel a short lifetime, a password, or burn it at the first download.

- [Sync codes](https://colis-docs.vercel.app/docs/protocole#les-codes)
- [A confidential delivery](https://colis-site.vercel.app/en/use-cases/livraison-confidentielle)

## Every step can start something.
The delivery page posts a signed event when a parcel is sent, opened, approved, sent back for changes, or burned. n8n, or any route that takes a POST, picks it up.

- `parcel.sent`: A parcel was created, from the page or from the CLI.
- `parcel.opened`: The client opened it. The first time only.
- `parcel.approved`: The client approved it.
- `parcel.changes_requested`: The client asked for changes; data.comment says which.
- `parcel.deleted`: The code was burned.

- **Signed, the Standard Webhooks way** — HMAC-SHA256 over the id, the timestamp and the body. `verifyWebhook` from `@colis/protocol` checks it with the same code that signs, and refuses anything more than five minutes old.
- **An n8n node** — Colis Trigger starts a workflow on the events you pick and checks the signature for you. The Colis node sends, reads and burns parcels.

## What freelancers deliver with it.
### Deliver
- [Get a mock-up signed off: A PDF or an image sent under a code, previewed by the client in the page, approved in one click or sent back with a comment.](https://colis-site.vercel.app/en/use-cases/valider-une-maquette)
- [Deliver from CI: Every test build sent from CI under a code, and the client’s answer coming back as a status: approved, or changes.](https://colis-site.vercel.app/en/use-cases/livrer-depuis-la-ci)
- [Deliver heavy files: Up to 2 GB by default, sent by the browser straight to your bucket, in parts, resumed if the connection drops.](https://colis-site.vercel.app/en/use-cases/fichiers-lourds)
- [A confidential delivery: A password the client types once, a short lifetime, and a code that is gone at the first download.](https://colis-site.vercel.app/en/use-cases/livraison-confidentielle)

### Automate
- [Invoice on approval: An n8n trigger on parcel.approved: you are told, and the invoice goes out with the parcel’s code as its reference.](https://colis-site.vercel.app/en/use-cases/facturer-a-la-validation)
- [Change requests in your own tools: Every request for changes arrives signed on your route, with the client’s comment, ready to become a ticket.](https://colis-site.vercel.app/en/use-cases/corrections-dans-vos-outils)
- [An AI summary of every deliverable: When a document is sent, n8n downloads it, extracts the text and writes a five-line summary for the project log.](https://colis-site.vercel.app/en/use-cases/resume-ia-des-livrables)

## Why not an attachment, or a transfer site?
Sometimes they are enough. Each page says when, and what colis adds.

- [An email attachment: Nothing to set up, but no preview, no receipt and no structured answer.](https://colis-site.vercel.app/en/alternatives/piece-jointe)
- [A hosted transfer service: Upload on their site, get a link. Quick, but the file sits on someone else’s servers.](https://colis-site.vercel.app/en/alternatives/service-d-envoi)
- [A shared cloud folder: Good for working together over time; heavy for handing over one deliverable.](https://colis-site.vercel.app/en/alternatives/dossier-partage)
- [Sign-off by email: “Fine by me” in a thread, or one click on the delivery itself.](https://colis-site.vercel.app/en/alternatives/validation-par-e-mail)

## The ones that come up.
### What is colis?
A delivery tool for freelancers. You send a file to storage you own (S3, R2, MinIO…) under an eight-character code; your client opens a pickup page, previews the file, then approves it or asks for changes with a comment. Every step can fire a signed webhook. There is a delivery page to deploy, a CLI with French commands, and an n8n node. [How it works](https://colis-site.vercel.app/en/how-it-works)

### Does my client need an account?
No. They get a link, or type the code on the pickup page, typos included: lower case, dashes and an O for a 0 are repaired. If the parcel has a password, they type it once. That is all. On the sending side, an account is optional too: it ties your uploads to your address, signed in by e-mail link.

### Where are the files stored?
In your bucket, and nowhere else. The delivery page runs on your deployment, with your credentials; large files even go straight from the browser to the bucket. colis has no hosted service in the middle. [Storage providers](https://colis-site.vercel.app/en/providers)

### How do I know the client opened or approved it?
The delivery page keeps a receipt for every parcel: sent, opened (the first opening by someone other than you), then approved or changes, with the time and the comment. You see it on your sending page, with colis statut in a terminal, or in the parcel.opened, parcel.approved and parcel.changes_requested webhooks. [Webhooks and n8n](https://colis-site.vercel.app/en/webhooks)

### Can the client change their mind?
No: a parcel gets one answer, and it is never overwritten. For a new version, send a new parcel; it gets its own code and its own receipt.

### How big can a file be?
From the delivery page, up to DROP_MAX_UPLOAD_MB, 2 GB by default: above DROP_MAX_SIZE_MB (4 MB by default, because of Vercel’s request limit), the browser sends straight to the bucket, in 8 MiB parts, resumable. That needs a CORS rule on the bucket. From the CLI or the n8n node, the upload goes through the function in one request and has to fit under DROP_MAX_SIZE_MB. [Deliver heavy files](https://colis-site.vercel.app/en/use-cases/fichiers-lourds)

### Is a code secure?
A code is a bearer token: whoever has it can open that parcel while it lives. For a sensitive deliverable, add a password (hashed with scrypt, never recoverable), a short lifetime, or burn after the first download. Wrong passwords are limited: ten from one client, or fifty on one code, lock it for fifteen minutes. [A confidential delivery](https://colis-site.vercel.app/en/use-cases/livraison-confidentielle)

### What happens when a parcel expires?
It is never handed over again: the expiry is checked on every read, and an expired code answers like one that never existed. The object itself is deleted by a lifecycle rule on your bucket, which colis verifier checks you have. The delivery receipt outlives the file.

### Can I install it with npm?
Yes for the command: npm i -g @mdemb/colis, which works with nothing configured thanks to the public colis service. The n8n-nodes-colis node installs from n8n. The @colis/* packages are not published yet: build those from the repository (bun install, then bun run build), and deploy the delivery page on Vercel by importing the whole repository. [Install the CLI](https://colis-site.vercel.app/en/cli)

### What does it cost?
colis is free software, under the MIT license: on your own deployment, the only bills are your storage provider’s and your host’s. The public service has two plans. Free: no account, files up to 100 MB, 24-hour links, 20 uploads an hour. Pro, €6 a month or €60 a year, with an account: up to 2 GB, 30-day links, 200 uploads an hour. No trial, cancel any time. [The Pro plan (in French)](https://colis-docs.vercel.app/docs/abonnement)

A fork of [s3nd](https://github.com/AbderrahmaneMouzoune/s3nd) (MIT), by Abderrahmane Mouzoune.
