Getting started
First five minutes
applies to v0.5.1This walk-through stores a key, a JSON document and a relational table in a fresh installation, using only curl. It assumes the service from Install is running and that KEY holds the admin key:
KEY=lura_… # your admin key from /etc/luradb/luradb.tomlResponse headers are shortened to the ones that matter; timestamps and generated keys differ on your machine.
A key with an expiry takes two requests
Section titled “A key with an expiry takes two requests”Every engine starts with a domain called default. Create a domain of your own for sessions and store a key in it that expires after an hour:
curl -s -X POST http://127.0.0.1:3000/store-api/domains \ -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \ -d '{"name": "sessions"}'{ "name": "sessions", "created_at": 1793741597, "require_conditional_writes": false }curl -s -X PUT "http://127.0.0.1:3000/store-api/kv/sessions/keys/s-4f2a?ttl=3600" \ -H "Authorization: Bearer $KEY" -d '{"user": "jane"}'The write answers 200 with an empty body. Read the key back with -i to see the headers:
curl -si http://127.0.0.1:3000/store-api/kv/sessions/keys/s-4f2a \ -H "Authorization: Bearer $KEY"HTTP/1.1 200 OKcontent-type: application/octet-streamx-expires-at: 1793745198etag: "1a1a354a9f90000"content-length: 16
{"user": "jane"}A value is plain bytes; LuraDB does not interpret it. X-Expires-At is the absolute expiry in Unix seconds and the ETag names this version of the key, which conditional writes use. Once the hour is over, the key answers 404.
A document is found by an indexed field
Section titled “A document is found by an indexed field”JSON documents live in their own domains. Create orders, index the field status and store two documents:
curl -s -X POST http://127.0.0.1:3000/store-api/json/domains \ -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \ -d '{"name": "orders"}'curl -s -X POST http://127.0.0.1:3000/store-api/json/orders/indexes \ -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \ -d '{"field": "status", "type": "string"}'curl -s -X POST http://127.0.0.1:3000/store-api/json/orders/documents \ -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \ -d '{"customer": "Jane Doe", "status": "open", "total": 42.5}'curl -s -X POST http://127.0.0.1:3000/store-api/json/orders/documents \ -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \ -d '{"customer": "Omar Haddad", "status": "shipped", "total": 19}'Each document comes back with the key LuraDB generated and its version:
{ "_key": "64780537-af9d-4d79-8326-540691f325ba", "_version": 1, "customer": "Jane Doe", "status": "open", "total": 42.5 }Search accepts filters on indexed fields only; a filter on a field without an index answers 400. Create the index before you store documents, or reindex afterwards.
curl -s -X POST http://127.0.0.1:3000/store-api/json/orders/search \ -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \ -d '{"filter": {"status": "open"}}'{ "documents": [ { "_key": "64780537-af9d-4d79-8326-540691f325ba", "_version": 1, "customer": "Jane Doe", "status": "open", "total": 42.5 } ], "total": 1, "offset": 0, "limit": 50}A table is queried with SQL
Section titled “A table is queried with SQL”Relational tables are created and queried through one endpoint that takes one LuraSQL statement per request. The domain is again called orders; the relational engine has its own domains. Values go in as parameters:
curl -s -X POST http://127.0.0.1:3000/store-api/rel/domains \ -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \ -d '{"name": "orders"}'curl -s -X POST http://127.0.0.1:3000/store-api/rel/orders/sql \ -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \ -d '{"sql": "CREATE TABLE customers (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, city TEXT)"}'curl -s -X POST http://127.0.0.1:3000/store-api/rel/orders/sql \ -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \ -d '{"sql": "INSERT INTO customers (name, city) VALUES (?, ?)", "params": ["Jane Doe", "Lisbon"]}'curl -s -X POST http://127.0.0.1:3000/store-api/rel/orders/sql \ -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \ -d '{"sql": "INSERT INTO customers (name, city) VALUES (?, ?)", "params": ["Omar Haddad", "Tunis"]}'The statements answer {"ok":true} and {"affected":1,"last_pk":1}. A SELECT returns typed columns and rows:
curl -s -X POST http://127.0.0.1:3000/store-api/rel/orders/sql \ -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \ -d '{"sql": "SELECT id, name, city FROM customers WHERE city = ?", "params": ["Lisbon"]}'{ "columns": [ { "name": "id", "type": "INTEGER" }, { "name": "name", "type": "TEXT" }, { "name": "city", "type": "TEXT" } ], "limit_applied": false, "row_count": 1, "rows": [[1, "Jane Doe", "Lisbon"]]}The API describes itself in Swagger UI
Section titled “The API describes itself in Swagger UI”Turn the Swagger UI on in /etc/luradb/luradb.toml and restart the service:
[server]swagger_enabled = trueThe UI is served at server.swagger_url (default /test-ui) and the OpenAPI contract at /api-docs/openapi.json. While authentication is on, both need the Bearer key, and that includes the page of the UI itself. A browser that opens /test-ui/ sends no such header and gets 401 Unauthorized; the contract is available to curl:
curl -s http://127.0.0.1:3000/api-docs/openapi.json -H "Authorization: Bearer $KEY"To click through the API in a browser on a machine of your own, start the server with auth.enabled set to false, which LuraDB accepts only on a loopback address, and open http://127.0.0.1:3000/test-ui/. Every endpoint, with its status codes and conditions, is also in the generated pages under REST API.
Where to go next
Section titled “Where to go next”- Domains and engines explains the three engines and how rows link to keys and documents.
- Key-value, JSON documents and LuraSQL cover each engine in detail.
- Security creates users whose keys reach only some domains, so that your application does not run with the admin key.