Getting Started

Edit this page on GitHub

Get SirixDB running and query temporal data in minutes. Pick the path that fits your use case:

Path Time Best for
Web GUI Demo ~2 min Exploring the UI, visualizing revisions and diffs
REST API ~5 min Building web/mobile apps, language-agnostic integration
Embedded Java Library ~10 min JVM applications, maximum performance, full control
CLI Tools ~10 min Ad-hoc queries, scripting, interactive JSONiq

Prerequisites: Docker for the first two paths, JDK 24+ for the last two.


Web GUI Demo

The fastest way to see SirixDB in action. The demo starts a pre-loaded SirixDB instance with sample data and a web frontend.

1. Clone and start:

git clone https://github.com/sirixdb/sirixdb-web-gui.git
cd sirixdb-web-gui
docker compose -f docker-compose.demo.yml up --build

2. Open the GUI:

Navigate to http://localhost:3000 and log in with admin / admin.

3. Explore:

4. Tear down:

docker compose -f docker-compose.demo.yml down -v

REST API

Start a full SirixDB server with Keycloak authentication and interact via curl.

Start the server

git clone https://github.com/sirixdb/sirix.git
cd sirix
docker compose up -d

Wait for Keycloak’s health check to pass (~30 s), then the SirixDB server starts on https://localhost:9443.

Authenticate

TOKEN=$(curl -sk -X POST "https://localhost:9443/token" \
  -H "Content-Type: application/json" \
  -d '{"username":"admin","password":"admin"}' \
  | python3 -c "import sys,json; print(json.load(sys.stdin)['access_token'])")

Store a JSON document

curl -sk -X PUT "https://localhost:9443/shop/products" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '[
    {"name": "Laptop", "price": 999},
    {"name": "Phone",  "price": 699},
    {"name": "Tablet", "price": 449}
  ]'

This creates a JSON database called shop with a resource called products — revision 1.

Read it back

curl -sk "https://localhost:9443/shop/products" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Accept: application/json"

Update the document (revision 2)

First, get the ETag of the root node:

ETAG=$(curl -skI "https://localhost:9443/shop/products?nodeId=1" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Accept: application/json" \
  | grep -i etag | tr -d '\r' | cut -d' ' -f2)

Then insert a new product:

curl -sk -X POST "https://localhost:9443/shop/products?nodeId=1&insert=asFirstChild" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "ETag: $ETAG" \
  -d '{"name": "Monitor", "price": 349}'

Time travel — read revision 1

curl -sk "https://localhost:9443/shop/products?revision=1" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Accept: application/json"

Diff two revisions

curl -sk "https://localhost:9443/shop/products/diff?first-revision=1&second-revision=2" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Accept: application/json"

Temporal JSONiq query

Retrieve all revisions of the entire document:

curl -sk -X POST "https://localhost:9443/" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{"query": "jn:all-times(jn:doc(\"shop\",\"products\"))"}'

Tear down

docker compose down -v

For the full endpoint reference, see REST API.


Embedded Java Library

Use SirixDB directly inside your JVM application for maximum performance and fine-grained control.

Add the dependency

Gradle (Kotlin DSL):

repositories {
    mavenCentral()
    maven("https://oss.sonatype.org/content/repositories/snapshots/")
}

dependencies {
    implementation("io.sirix:sirix-core:0.11.1-SNAPSHOT")
}

Maven:

<repositories>
  <repository>
    <id>sonatype-snapshots</id>
    <url>https://oss.sonatype.org/content/repositories/snapshots/</url>
    <snapshots><enabled>true</enabled></snapshots>
  </repository>
</repositories>

<dependencies>
  <dependency>
    <groupId>io.sirix</groupId>
    <artifactId>sirix-core</artifactId>
    <version>0.11.1-SNAPSHOT</version>
  </dependency>
</dependencies>

Complete example

import io.sirix.access.DatabaseConfiguration;
import io.sirix.access.Databases;
import io.sirix.access.ResourceConfiguration;
import io.sirix.api.JsonNodeReadOnlyTrx;
import io.sirix.api.JsonNodeTrx;
import io.sirix.api.json.JsonResourceSession;
import io.sirix.service.json.serialize.JsonSerializer;
import io.sirix.service.json.shredder.JsonShredder;

import java.io.StringWriter;
import java.nio.file.Files;
import java.nio.file.Path;

public class SirixQuickStart {
    public static void main(String[] args) throws Exception {
        final var dbPath = Path.of(System.getProperty("java.io.tmpdir"), "sirix-getting-started");

        // Clean up from previous runs
        if (Files.exists(dbPath)) {
            Databases.removeDatabase(dbPath);
        }

        // 1. Create a database and resource
        Databases.createJsonDatabase(new DatabaseConfiguration(dbPath));

        try (final var database = Databases.openJsonDatabase(dbPath)) {
            database.createResource(ResourceConfiguration.newBuilder("products").build());

            // 2. Insert JSON data (revision 1)
            try (final var session = database.beginResourceSession("products");
                 final var wtx = session.beginNodeTrx()) {

                wtx.insertSubtreeAsFirstChild(JsonShredder.createStringReader("""
                    [
                      {"name": "Laptop", "price": 999},
                      {"name": "Phone",  "price": 699}
                    ]
                    """));
                wtx.commit();

                // 3. Update data (revision 2) — add a product
                wtx.moveTo(1); // move to the array node
                wtx.insertSubtreeAsFirstChild(JsonShredder.createStringReader(
                    """
                    {"name": "Monitor", "price": 349}
                    """));
                wtx.commit();
            }

            // 4. Read a specific revision
            try (final var session = database.beginResourceSession("products");
                 final var rtx = session.beginNodeReadOnlyTrx(1)) {
                // rtx is now positioned at revision 1
                final var writer = new StringWriter();
                final var serializer = new JsonSerializer.Builder(session, writer)
                    .startNodeKey(rtx.getNodeKey())
                    .revisions(new int[]{1})
                    .build();
                serializer.call();
                System.out.println("Revision 1: " + writer);
            }

            // 5. Read the latest revision
            try (final var session = database.beginResourceSession("products");
                 final var rtx = session.beginNodeReadOnlyTrx()) {
                final var writer = new StringWriter();
                final var serializer = new JsonSerializer.Builder(session, writer).build();
                serializer.call();
                System.out.println("Latest:     " + writer);
            }
        }

        // Clean up
        Databases.removeDatabase(dbPath);
    }
}

Key concepts:

For the full cursor API, see Cursor API. For the DOM-alike layer, see DOM-alike API.


CLI Tools

Kotlin CLI

Build and run the Kotlin CLI for basic database operations:

git clone https://github.com/sirixdb/sirix.git
cd sirix
./gradlew :sirix-kotlin-cli:build

Usage:

java -jar bundles/sirix-kotlin-cli/build/libs/sirix-kotlin-cli-*-all.jar --help

Interactive JSONiq shell

Launch an interactive shell to run JSONiq queries:

./gradlew :sirix-query:run

This opens a REPL where you can run temporal queries against local databases. See the JSONiq Tutorial for query examples.


What’s next?