HTTP API

Overview

Cesium+ Pod offer RESTfull HTTP access:

  • ES CORE API: BlockChain indexation and statistics;
  • ES USER API: User data indexation, such as: profiles, private messages, encrypted settings;
  • ES SUBSCRIPTION API: User service subscription, such as: email notification service;

Data is made accessible through an HTTP API :

    http[s]://node[:port]/...
    |-- <currency>/
    |   |-- block
    |   |-- blockstat
    |   |-- peer
    |   |-- movement
    |   `-- pending
    |-- document/
    |   `-- stats
    |-- message/
    |   |-- inbox
    |   `-- outbox
    |-- invitation/
    |   `-- certification
    `-- subscription/
        `-- record

Document format

All stored documents use a JSON format.

Data document

Every document have the following mandatory fields:

  • version : The document’s version.
  • issuer : The document’s emitter
  • hash: the document’s hash
  • signature: the signature emitted by the issuer. Since version: 2, only the hash is signed.

Deletion

Document deletion use a document with this mandatory fields:

  • index : The document’s index
  • type : The document’s type
  • issuer: The deletion issuer. Should correspond to the document’s issuer, or the recipient in some special case (inbox message or invitation)
  • time: the current time
  • hash
  • signature

For instance, a deletion on message/inbox should send this document:

{
  "version" : 2,
  "index" : "message",
  "type" : "inbox",
  "id" : "AV9VOeOuTvXJwYisNfU6",
  "issuer" : "F13aXKWQPGCjSQAxxTyJYyRyPm5SqzFSsYYWSDEQGi2A",
  "time" : 1509806623,
  "hash" : "61EBBFBCA630E8B715C360DDE1CD6CABD92B9267CA4B724A2F1F36F0FF7E3455",
  "signature" : "FOkYCX1b05LTAbtz72F/LMWZb8F8zhQKEqcvbuiQy1N6AXtCUC5Xmjcn+NeO9sCLdcmA0HxsJx42GnWZOmKCDA=="
}

ES CORE API

node/*

node/summary

  • Get software version of the pod (using the format defined by Duniter BMA API);

    {
      "duniter" : {
        "software" : "cesium-plus-pod",
        "version" : "1.6.1",
        "status" : 200
      }
    }
    

node/stats

  • Get statistics on the pod:
  • Number of listeners open by WebSocket sessions;
  • Status of the embedded ES cluster ;
  • etc.

    { 
       "stats" : {
            "listeners" : [ {
              "source" : "subscription/execution,record",
              "count" : 1
            }, {
              "source" : "user/event",
              "count" : 1
            }, {
              "source" : "group/comment",
              "count" : 1
            },{
              "source" : "page/comment",
              "count" : 1
            }, {
              "source" : "*/block",
              "count" : 2
            }, {
              "source" : "g1/block/current",
              "count" : 1
            } ],
            "cluster" : {
              "timestamp" : 1583310606941,
              "cluster_name" : "g1-es-data",
              "status" : "yellow",
              "indices" : {
                 "count" : 12             
             }
           }
        }
    }
    

