REST API

REST is our primary API for interacting with the node from scripts, libraries, and system-to-system integration.

Here you can find the latest OpenAPI documentation along with usage examples.

Interactive Swagger UI is also available on HTTP port of all running nodes.

If you are considering to build applications on top of Kamu Node - also consider using GraphQL API.

For accessing individual components of the datasets (blocks, references, data slices) you can use ODF protocol.

Reading Data

To get dataset information like description, schema, etc. use /metadata endpoint:

https://node.demo.kamu.dev/kamu/com.cryptocompare.ohlcv.eth-usd/metadata?include=attachments,info,license,refs,schema,seed,vocab

To get sample data from any dataset use /tail endpoint:

https://node.demo.kamu.dev/kamu/com.cryptocompare.ohlcv.eth-usd/tail?limit=10

To execute arbitrary SQL that can access multiple datasets at once use /query endpoint:

https://node.demo.kamu.dev/query?query=select+1&skip=0&limit=10&include=input,schema

The /query endpoint also supports POST requests for finer control:

Example request body:

{
    "query": "select event_time, from_symbol, to_symbol, close from \"kamu/com.cryptocompare.ohlcv.eth-usd\"",
    "limit": 3,
    "queryDialect": "SqlDataFusion",
    "dataFormat": "JsonAoa",
    "schemaFormat": "ArrowJson"
}

Example response:

{
    "output": {
        "data": [
            ["2024-09-02T21:50:00Z", "eth", "usd", 2537.07],
            ["2024-09-02T21:51:00Z", "eth", "usd", 2541.37],
            ["2024-09-02T21:52:00Z", "eth", "usd", 2542.66]
        ],
        "dataFormat": "JsonAoa",
        "schema": {"fields": ["..."]},
        "schemaFormat": "ArrowJson"
    }
}

Cryptographic Proofs

Cryptographic proofs can be also requested to hold the node forever accountable for the provided result.

Example request body:

{
    "query": "select event_time, from_symbol, to_symbol, close from \"kamu/com.cryptocompare.ohlcv.eth-usd\"",
    "limit": 3,
    "queryDialect": "SqlDataFusion",
    "dataFormat": "JsonAoA",
    "schemaFormat": "ArrowJson",
    "include": ["proof"]
}

Example response:

{
    "input": {
        "query": "select event_time, from_symbol, to_symbol, close from \"kamu/com.cryptocompare.ohlcv.eth-usd\"",
        "queryDialect": "SqlDataFusion",
        "dataFormat": "JsonAoa",
        "include": ["Input", "Proof", "Schema"],
        "schemaFormat": "ArrowJson",
        "datasets": [{
            "id": "did:odf:fed0119d20360650afd3d412c6b11529778b784c697559c0107d37ee5da61465726c4",
            "alias": "kamu/com.cryptocompare.ohlcv.eth-usd",
            "blockHash": "f1620708557a44c88d23c83f2b915abc10a41cc38d2a278e851e5dc6bb02b7e1f9a1a"
        }],
        "skip": 0,
        "limit": 3
    },
    "output": {
        "data": [
            ["2024-09-02T21:50:00Z", "eth", "usd", 2537.07],
            ["2024-09-02T21:51:00Z", "eth", "usd", 2541.37],
            ["2024-09-02T21:52:00Z", "eth", "usd", 2542.66]
        ],
        "dataFormat": "JsonAoa",
        "schema": {"fields": ["..."]},
        "schemaFormat": "ArrowJson"
    },
    "subQueries": [],
    "commitment": {
        "inputHash": "f1620e23f7d8cdde7504eadb86f3cdf34b3b1a7d71f10fe5b54b528dd803387422efc",
        "outputHash": "f1620e91f4d3fa26bc4ca0c49d681c8b630550239b64d3cbcfd7c6c2d6ff45998b088",
        "subQueriesHash": "f1620ca4510738395af1429224dd785675309c344b2b549632e20275c69b15ed1d210"
    },
    "proof": {
        "type": "Ed25519Signature2020",
        "verificationMethod": "did:key:z6MkkhJQPHpA41mTPLFgBeygnjeeADUSwuGDoF9pbGQsfwZp",
        "proofValue": "uJfY3_g03WbmqlQG8TL-WUxKYU8ZoJaP14MzOzbnJedNiu7jpoKnCTNnDI3TYuaXv89vKlirlGs-5AN06mBseCg"
    }
}

