Public APIs

Raijin provides two types of API access to extend its manageability and interoperability with other systems.

Both APIs are discussed in detail below.

Direct JSON API

The Direct JSON API is a set of endpoints for ingesting and querying data in a Raijin database.

A POST request to RAIJIN_SRV:RAIJIN_PORT/DB_NAME/TABLE_NAME with a series, or an array, of single-object JSON documents inserts data into the specified table. The endpoint accepts data in the NDJSON format. The database and table specified must already exist.

The response indicates the number of records ingested successfully, the number of failed records, the reason for any failures, and the respective database and table names.

{"copy":1,"failed":"1","reasons":"[{\"line\": 1, \"error\": \"Invalid JSON (Missing a closing quotation mark in string.). File offset: 14\", \"record\": \"{\"Version: 10, <...>}\"}]","database":"logs","table":"demo"}

Malformed POST data will return an HTTP 400 status code. See Error handling for further details.

API query structure

Send a POST request with the following structure to execute a query:

{
  "query": "QUERY_STRING"
}

The QUERY_STRING may contain any number or combination of supported SQL queries (SELECT, INSERT, etc.), each terminated with a semicolon (;), with the entire set of queries enclosed in double quotes (" ").

Ingesting data

NDJSON

JSON objects are often saved to file or streamed over the network as NDJSON (newline-delimited JSON). NDJSON data can be POSTed to Rajin as is for ingestion as seen here.

Example 1. Inserting multiple flat JSON objects in NDJSON format
$ curl -sS raijin.example.com:2500/logs/demo -d '{"field1":-3.2,"field2":false}
{"field1":5.671,"field2":true}
{"hostname":"g01c335n2027","os":"Windows","active":1}
{"hostname":"g01c335n2028","os":"Linux","active":0}
'

Querying Raijin

The following examples use the API query structure for querying Raijin.

Database administration

Like most SQL-capable database engines, Raijin accepts standard SQL queries for administering databases and tables.

Example 2. Create a new table

In this example, a new, schemaless table called demo is created.

curl -sS raijin.example.com:2500 -d '{"query":"USE logs; CREATE TABLE demo();"}'
Example 3. Verify table creation
$ curl -sS raijin.example.com:2500 -d '{"query":"USE logs; SHOW TABLES;"}'
Result
{"table":"demo","record_count":14,"encrypted":"no","partitioning_type":"none","size":71}

Querying data

Data queries must reference existing tables and the database they belong to. If DB_NAME is not specified in the FROM clause as FROM DB_NAME.TABLE_NAME, then the SQL query needs to be prefixed with USE DB_NAME;.

Example 4. USE DB_NAME
curl -sS raijin.example.com:2500 -d '{"query":"USE logs; SELECT * FROM demo;"}'
Result
{"_id":4311,"field1":-3.2,"field2":false}
{"_id":4312,"field1":5.671,"field2":true}
{"_id":4313,"hostname":"g01c335n2027","os":"Windows","active":1}
{"_id":4314,"hostname":"g01c335n2028","os":"Linux","active":0}
Example 5. FROM DB_NAME.TABLE_NAME
curl -sS raijin.example.com:2500 -d '{"query":"SELECT * FROM logs.demo;"}'
Result
{"_id":4311,"field1":-3.2,"field2":false}
{"_id":4312,"field1":5.671,"field2":true}
{"_id":4313,"hostname":"g01c335n2027","os":"Windows","active":1}
{"_id":4314,"hostname":"g01c335n2028","os":"Linux","active":0}
Example 6. Table-independent queries

For queries that involve only constants or functions, i.e., queries tha do not require a FROM clause, there is no need to reference a DB_NAME or TABLE_NAME.

$ curl -sS raijin.example.com:2500 -d '{"query":"SELECT pi(),ln(2.718281828)"}'
Result
{"pi":3.141593,"ln":1}
curl -sS raijin.example.com:2500 -d '{"query":"SELECT QUARTER(NOW()),YEAR(NOW())"}'
Result
{"quarter":2,"year":2022}

