Developer & Server Workflows

Automating Secure File Transfer: the SRIFT REST API and SDKs

By SRIFT maintainers · Published

Reviewed by SRIFT maintainers · last reviewed against the SRIFT 4.3.2 source.

Short answer

A file-transfer API is secure when the file is encrypted before it leaves your machine, the caller is authenticated appropriately, links can expire and be revoked, and large files stream instead of loading into memory. Most cloud transfer APIs meet some of these by uploading to the provider under an API key; the provider then holds the file and usually the key.

SRIFT takes the other route: a daemon on 127.0.0.1:3822 exposes a REST API (documented in OpenAPI 3.1), reads and encrypts files locally, and streams them out over outbound HTTPS. There is no API key and no upload; zero-dependency SDKs for Python, Node.js, Go, Rust, Java, .NET, PHP, Ruby, Bash and PowerShell wrap it.

Base URL
http://127.0.0.1:3822 (SRIFT_BASE_URL overrides)
Spec
OpenAPI 3.1 at /openapi.json
Auth
None: loopback only, local callers
Events
Server-sent events at /api/v1/monitor/events

What makes a file-transfer API secure

Whatever service you call, the same handful of design questions decide what an integration can leak. They are worth asking before writing any code against a transfer API.

  • Where encryption happens. If your code uploads the plaintext over HTTPS, the provider can read it. Only encryption performed before the request (client-side or end-to-end) keeps the provider out; see client-side vs server-side encryption.
  • What the credential can do. A long-lived API key in a CI job or an agent sandbox is a standing liability. Prefer scoped, short-lived credentials, or designs that need none.
  • Link lifetime and revocation. A download link is a bearer secret. The API should let you set a download cap and an expiry when you create it, and revoke it afterwards.
  • Streaming. Files should be read and sent in chunks. An API that wants the whole file in one request body, or base64 inside JSON, will fail on large files and multiply memory use.
  • Events instead of polling. Transfers take time. A push channel for progress and incoming requests is simpler and cheaper than polling a status endpoint.
  • Retention. Find out whether the provider stores the file, for how long, and whether deleting the link deletes the bytes.

The SRIFT approach: a local daemon API

A local file-transfer API compared with a cloud upload APIYour script calls a daemon on 127.0.0.1, which reads the file and encrypts it on the same machine before streaming it out through a relay. With a cloud API, the script uploads the file to the provider with an API key and the provider stores it.your machineScript / SDKHTTP + JSONDaemon127.0.0.1:3822pathRelayforwards, stores nothingciphertext, 443Script / SDKAPI keyCloud APIstores the uploadwhole file, TLS, provider can read it unless you encrypt first
With a local daemon, the file is read and encrypted on the same machine and only ciphertext leaves it. With a typical cloud API, the file is uploaded to the provider.

The srift CLI starts a background daemon on first use. It listens on 127.0.0.1:3822 only (set SRIFT_DAEMON_PORT to change the port) and exposes the same operations as the CLI and the MCP server: quick-share links, sessions, in-session transfers, chat, diagnostics and an event stream. The daemon holds the keys and reads files directly from disk, so your code passes a path, not bytes.

Because it only listens on loopback, there are no API keys. The flip side is that every program on the machine can call it, so on a shared multi-user host treat it as available to all local users, and stop it with srift daemon stop when it is not needed.

The endpoints most integrations need:

Core endpoints of the SRIFT daemon API (version 4.3.2). The full list, with schemas, is in /openapi.json.
EndpointWhat it does
POST /quick-shareTurn a file or folder into a download link. Body: filePath (or filePaths), encrypt, password, maxDownloads, ttlMs, exclude.
GET /pubshare/listEvery active link with its download counters.
POST /pubshare/revokeInvalidate a link immediately. Body: token.
POST /session/startCreate a session; returns sessionId and a browser joinUrl. Optional roomSecret.
POST /session/approveAdmit a person or agent who asked to join. Body: tempUserId.
POST /sendOffer a file to the session's members. Body: filePath.
POST /receiveAccept an incoming offer and save it. Body: fileId, saveDir.
GET /api/v1/monitor/eventsServer-sent events: connection_state, join_request, file_offer, transfer_progress, chat_received.
GET /v1/diagWhich transports work on this machine, with a fix for each blocked one.
GET /healthLiveness, version and uptime.

Sending a file: curl and the SDKs

Start the daemon once (srift daemon start, or any srift command starts it), then create a link. The request names a local path; the response carries the URL to hand to the recipient.