node/moderators

  • Get pubkeys of node moderators. Moderators can delete document (profiles, etc.) on pod;

    {
      "moderators": [
        "38MEAZN68Pz1DTvT3tqgxx4yQP6snJCQhPqEFxbDk4aE",
        "47JpfrGkoHJWtumeu7f67fbAxkvaHYVQBNo5GszNs61Z",
        "HmH5beJqKGMeotcQUrSW7Wo5tKvAksHmfYXfiSQ9EbWz"
      ]
    }
    
  • currency/*

    currency/block

    • Get the current block: <currency>/block/current
    • Get a block by number: <currency>/block/<number>
    • Search on blocks (using the ElasticSearch search API): <currency>/block/_search (POST or GET)

    <currency>/blockstat

    • Search on blocks, with count of each parts of a block: certCount, memberCount, txCount, txAmount, etc. (using the ElasticSearch search API): <currency>/blockstat/_search (POST or GET)

    json { "took" : 3, "timed_out" : false, "_shards" : { "total" : 3, "successful" : 3, "failed" : 0 }, "hits" : { "total" : 302494, "max_score" : 1.0, "hits" : [ { "_index" : "g1", "_type" : "blockstat", "_id" : "29003", "_score" : 1.0, "_source" : { "version" : 10, "currency" : "g1", "number" : 29003, "issuer" : "H1yTj77m946f52u64FvR36o9SmD38Ye2j1H4XCvwBFXK", "hash" : "0000024FD141E2DA5E3BCAC15CD558EF47BD9CB38DE022F2E0E8727AA885FCD4", "medianTime" : 1498016342, "membersCount" : 161, "monetaryMass" : 10533000, "unitbase" : 0, "dividend" : null, "txCount" : 1, "txAmount" : 2500, "txChangeCount" : 0, "certCount" : 0 } } } }

    <currency>/peer

    • Search on peers by endpoint and API, with a status (UP, DOWN) and other stats on blockchain (main consensus, …)

    (using the ElasticSearch search API): <currency>/peer/_search (POST or GET)

    ```json
    {
      "took" : 7,
      "timed_out" : false,
      "_shards" : {
        "total" : 3,
        "successful" : 3,
        "failed" : 0
      },
      "hits" : {
        "total" : 691,
        "max_score" : 1.0,
        "hits" : [ {
          "_index" : "g1",
          "_type" : "peer",
          "_id" : "54F93B092CAA3A4B287F39517C7B446A2D010BE4DD0E2FDBC76E0920B3714532",
          "_score" : 1.0,
          "_source" : {
            "api" : "BASIC_MERKLED_API",
            "dns" : null,
            "ipv4" : "91.160.74.131",
            "ipv6" : "2a01:e0a:12:a0c0:4951:28fb:745a:9ec9",
            "epId" : null,
            "pubkey" : "8dyDUH4KCMgpHkzAS9uu4NWPSf2xBmrp6D6S7d37A8M7",
            "hash" : "54F93B092CAA3A4B287F39517C7B446A2D010BE4DD0E2FDBC76E0920B3714532",
            "currency" : "g1",
            "stats" : {
              "version" : "1.5.9",
              "status" : "DOWN",
              "blockNumber" : 76834,
              "blockHash" : "000005D2162A8ECDC3A1268FC76D1F42AC3DEAE0479640D56D877796EB6F4968",
              "error" : null,
              "medianTime" : 1512998820,
              "hardshipLevel" : null,
              "consensusPct" : 77.77777777777777,
              "uid" : null,
              "lastUpTime" : 1513002789,
              "mainConsensus" : true,
              "forkConsensus" : false,
              "firstDownTime" : 1564882432
            },
            "port" : 10901,
            "useSsl" : false
          }
        }
     }
    

    } ```

    <currency>/movement

    • Allow to search on all blockchain transactions, but split by issuer.

    (using the ElasticSearch search API): <currency>/movement/_search (POST or GET):

    ```json
    {
     "took" : 7,
     "timed_out" : false,
     "_shards" : {
       "total" : 3,
       "successful" : 3,
       "failed" : 0
     },
     "hits" : {
       "total" : 67237,
       "max_score" : 1.0,
       "hits" : [ {
         "_index" : "g1",
         "_type" : "movement",
         "_id" : "AWAsh08ZeZsmCDV2GYit",
         "_score" : 1.0,
         "_source" : {
           "currency" : "g1",
           "medianTime" : 1498016342,
           "version" : 10,
           "issuer" : "TENGx7WtzFsTXwnbrPEvb6odX2WnqYcnnrjiiLvp1mS",
           "recipient" : "D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx",
           "amount" : 320,
           "unitbase" : 0,
           "comment" : "REMU:28501:29000",
           "reference" : {
             "index" : "g1",
             "type" : "block",
             "id" : "29003",
             "anchor" : null,
             "hash" : "0000024FD141E2DA5E3BCAC15CD558EF47BD9CB38DE022F2E0E8727AA885FCD4"
           },
           "ud" : false
         }
       }
       }
    ```
    

    <currency>/pending

    • All pending membership, collected from Duniter peers (selected randomly, each hour);

    • Allow to search on pending memberships (including old memberships), using <currency>/pending/_search (using ES search API);

    • Output as Duniter BMA format, using <currency>/pending:

      {
        "memberships" : [ {
          "pubkey" : "C59xaJfBXLpn9YhKet64KS3geTV9UQjvkLqpcTDy6dcK",
          "uid" : "JacquesDupond",
          "version" : "10",
          "currency" : "g1",
          "membership" : "IN",
          "blockNumber" : 302423,
          "blockHash" : "0000038FD71F131B76FF76F3E1D0CBA08901DD350551867CE5611DDAA1C1E057",
          "written" : null
        }, {
          "pubkey" : "GhicsNYYPrMvp1inmgxKUjww1s9PLnuzSV8CGtHrjUbq",
          "uid" : "MikeHorn",
          "version" : "10",
          "currency" : "g1",
          "membership" : "IN",
          "blockNumber" : 302376,
          "blockHash" : "000000F466B3BE9E93B1C19FF7A6A5556D9CD750D84458B660FEA1B81BA406B2",
          "written" : null
       }]
         }
      

    ES USER API

    user/*

    user/event

    • Get events on an account, by pubkey: user/event/_search?q=issuer:<pubkey> (GET)
    • Search on events: user/event/_search (POST or GET)

    user/profile

    • Get an profile, by public key: user/profile/<pubkey>
    • Add a new profile: user/profile (POST)
    • Update an existing profile: user/profile/_update (POST)
    • Delete an existing invitation: invitation/certification/_delete (POST)
    • Search on profiles: user/profile/_search (POST or GET)

    A profile document is a JSON document. Mandatory fields are:

    • title: user name (Lastanem, firstname…)
    • time: submission time, in seconds
    • issuer: user public key
    • hash: hash of the JSON document (without fields hash and signature)
    • signature: signature of the JSON document (without fields hash and signature)

    Example with only mandatory fields:

    {
        "version" : 2, 
        "title" : "Pecquot Ludovic",
        "description" : "Développeur Java et techno client-serveur\nParticipation aux #RML7, #EIS et #Sou",
        "time" : 1488359903,
        "issuer" : "2v6tXNxGC1BWaJtUFyPJ1wJ8rbz9v1ZVU1E1LEV2v4ss",
        "hash" : "F66D43ECD4D38785F424ADB68B3EA13DD56DABDE275BBE780E81E8D4E1D0C5FA",
        "signature" : "3CWxdLtyY8dky97RZBFLfP6axnfW8KUmhlkiaXC7BN98yg6xE9CkijRBGmuyrx3llPx5HeoGLG99DyvVIKZuCg=="
    }
    

    Some additional fields are description, socials, tags and avatar :

    {
        "version" : 2, 
        "title" : "My profile name",
        "description" : "#developer",
        "city" : "Rennes",
        "socials" : [ {
          "type" : "diaspora",
          "url" : "https://diaspora-fr.org/people/f9d13420f9ssqzq97aa01beea1f31e2"
        } ],
        "time" : 1487422234,
        "tags" : [ "developer" ],
        "issuer" : "2ny7YAdmzReQxAayyJZsyVYwYhVyax2thKcGknmQy5nQ",
        "avatar" : {
          "_content_type" : "image/png",
          "_content" : "iVBORw0KGgoAAAANSUhEUgAAAGQAAABkC(...)" // base 64 encoding
        }
        "hash" : "85F527077D060E03ECAC6D1AE38A74CCC900ACAF5D52F194BA34F5A5E8A55139",
        "signature" : "WeP7JEwttAoSkHcuiFwo6N4SM0uVakTYBQ09H1+K8/nPFyxO3ak1U9EQ6qaQFoAx9IdDp5qO2EX662wP/pcEAg==",
    }
    

    user/settings

    • Get an settings, by wallet pubkey: user/settings/<pubkey>
    • Add a new settings: user/settings (POST)
    • Delete an existing settings: user/settings/_delete (POST)
    • Search on settings: user/settings/_search (POST or GET)

    Some additional fields are content (the settings content, but encrypted) and nonce (required for an optimal encryption security level) :

    {
        "hash" : "58ECD135719628AA6DCE6DEFE1C2B328B04047B836BC478D0CF9E6F5A515896EC",
        "signature" : "3zP/mOgwnTj6EAfhb9vNfSUoPLZLqMwTP9QDk4wShTXlWnFPmPl2To3VTAoS3aHbLQAKDAWZa6EeVfsYCDVoDg==",
        "issuer" : "EtmXYFdh6WjgKyX3D6s2fXphCDv7jRPRnqnkKFTdMwNr",
        "nonce" : "Lfv5wXbLKF3RY9qbQVgv914ZKbsVi1sAm",
        "time" : 1516311640,
        "content" : "4bW4cL075bLWuTrHRuo69P0glmZJiVKF/AOtRt1e3trcm+Es/E77cYdAL00TCQw8N1kVU6fznCmZyVxtD8gfxpZwcoipWjWeTZTu21SxtPDxTxEvAV4gxbmOk/Li9oMy04WOmpkbsKawmdYW2oaKzz3psJXn4C4/jFQZIL/X863R9sQDGWPHm8MRvCaP7xQT+MMSpb8/1lIgf5443PKBixQbcY4fcqDRK3365xG2jDZEJ/uVZ/bRPJyjclKgBEd8xariJUV+zdh31f/qHhnQlcg/kLmdQ4sja2L/BWE5kTFlajRqOJDGrtuRafWTFamoUKZDE8C9YeivvFR7oGwY0zPE0uFnuZCGAvm3xC13ekpsqDv9YtBmZhou7AZAtw9JV81QuHoorWrka7C3LW12YuOSBKxkZNCi0tPHmF2ArI5WJl7W",
        "version" : 2
    }
    

    message/*

    message/inbox

    Some additional fields are recipient (the message recipient), title (the encrypted message’s title), content (the encrypted message’s body) and nonce (required for an optimal encryption security level) :

    {
        "issuer" : "DMwEdBiWuCGkPvtfvGs7fAoyaqbiA3ZXeX5grcNsg5x8",
        "recipient" : "FbvRnCM8gQdDig614qR1y1QY7x7sUN2RzXr3a9D9Rzw4",
        "title" : "jBhFV2kDyUvDxmYtodsO1D9ZpbX+j2vyOjVuMkgWa4vTyvM6VCqZWhutwYpMmXr1vdA=",
        "content" : "sX5/XOwcZe2RUIM2jd7Wlz9NoLTvgxPbNXZtNU8Qa4vT2qApB2rHFloNFdk+mHHo+NOfwk6RZjU3gnmUN0yi3eyUIOr2FYAoltdhx6C4Zmd9JQy5jVMzKg1HfD6K7daYbtN72ZTLfIxwlnAXG8z1+Rf9hZcmRNSIpFJ6lC2IUFcrFbulE8EsZuMPtrfuLlzNoW8HButmBlfbkMlALKcOcGYhVUCFhVAiL5FSgF+sHsUZe9CtubeGPlNT9m1y2joNZ8B4/rBn97XGV5odsaZZBO5gqcRQN4Y9SJSaNEbNFdaeWIFaO4NPT0r48eXKP4OGhYeQl4vCUQGG21U+GmcJiT4hiYJm41Xwp+qyjePlJ+om",
        "time" : 1504199349,
        "nonce" : "CWKAtBXqXu2ZuifeHnRBePw15e36gw3v9",
        "hash" : "965E9C4693C0B63C6F4CC6924A93354F0CE2B16F91BF0243FB5A355B4222D502",
        "signature" : "f0sPHFKukSbIahwkrYzPis9T5fP73QuH6UB76IdXN0JeWfg3Gh9A0oUc/YL78QmcKaM0FrD8JoK8BqYZNd1YAQ=="
    }
    

    content and title are encrypted for the issuer box public key. Only the message issuer will be able to decrypt this fields.

    message/outbox

    content and title are encrypted for the recipient box public key. Only the message recipient will be able to decrypt this fields.

    invitation/*

    invitation/certification

    • Get an invitation, by id: invitation/certification/<id>
    • Add a new invitation: invitation/certification (POST)
    • Delete an existing invitation: invitation/certification/_delete (POST)
    • Search on invitations: invitation/certification/_search (POST or GET)

    like/*

    like/record

    All documents stored in this index have a mandatory kind attribute, with one of the following values: - VIEW - LIKE - DISLIKE - STAR - ABUSE

    Only record with VIEW kind can be anonymous (no issuer and signature attributes).

    This index allow you to:

    • Count like records by kind, on any document (e.g. number of stars on a profile): /<doc_index>/<doc_type>/_likes, <doc_index>/<doc_type>/_abuses, etc.

    • Example: number of likes of a user profile: /user/profile/<pubkey>/_likes

    • Add a new like record: like/record (POST)

    • To delete a existing like record, use: history/delete (POST)

    ES SUBSCRIPTION API

    subscription/*

    subscription/record

    • Get an subscription, by id: subscription/record/<id>
    • Add a new subscription: subscription/record (POST)
    • Delete an existing subscription: subscription/record/_delete (POST)
    • Search on subscriptions: subscription/record/_search (POST or GET)