replace big-tech and host basic infrastructure yourself! ordner.fyi
ordner docs developers
2 folders · 13 files

README.md

Writing an application for an ordner.fyi install #

This guide is for someone who writes an application against an ordner.fyi install and has never read anything else about it: a desktop photo manager, a phone app, an AI agent on a server, a script. It says everything such an application needs: how it finds the install, registers, signs the person in, reads their files and pictures, writes back what it found, keeps a copy in step, and what it owes the person whose data it reads.

An install is one organisation's self-hosted suite (mail, calendar, files, photos and more) on one origin, here https://ordner.example. Its files and pictures are served over JMAP (RFC 8620), the person signs in with OAuth 2.0 and OpenID Connect, and an application registers itself without anyone's help (RFC 7591).

Chapters #

Chapter What it says
Concepts Annotators and front-ends, sources, what the server never does, the person's control
Discovery From the origin to the session and the authorization server: _jmap._tcp, /.well-known/jmap, RFC 9728, RFC 8414
Registration RFC 7591 registration with every field and rule, RFC 7592 management, limits
Signing in The loopback code flow with PKCE, the device grant, what the person sees per scope, tokens, refresh, revocation, withdrawn lines; app passwords; acting as a delegate; how rights combine
JMAP for this API Sessions, requests, /get /set /query /changes, back-references, upload and download, capabilities and limits
Reference Every type, property, method, argument, filter condition, comparator, facet, error and limit
Keeping up and keeping a copy The annotator's queue, /changes, changedAfter and updatedAfter, cannotCalculateChanges, push
Recipes An annotator's loop, defining fields and views, faces and embeddings, semantic search, album suggestions, acting for someone
Privacy duties Biometric data, what the person sees, Remove what it added, text the web apps treat as untrusted
Errors and rate limits HTTP errors, method errors, SetErrors, 429
Compatibility How the API is versioned and what may change
The reference client scripts/annotate-example.ts, a complete application in Node built-ins, walked through

JSON Schema for every type is in schema/, generated from the very constants the server checks with.

The examples are executed #

Every request and answer in this guide is a file under examples/. The install's own tests send each one to the real server, in order, and compare its answer with the file; a change of the server that changes an answer fails them. The guide quotes the files as they are.

Values the server makes, which differ every time (ids, blob ids, states, tokens, dates), are written as placeholders:

  • ${name} is a value the server made and the example names: the first time a name appears in an answer it stands for whatever the server answered there, and every later appearance, in a request or an answer, means the same value. ${picture1} is the id of a picture, ${picture1Blob} the blob id of its content, ${accessToken} the access token of the credential that sends the request.
  • ${*} is a value the example does not name: a state, a date, a token nobody uses again.

A few names are given before the first example, by the setup the examples run in:

Name What it is
${accountId} Pip's account, the drive the examples work in
${emmaAccountId} Emma's account; Pip has delegated drive:read and drive:annotate on Pip's drive to Emma
${pictures}, ${documents} Pip's folders Pictures and Documents
${picture1}, ${picture2} Pictures/IMG_0001.JPG and IMG_0002.JPG, both read by the photo worker
${invoice}, ${notes} Documents/invoice-2026-10.pdf and Documents/notes.txt
${faceVector1}, ${faceVector2}, ${imageVector1}, ${imageVector2}, ${textQuery} 64-dimension vectors, base64 of little-endian float32

The applications in the examples are registered relying parties: "Photo Sorter" (client id rp-7Kq2mWv9XbTa), an annotator; "Library" (rp-L1brAry0x9Qz), a front-end; and "Frame" (rp-Fr4m3sPh0t0s), granted the Pictures folder only. The person is Pip (pip@ordner.example); Emma (emma@ordner.example) is Pip's delegate. Ids such as account ids are opaque: an application never builds one from a name, it reads them from the session.

What is not executed: the person's own steps on the install's web pages (signing in, ticking consent lines, approving a device code) happen in the tests through the server's own functions, not over HTTP; a JMAP answer of 401 with its WWW-Authenticate header is served by the install's origin in front of the files service and is described, not executed.