A client that gets a proof in response should perform a few basic steps to validate the proof integrity. For example making sure that the DID in proof.verificationMethod actually corresponds to the node you’re querying data from and that the signature in proof.proofValue is actually valid. Only after this you can use this proof to hold the node accountable for the result.

A proof can be stored long-term and then disputed at a later point using your own node or a 3rd party node you can trust via the /verify endpoint.

Example request:

{
    "input": {
        "query": "select event_time, from_symbol, to_symbol, close from \"kamu/com.cryptocompare.ohlcv.eth-usd\"",
        "queryDialect": "SqlDataFusion",
        "dataFormat": "JsonAoa",
        "include": ["Input", "Proof", "Schema"],
        "schemaFormat": "ArrowJson",
        "datasets": [{
            "id": "did:odf:fed0119d20360650afd3d412c6b11529778b784c697559c0107d37ee5da61465726c4",
            "alias": "kamu/com.cryptocompare.ohlcv.eth-usd",
            "blockHash": "f1620708557a44c88d23c83f2b915abc10a41cc38d2a278e851e5dc6bb02b7e1f9a1a"
        }],
        "skip": 0,
        "limit": 3
    },
    "subQueries": [],
    "commitment": {
        "inputHash": "f1620e23f7d8cdde7504eadb86f3cdf34b3b1a7d71f10fe5b54b528dd803387422efc",
        "outputHash": "f1620e91f4d3fa26bc4ca0c49d681c8b630550239b64d3cbcfd7c6c2d6ff45998b088",
        "subQueriesHash": "f1620ca4510738395af1429224dd785675309c344b2b549632e20275c69b15ed1d210"
    },
    "proof": {
        "type": "Ed25519Signature2020",
        "verificationMethod": "did:key:z6MkkhJQPHpA41mTPLFgBeygnjeeADUSwuGDoF9pbGQsfwZp",
        "proofValue": "uJfY3_g03WbmqlQG8TL-WUxKYU8ZoJaP14MzOzbnJedNiu7jpoKnCTNnDI3TYuaXv89vKlirlGs-5AN06mBseCg"
    }
}

Example response:

{
    "ok": false,
    "error": {
        "kind": "VerificationFailed::OutputMismatch",
        "actual_hash": "f162..c12a",
        "expected_hash": "f162..2a2d",
        "message": "Query was reproduced but resulted in output hash different from expected.
                    This means that the output was either falsified, or the query
                    reproducibility was not guaranteed by the system.",
    }
}

See commitments documentation for details.

Ingesting Data

Example using curl:

echo '[{"foo": "bar"}]' | curl -v -X POST \
    'https://api.demo.kamu.dev/account/my-dataset/ingest' \
    -H 'Authorization: Bearer <access-token>' \
    -H 'Content-Type: application/json'

Example using xh:

echo '[{"foo": "bar"}]' | xh -v POST \
    'https://node.demo.kamu.dev/account/my-dataset/ingest' \
    'Authorization: Bearer <access-token>' \
    'Content-Type: application/json'

Content types correspond directly to supported input formats:

Media TypeExample
text/csv
2020-01-01T00:01:00Z,-123.12,49.28
2020-01-01T00:02:00Z,-123.13,49.29
application/json
[{
“event_time”: “2020-01-01T00:01:00Z”,
“long”: -123.12,
“lat”: 49.28
}, {
“event_time”: “2020-01-01T00:02:00Z”,
“long”: -123.13,
“lat”: 49.29
}]
application/x-ndjson
{“event_time”: “2020-01-01”, “long”: -123.12, “lat”: 49.28}
{“event_time”: “2020-01-01”, “long”: -123.13, “lat”: 49.29}
application/geo+json
{
“type”: “FeatureCollection”,
“features”: [
{“type”: “Feature”, “geometry”: {…}, “properties”: {…}},
{“type”: “Feature”, “geometry”: {…}, “properties”: {…}}
]
}
application/x-ndgeojson
{“type”: “Feature”, “geometry”: {…}, “properties”: {…}}
{“type”: “Feature”, “geometry”: {…}, “properties”: {…}}
application/vnd.apache.parquet
<binary data>
application/vnd.esri.shapefile
<binary data>