curl
curl -s http://127.0.0.1:3822/quick-share \
  -H 'Content-Type: application/json' \
  -d '{"filePath":"/srv/exports/report.pdf","encrypt":true,"maxDownloads":1,"ttlMs":3600000}'
Response (abridged)
{
  "success": true,
  "token": "<token>",
  "downloadUrl": "https://srift.app/d/<token>#k=<key>",
  "fileName": "report.pdf",
  "encrypted": true,
  "maxDownloads": 1,
  "expiresAt": 1791460800000
}

With encrypt set, the file is sealed with AES-256-GCM in the daemon and the key exists only in the part of downloadUrl after #k=. Treat the whole URL as a secret: do not log it. The link works while the daemon runs, and POST /pubshare/revoke with the token ends it early.

Python

pip install srift installs the CLI and the Python SDK together. The SDK uses only the standard library.

share.py
from srift import Srift

s = Srift()  # http://127.0.0.1:3822, or SRIFT_BASE_URL
link = s.quick_share("/srv/exports/report.pdf", encrypt=True, max_downloads=1, ttl_ms=3_600_000)
print(link["downloadUrl"])

Node.js

The Node.js SDK is a single dependency-free file, published at https://srift.app/sdk/node/srift.mjs; it needs Node.js 18 or later for the built-in fetch.

share.mjs
import { Srift } from "./srift.mjs"

const s = new Srift()
const link = await s.quickShare("/srv/exports/report.pdf", { encrypt: true, maxDownloads: 1 })
console.log(link.downloadUrl)

The Go, Rust, Java, .NET, PHP, Ruby, Bash and PowerShell clients follow the same method names and are linked from llms.txt. All of them are thin HTTP clients: none bundles the daemon, so the srift CLI must be installed on the machine.

Receiving files: sessions and events

To receive a file from a person, a script opens a session, waits for them to ask to join, admits them, and accepts their offer. The event stream drives the whole flow without polling:

receive.py
from srift import Srift

s = Srift()
session = s.start_session(name="uploads")
print("Send this link to the sender:", session["joinUrl"])

for ev in s.stream_events():
    if ev["event"] == "join_request":
        # Check who it is before admitting: anyone with the link can ask.
        s.approve_join(ev["data"]["tempUserId"])
    elif ev["event"] == "file_offer":
        s.accept_transfer(ev["data"]["fileId"], save_dir="./incoming")
    elif ev["event"] == "transfer_progress" and ev["data"].get("status") == "completed":
        print("received", ev["data"]["fileId"])
        break

Chunks that pass through the relay are sealed with AES-256-GCM under a key the two sides agree with ECDH. When both ends are scripts or agents, pass the same room_secret to start_session and join_session: it is mixed into the keys and never sent to the server, which closes the key-substitution gap described in the SRIFT security architecture.

REST, CLI or MCP?

The daemon serves three interfaces over the same core. Pick by who is driving it:

  • Shell scripts and CI: the CLI. srift quick-share file --encrypt --once --json prints one JSON line, and it can run without a background daemon in sandboxes. See sharing CI/CD build artifacts.
  • Applications and services: the REST API or an SDK, especially when you need events or several operations in one process.
  • AI agents: the MCP server, which exposes the same operations as tools with typed schemas. See setting up SRIFT in MCP clients.

In each case the security properties come from the daemon: what is encrypted, what the relay sees and how links expire do not change with the interface. What a relay can see lists the metadata that remains.

Frequently asked questions

Does the SRIFT API need an API key?

No. The daemon listens only on 127.0.0.1 and has no accounts or keys. Any program on the same machine can call it, so stop the daemon on shared hosts when you are not using it.

Can I call the SRIFT API from another machine?

Not the daemon: it binds to the loopback address only. Run the daemon or CLI on the machine that has the file. Cloud agents that cannot run local processes can use the hosted MCP endpoint at https://srift.app/mcp for session control, but it cannot read files.

Is there a file size limit in the API?

SRIFT sets no limit. The daemon reads the file from disk in chunks and streams it, so the practical limits are disk space on the receiving side and the time both ends stay online.

References

  1. SRIFT OpenAPI 3.1 definition (SRIFT)
  2. OpenAPI Specification 3.1 (OpenAPI Initiative)
  3. Server-sent events (WHATWG)
  4. RFC 9110: HTTP Semantics (range requests) (IETF)
  5. RFC 3986: URI Generic Syntax (fragment identifiers) (IETF)

Use SRIFT from a terminal

One command prints a download link that streams from your machine. Needs only outbound HTTPS; --encrypt keeps the key out of the relay.

npx -y srift-transfer quick-share ./build.tar.gz --encrypt