Skip to content
svc.nz
Blog
Transfer guide · 6 min read

How do I receive files from someone without giving them an account?

Create a box, give the sender only a write capability and keep the read capability for yourself. The sender can then upload with curl or the svcbox client without an account, and cannot download, list or read back anything, including their own upload.

17 October 2026 · svc.nz

What a write-only handoff needs to do

Receiving a file from someone usually forces a choice between two awkward options. Either the sender creates an account on a service you both use, or you hand over a credential that can also read everything you have stored. A write-only capability removes that choice, because it grants exactly one verb, which is adding bytes, and nothing that lets the holder look at what is already there.

HTTP already supplies the pieces you need. RFC 9110 defines PUT as storing a representation at a target and the Authorization header as the place to carry a credential. The remaining work is deciding what the credential allows, which is the least-privilege question that the OWASP authorization guidance asks of any access design. For a drop-off the answer is narrow: the sender may deposit, the owner may collect.

Create the box and keep the read capability

The unit you create is a box, a named space that holds uploaded objects, each with its own list of versions. In svc.nz the first upload to a new box creates it, and the response to that upload hands back a read capability, a write capability and a longer-lived owner capability for later administration. During the private trial a new box on the hosted service is created by invitation, so read the policy centre for the current status before planning around it. Once you hold the capabilities, handing out access needs no account on the sender's side.

Keep the read capability and the owner capability to yourself. Give the sender only the write capability, along with the box name and the object name you want them to use. The commands below use placeholders in angle brackets, because a real capability is a secret and belongs in a header, never in a URL, a ticket title or a chat link.

One box, two capabilities with different verbs The sender holds a write capability and uploads into the box with PUT. The owner holds a read capability and downloads from the box with GET. The write capability is refused on download and the read capability is refused on upload. SENDER write capability BOX versioned objects YOU read capability PUT GET GET refused PUT refused
The same box accepts a PUT from the write capability and a GET from the read capability, and refuses the opposite verb in each case.
Action Write capability Read capability
Upload an object (PUT) Accepted Refused with 401
Download an object (GET) Refused with 401 Accepted
List names in the box Refused with 401 Accepted

The table records one run against the repository's own server on a local machine, with one freshly created box and one request per cell, so it shows the intended behaviour rather than a statistical sample. The refusal messages were "Write-only capability cannot read." and "Read-only capability cannot write."

What the sender runs

Anyone with curl can upload using a single command. The file travels as raw bytes, so --data-binary matters: it stops curl from treating the content as a web form.

curl -X PUT -H "Authorization: Capability <write-capability>" \
  --data-binary @invoice.pdf \
  https://in.svc.nz/<box>/invoice.pdf

Anyone who already has the svcbox client can use its put command instead, with the box, the object name, the file and the capability. The client sends the capability in the same header, so nothing about the secret reaches a URL.

svcbox put <box> invoice.pdf invoice.pdf --cap <write-capability>

Both commands print or return the new version number and nothing the sender can use to fetch the file back. That is the point of the design: a successful upload proves the bytes were stored, and the sender has no way to confirm their content beyond that. If you want them to know it arrived, tell them out of band.

How you read what arrived

With the read capability you fetch the latest version of an object, or pin a specific one when you need the same bytes again. The two commands below were run against a local server with a file the sender had uploaded using the write capability, and the downloaded copy matched the original.

curl -H "Authorization: Capability <read-capability>" \
  https://out.svc.nz/<box>/invoice.pdf/latest -o invoice.pdf

svcbox get <box> invoice.pdf latest --cap <read-capability> --out invoice.pdf

The read capability can also list the names in the box and the versions of one name, which is how you find out what several senders have deposited. The svcbox versions command prints each version with its size, type and time. Compare a checksum of the received file with one the sender gives you through a different channel when the content matters, because a capability controls access and says nothing about integrity.

Limits and expiry

Every upload becomes a new version, so a second upload to the same name adds a version and leaves the earlier one readable by you. A sender holding the write capability can therefore add to a name that already exists. If one box serves several senders, give each a distinct object name, and ask them to add an If-None-Match: * header so a PUT to a taken name is refused with a 412 status instead of adding a version. That refusal was confirmed in the same local run.

Boxes created without an account expire, and expiry ends normal access through the API for every capability on the box. It does not promise that the underlying bytes are erased at that moment, so a sensitive file should be encrypted by the sender before upload and the key passed through a separate channel. Collect what you need before the expiry time shown in the response to your first upload.

Size, storage and request limits also apply. This post does not list the numbers, because they belong to the deployment and can change. The response to the first upload reports the limits that apply to that particular box, so check those figures before asking a sender for a large file.

Next, create a box with a small test file, hand a colleague only the write capability and ask them to upload something. Then try a download with that same capability and confirm it is refused, which tells you the handoff behaves as described before a real sender depends on it.

FAQ

Can the sender see what other people uploaded?

Nothing beyond the response to their own upload is visible to them. A write-only capability is refused when it tries to download or list names.

Can the sender overwrite someone else's file?

A second upload to a name that already exists becomes the next version of that name, and earlier versions stay available to the read capability. Give each sender a distinct name, or have them add an If-None-Match: * header so an upload to a taken name is refused.

What if the write capability leaks?

Whoever holds it can add uploads to the box until it expires, but cannot read anything back. Treat it as a bearer secret, send it over a channel you trust for the job and let it expire when the job is done.

Does the sender need svcbox installed?

Any HTTP client that can send a PUT request with an Authorization header works, and curl is the smallest example. svcbox adds a convenient put command for people who already have it.

Sources

HTTP Semantics, the standard reference; OWASP Authorization Cheat Sheet; curl man page.

svc.nz Notes for the private trial. Operated by Anphase Ltd in Aotearoa New Zealand.
Policy centreTermsPrivacyAcceptable useAbuseSecurityCopyrightCookiesSubprocessors