The local REST API

Windows and macOS can run an HTTP API bound to 127.0.0.1, so a script on the same machine can create projects and datasets, upload media, read and write annotations and video tracks, and drive dataset versions, splits and quality scans. It is off by default, needs a personal access token you create yourself, and never leaves the loopback interface — it is local automation, not a server anybody else can reach.

What it is, and what it is not

A local-first application has no server, which normally also means no way to script it. The REST API closes that gap without reopening the privacy question: the listener binds to the loopback address only, so nothing outside the machine can connect to it, however the network is configured.

  • It is not a collaboration server. There are no other users on the far end of it.
  • It is not exposed on your network, and there is no setting that would expose it.
  • It is not available in the browser build or on iPhone and iPad — a browser tab cannot open a listening socket.
  • It is off until you turn it on.

Turning it on

  1. Open Settings and go to the REST API section, on Windows or macOS.
  2. Choose a port — 8420 by default — and switch the listener on. A port already in use is reported rather than failing silently.
  3. Create a personal access token, and copy it there and then — only its SHA-256 digest is stored, so one that was not copied cannot be recovered, only replaced.
  4. Check the section again: it shows whether the listener is actually running, and on which port.

Authentication

Requests carry the token as a bearer credential in the Authorization header. Every endpoint needs one except GET /product-info and GET /openapi.json, which expose version discovery and the machine-readable contract without exposing user data. Every rejection returns the same message on purpose — distinguishing "no such token" from "expired" only helps someone guessing. Only a SHA-256 digest of the token is stored, so copy it when it is created: a token that was not copied cannot be recovered, only replaced. Tokens live in the same local database as everything else and can be revoked from the same settings page.

A request
curl http://127.0.0.1:8420/api/v1/projects \
  -H "Authorization: Bearer <your-token>"

What it exposes

The API covers most of what the dataset side of the app can do — not just media and annotations, but versions, splits, quality scans and video tracks as well. Grouped by area:

AreaOperations
ProjectsList, create, read, update, delete and duplicate · native project archive import/export · annotation progress · the activity-history log
DatasetsList, create, rename, delete · copy a dataset · statistics
MediaList and filter by annotation status · upload · fetch metadata or original bytes · delete
AnnotationsRead and write per image, and per video frame
Video tracksList, create, read, replace, delete a track · upsert or delete one keyframe
Dataset versionsList, create, read, delete · diff two versions · restore, with a preflight · export plan and immutable archive download
SplitsRead state, validation and the manifest · plan, apply, rebalance, reset · set and lock individual assignments
QualityStart and cancel a scan · read the last report · read the fingerprint
SystemGET /status · GET /product-info · GET /openapi.json
A few concrete paths
GET    /api/v1/projects
POST   /api/v1/projects/{projectId}/datasets
GET    /api/v1/projects/{projectId}/datasets/{datasetId}/media
PUT    …/media/{mediaId}/annotations
PUT    …/media/{mediaId}/frames/{frameNumber}/annotations
GET    …/datasets/{datasetId}/versions
POST   …/datasets/{datasetId}/quality:scan

All paths sit under /api/v1. GET /product-info reports the independent semantic API version and the application build; GET /openapi.json returns the exact OpenAPI 3.1 document compiled into that running build. A checked-in copy is generated from the same source and CI fails if the document, API version and route table disagree. This table is the map, not the contract.

The remaining roadmap is deliberately narrower: importing a generic dataset into a brand-new project, enumerating model installations, long-running prediction jobs, typed settings and feature-flag discovery still need stable service contracts before they can be promised to generated clients. Token management is deliberately absent: a token is the credential, so minting one over the API it authenticates would let a leaked token extend its own life. The live document contains only routes that the running app actually serves.

Behaviour worth knowing

  • Request bodies stay in the native process until a handler asks for them, so a large upload is never materialised in memory for a request that turns out to be unauthorised or misrouted.
  • Writes go through the same code paths as the user interface, so an annotation written over HTTP is subject to the same validation as one you draw.
  • The app must be running. This is an API on top of an open application, not a background service.

What people use it for

  • Pulling a batch of images out of an existing pipeline and into a dataset without clicking through an upload dialog.
  • Reading annotations straight into a training script during development, before the dataset is stable enough to export.
  • Scripted setup — creating the same project skeleton repeatedly with a known label set.

See also

Video tutorial

AnnotateIt tutorial