Skip to content

annosaurus

MBARI logo

Annosaurus is a REST API for creating and managing video and image annotations. It is a core service of MBARI's Video Annotation and Reference System (VARS), providing a language-agnostic interface so annotations can be created and retrieved from any programming environment.

The service is self-contained: it needs a PostgreSQL or SQL Server database and nothing else. Schema migrations are applied automatically at startup, and an interactive Swagger UI is published at /docs once it is running.

Source code and issue tracker: https://github.com/mbari-org/annosaurus

Where to start

If you are… Start here
Deciding whether annosaurus fits your project Overview — what it stores, what it deliberately leaves to other services
Reading annotations out of an existing deployment Fetching Annotations
Assembling a dataset with filters on depth, time, platform, or concept Advanced Queries
Writing annotations, or anything that changes data Security Handshake, then the Swagger UI at /docs
Standing up a server Deployment, plus For staff deploying annosaurus below

Authentication in one paragraph

Read-only endpoints are open — no token, no API key. Anyone who can reach the service can fetch and query annotations. Endpoints that create, update, or delete data require a JWT Bearer token, which you obtain by exchanging an API key for one. That exchange, and how to use the resulting token, is described in Security Handshake.

In practice:

GET  /v1/fast/videoreference/{uuid}        # no auth needed
POST /v1/query/download                    # no auth needed (a query, despite being a POST)
POST /v1/annotations                       # Authorization: Bearer <jwt>
PUT  /v1/observations/{uuid}               # Authorization: Bearer <jwt>

Note that several read-only operations use POST because they take a JSON request body — searching by a list of video references, or submitting a query. Those still need no token. The rule follows what the endpoint does, not which verb it uses.

For staff deploying annosaurus

The Deployment guide has the full procedure. The points that most often bite:

Both JWT secrets are required. BASICJWT_CLIENT_SECRET and BASICJWT_SIGNING_SECRET have no defaults — the service refuses to start without them, the same way it refuses to start without a database URL. Set them to real secrets and keep them out of source control. Earlier releases fell back to the placeholders secret and supersecret, so if you are upgrading a deployment that never set them, treat any token issued so far as compromised and rotate.

The database is the only dependency. Point DATABASE_DRIVER, DATABASE_URL, DATABASE_USER, and DATABASE_PASSWORD at a PostgreSQL or SQL Server instance. Flyway migrations run on startup, so the account needs DDL rights on first launch. Both databases are supported and tested.

Endpoints worth knowing as an operator:

Path Purpose
/v1/health Health check — returns version, JDK, and memory figures. Use for readiness and liveness probes.
/metrics Prometheus metrics for scraping.
/docs Swagger UI. Auto-generated from the running build, so it always matches the deployed version.

Restrict the service, not just the tokens. Writes require a token, but reads do not, so network placement is part of your security posture. Put annosaurus behind a reverse proxy or on a private network unless your annotations are meant to be readable by anyone who can reach the host.

Optional change notifications. Annosaurus can publish CREATED/UPDATED/DELETED messages to a NATS topic as observations and associations change, so downstream systems can stay in sync. Off by default; enable with MESSAGING_NATS_ENABLE.

Configuration precedence. Environment variables override application.conf, which overrides the built-in defaults in reference.conf. Not every setting has an environment variable — the ones that do are declared with an uppercase, underscore-separated name in reference.conf, which is the authoritative list.

The data model in brief

An imaged moment is a point in a video or an image, indexed by recorded timestamp, timecode, and/or elapsed time. It holds observations — the actual annotations, each with a concept and an observer — and image references for framegrabs. Each observation can carry associations, structured detail in linkName | toConcept | linkValue form. Ancillary data (position, depth, CTD) is cached against the moment so that spatial and environmental queries stay fast.

Annotations are keyed to video by videoReferenceUuid, a UUID that comes from the video asset service rather than from annosaurus. See the Overview for how that boundary is drawn.