SFTP for EDI and ERP feeds, wired to your API
Accept orders, invoices and stock feeds over SFTP, then process each file the moment it lands.
The problem. Sound familiar?
Your trading partners' ERP can only push files over SFTP or FTP, but your stack is APIs and queues.
Polling a folder every few minutes is slow, and it's easy to miss or double-process files.
The old integration server in the corner is a single point of failure that nobody wants to touch.
How it works with CloudFile, in about a minute.
- Step 1
Give each system a login
One user per trading partner or ERP, with the protocol it supports: SFTP, FTPS or FTP.
erp-acme SFTP ssh-ed25519 AAAA… - Step 2
Filter the events you care about
Fire only for finished files in the right folder, such as path starts with /orders and ends with .xml.
upload, rename path ^/orders/ .xml$ - Step 3
Process it in your pipeline
Your endpoint gets a signed webhook with a download link and pulls the file.
POST /hooks/edi /orders/PO-4821.xml 200
What you get, and nothing you have to run.
Every protocol
SFTP, FTPS and FTP, switchable per server, for systems that were configured a decade ago.
Event-driven, not polling
A webhook per upload, rename or delete, filtered by path or user. No cron job watching a folder.
Signed deliveries
Every request is signed with HMAC-SHA256 and a timestamp, so you can reject anything that didn't come from us.
Retries built in
Failed deliveries retry with backoff for hours, and you can resend any event from the last 30 days.
Fresh download link
Each delivery includes a presigned URL valid for an hour. Fetch the file with a plain GET.
Delivery log
Every attempt is listed with its status code, so you can tell a partner exactly when their file was processed.
Handle a new order file. Verify the signature, then download the file from the link in the payload.
import { createHmac, timingSafeEqual } from "node:crypto";
app.post("/hooks/edi", express.raw({ type: "application/json" }), async (req, res) => {
const { t, v1 } = Object.fromEntries(
req.get("X-CloudFile-Signature").split(",").map((p) => p.split("=")),
);
const expected = createHmac("sha256", process.env.CLOUDFILE_SECRET)
.update(`${t}.${req.body}`)
.digest("hex");
if (!timingSafeEqual(Buffer.from(expected), Buffer.from(v1))) return res.sendStatus(401);
const event = JSON.parse(req.body);
const xml = await fetch(event.download_url).then((r) => r.text());
await queue.add("import-order", { path: event.full_path, xml });
res.sendStatus(200);
});Questions about this setup.
My partner's system uploads under a temporary name. Will I get two events?
Listen to both upload and rename and add a filter such as path ends with .xml. You only get the event for the finished file, and full_path always holds the final name.
What if my endpoint is down?
We retry with exponential backoff for several hours. After that you can resend any event from the dashboard for 30 days.
Can I also send files back, like order confirmations?
Yes. Upload into the partner's folder over SFTP from your own system, or through the web file manager, and their ERP picks it up.
Which formats do you support?
Any. We move files and don't parse them, so EDIFACT, X12, XML, CSV or ZIP archives all work the same way.
More in the docs: Webhooks, payload and signatures · Users and permissions · Connecting
Other jobs for the same server.
File exchange with partners
One login and one private folder per partner, with a notification on every upload.
Learn moreScanners, cameras and devices
Point scanners, cameras and NAS boxes at a cloud FTP server instead of a PC under the desk.
Learn moreSFTP for serverless apps
Your customers upload over SFTP. Your function gets a signed webhook with a download link.
Learn moreRansomware-proof backups
Back up with a login that can add files but not delete or replace them, on top of a versioned bucket you own.
Learn more