Error handling

Example 7. Invalid SQL statements

Raijin will return a HTTP 400 status code and a JSON-formatted response for invalid SQL statements.

$ curl -sv raijin.example.com:2500 -d '{"query":"selert 1 as one;"}' | jq
*   Trying 192.168.1.60:2500...
* Connected to raijin.example.com (192.168.1.60) port 2500 (#0)
> POST / HTTP/1.1
> Host: raijin.example.com:2500
> User-Agent: curl/7.77.0
> Accept: */*
> Content-Length: 28
> Content-Type: application/x-www-form-urlencoded
>
} [28 bytes data]
* Mark bundle as not supporting multiuse
< HTTP/1.1 400 Bad Request (1)
< Content-Length: 157
< Content-Type: text/html
<
{ [157 bytes data]
* Connection #0 to host raijin.example.com left intact
{
  "raijin-exception": {
    "parser-location": "http:1:1: ",
    "tag_reason": "syntax error at or near \"selert\"", (2)
    "where": "scan.cc:9246",
    "error_code": "16801924"
  }
}
1 HTTP 400 status code
2 tag_reason indicates that SELECT was misspelled as selert.
Example 8. Data ingestion with malformed JSON objects

The response indicates the number of records successfully ingested. In case of ingestion errors, the API will respond with HTTP 200 and the number of successfully ingested records as well as provide reasons for the ingestion errors.

 $ curl -sv raijin.example.com:2500/logs/demo -d '{"field1":-3.2,"field2":false}
{"field1":5.671,"field2":true}
{"hostname":"g01c335n2027","os":"Windows",active:1} (1)
{"hostname":"g01c335n2028","os":"Linux","active":0} (2)
'
*   Trying 192.168.1.60:2500...
* Connected to raijin.example.com (192.168.1.60) port 2500 (#0)
> POST /logs/demo HTTP/1.1
> Host: localhost:2500
> User-Agent: curl/7.81.0
> Accept: */*
> Content-Length: 166
> Content-Type: application/x-www-form-urlencoded
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK (3)
< Transfer-Encoding: chunked
< Content-Type: text/json
<
{"copy":3,"failed":"1","warnings":"0","reasons":"[{\"line\": 3, \"error\": \"Invalid JSON (Missing a name for object member.). File offset: 104\", \"record\": \"{\"hostname\":\"g01c335n2027\",\"os\":\"Windows\",active:1}\"}]","database":"logs","table":"demo"} (4)
* Connection #0 to host localhost left intact
1 This object violates JSON syntax by not enclosing the active key in double quotes (" ") and was not ingested.
2 This object has valid JSON syntax and was ingested.
3 HTTP 200 OK
4 This shows that 3 of the 4 records were ingested and the one that violates the JSON syntax failed.

JSON part of the answer (pretty printed)

{
  "copy":3,
  "failed":"1",
  "warnings":"0",
  "reasons":"[
    {\"line\": 3, \"error\": \"Invalid JSON (Missing a name for object member.). File offset: 104\", \"record\": \"{\"hostname\":\"g01c335n2027\",\"os\":\"Windows\",active:1}\"}
   ]",
  "database":"logs",
  "table":"demo"
}

Raijin REST API

The Raijin REST API provides endpoints for database management and health monitoring. It comes with a Swagger UI that you can use to explore and interact with the API. Access the Swagger UI by opening http://raijin.example.com:2500/api/v1.1/swaggerui from your browser.

The REST management API includes the following features:

  • Retrieve a listing of available API versions

  • Manage databases

  • Manage tables

  • Manage table partitions

  • Check the Raijin server health status

Example 9. Retrieve a list of databases
cURL request
curl -X 'GET' 'http://raijin.example.com:2500/api/v1.1/schema/databases' -H 'accept: text/json'
Request URL
http://raijin.example.com:2500/api/v1.1/schema/databases
Response format
{
  "database": "string",
  "size": "integer",
  "record_count": "integer"
}
Example response
{"database":"testdb","record_count":22,"size":3000}