Node API

Moera Node API is a JSON-based REST API. See introduction to Node REST API in the Overview section.

Timestamp below is the number of seconds that passed since 01-01-1970 00:00:00 in UTC timezone.

If an error occurs when processing a API request, Result structure is returned instead of the regular response. The structure contains the error code and message, and also the HTTP status code is set accordingly. All error codes are case-insensitive.

An error may occur on different stages of request processing.

  • If the request URL is unknown, not-found error is returned.
  • If incorrect JSON is provided, invalid-syntax error is returned.
  • If value of one of the arguments does not correspond its type, invalid-argument-value error is returned.
  • If invalid authentication token or root secret is provided, authentication.invalid error is returned.
  • If authentication is required, but not provided, authentication.required error is returned.
  • If request body does not pass validation, a validation error is returned. Look into the chapter on the particular structure for the list of validation errors that correspond to the structure.
  • If an error occurs while executing the operation, one of the errors listed in the corresponding operation's chapter is returned.
  • If a configuration error or a software bug occurs, server.misconfiguration error is returned.
  • If request processing involves a naming server, but it is not available, naming.not-available error is returned.

Authentication scheme, if specified in the request description, may be one of the following:

  • none or not present - authentication is not required;
  • root secret - URL parameter secret must be provided with the value equal to the secret value set in the node configuration;
  • admin - admin token received after signing in must be passed in URL parameter token;
  • signature - user's access rights are figured out from the name and signature passed in the request body;
  • owner - only the owner of the posting, comment etc. may perform this request, use admin (for own posts on the home node only) or signature scheme for authentication.
  • configurable - access to the request is configurable, the client may refer to the corresponding access hint to clarify and use admin or signature scheme for authentication.

Standard permission groups are:

  • admin - administrator of the node;
  • owner - owner of the posting, comment etc.

Credentials object

Credentials used to authenticate the administrator of the node.

GET /credentials

Check whether the credentials are initialized already.

Response:
CredentialsCreated
Authentication (read more):
none

POST /credentials

Initialize credentials, if they are not set yet. Note that this operation can be executed without authentication, so this should be done as soon as possible after the node installation. Sign in is not allowed until the credentials are set.

Request body:
Credentials
Response:
Result
Authentication (read more):
none
Errors:
Code Description
credentials.already-created credentials are already created

PUT /credentials

Update credentials.

Request body:
Credentials
Response:
Result
Authentication (read more):
admin

Deleted Postings object

All deleted postings, that are not purged from the database yet.

GET /deleted-postings

Get the list of deleted postings, page by page. The node may decide to use smaller page size than the given limit. The postings are always sorted by the deletion timestamp, descending.

Parameters:
int page - page number, 0 by default
int limit - page size (maximum number of postings returned), the default is defined by the node
Response:
PostingInfo[]
Authentication (read more):
admin
Errors:
Code Description
page.invalid page parameter has an invalid value
limit.invalid limit parameter has an invalid value

GET /deleted-postings/{id}

Get an individual deleted posting.

Parameters:
UUID id - ID of the posting
Response:
PostingInfo
Authentication (read more):
none
Errors:
Code Description
posting.not-found there is no deleted posting with the given ID

POST /deleted-postings/{id}/restore

Restore a posting. A new revision is created with the same content as in the latest revision.

Parameters:
UUID id - ID of the posting
Response:
PostingInfo
Authentication (read more):
admin
Errors:
Code Description
posting.not-found there is no posting with the given ID

Deleted Posting Revisions object

All revisions of the deleted posting. This object supports the same requests as Posting Revisions object, but uses /deleted-postings prefix instead of /postings.

Domains object

One instance of Moera node software can serve several virtual nodes. These virtual nodes are called domains and distinguished by the hostname passed in the HTTP request. Each virtual node has node ID, it is used in the database to designate the data that belongs to a particular node. The hostname is mapped to the node ID when the request is processed, using the list of registered domains. If there is no domain with such a name, the special _default_ domain is used.

GET /domains

Get the list of registered domains.

Response:
DomainInfo[]
Authentication (read more):
root secret

GET /domains/{name}

Get information about the domain with the given hostname.

Parameters:
String name - domain name
Response:
DomainInfo
Authentication (read more):
root secret
Errors:
Code Description
domain.not-found there is no domain with the given hostname

POST /domains

Create a new domain with the given hostname. If nodeId is not passed, it is generated automatically.

Request body:
DomainInfo
Response:
DomainInfo
Authentication (read more):
root secret
Errors:
Code Description
domainInfo.name.blank the hostname is empty
domain.already-exists the domain with the given hostname already exists

PUT /domains/{name}

Update the domain with the given hostname. If the new hostname is not passed, the old hostname is preserved. (Note that you cannot pass a new name for the default hostname, because it cannot be renamed and _default_ is not a valid hostname. Skip this field if you want to update the default hostname.) If nodeId is not passed, it is generated automatically.

Parameters:
String name - domain hostname
Request body:
DomainInfo
Response:
DomainInfo
Authentication (read more):
root secret
Errors:
Code Description
domain.not-found there is no domain with the given hostname
domain.cannot-rename-default cannot change the name of the default domain

DELETE /domains/{name}

Delete the domain with the given hostname. This operation deletes the domain record only, the user's data related to the domain is preserved.

Parameters:
String name - domain name
Response:
Result
Authentication (read more):
root secret
Errors:
Code Description
domain.not-found there is no domain with the given hostname
domain.cannot-delete-default cannot delete the default domain

Postings object

All postings. Each posting may contain one or more revisions, a new revision is created every time the posting is updated. The latest revision is the current one, the previous ones are marked as deleted.

POST /postings

Create a new posting from the text given, sign it with the signing key and publish it on the timeline. The heading and the preview of the posting are created automatically, if needed.

Request body:
PostingText
Response:
PostingInfo
Authentication (read more):
configurable
Errors:
Code Description
posting.registered-name-not-set registered name is not set yet
posting.signing-key-not-set signing key is not set yet

PUT /postings/{id}

Update the posting, creating a new revision of it. The text is processed just like in the POST request.

Parameters:
UUID id - ID of the posting
Request body:
PostingText
Response:
PostingInfo
Authentication (read more):
configurable
Errors:
Code Description
posting.not-found there is no posting with the given ID
posting.registered-name-not-set registered name is not set yet
posting.signing-key-not-set signing key is not set yet

GET /postings/{id}

Get an individual posting.

Parameters:
UUID id - ID of the posting
String include - Comma-separated list of additional blocks of information that are needed. The values are:
  • source - source text of the posting.
Response:
PostingInfo
Authentication (read more):
none
Errors:
Code Description
posting.not-found there is no posting with the given ID

DELETE /postings/{id}

Delete the posting. The posting may not be purged from the database immediately, but preserved for some period of time to give a chance to restore it.

Parameters:
UUID id - ID of the posting
Response:
Result
Authentication (read more):
configurable
Errors:
Code Description
posting.not-found there is no posting with the given ID

GET /postings/features

Get information about supported features of postings.

Response:
PostingFeatures
Authentication (read more):
none

Posting Revisions object

All revisions of the posting.

GET /postings/{postingId}/revisions

Get all revisions of the posting.

Parameters:
UUID postingId - ID of the posting
Response:
PostingRevisionInfo[]
Authentication (read more):
configurable
Errors:
Code Description
posting.not-found there is no posting with the given ID

GET /postings/{postingId}/revisions/{id}

Get an individual revision of the posting.

Parameters:
UUID postingId - ID of the posting
UUID id - ID of the revision
Response:
PostingRevisionInfo
Authentication (read more):
configurable
Errors:
Code Description
posting.not-found there is no posting with the given ID
posting-revision.not-found there is no revision with the given ID

POST /postings/{postingId}/revisions/{id}/restore

Restore a revision of the posting. A new revision is created with the same content as in the given revision.

Parameters:
UUID postingId - ID of the posting
UUID id - ID of the revision
Response:
PostingRevisionInfo
Authentication (read more):
owner
Errors:
Code Description
posting.not-found there is no posting with the given ID
posting-revision.not-found there is no revision with the given ID
posting-revision.already-current the given revision is already the current one

Profile object

The profile - the detailed information about the node's owner, node's purpose etc.

GET /profile

Get the profile.

Response:
ProfileInfo
Authentication (read more):
none or admin

PUT /profile

Update the profile.

Request body:
Profile
Response:
ProfileInfo
Authentication (read more):
admin

Registered Name object

The registered name of the node. Read more about it in the Overview section. Operations with the registered name are performed asynchronously - need to poll the node periodically to get the current status of the operation. Only one operation with the registered name may be performed by the node at any moment.

GET /registered-name

Get the registered name of the node. Admin user receives also the current status of the latest operation with the registered name.

Response:
RegisteredNameInfo
Authentication (read more):
none or admin

POST /registered-name

Register a new name for the node. The corresponding signing key is generated automatically and stored at the node. The updating key is generated and returned in the encoded form and in the form of mnemonic (a sequence of English words) that need to be written down and stored securely to be able to perform further operations with the name.

Request body:
NameToRegister
Response:
RegisteredNameSecret
Authentication (read more):
admin
Errors:
Code Description
naming.operation-pending another operation with the registered name is pending currently

PUT /registered-name

Update the registered name of the node. May be used to assign an already-registered name to the node (the corresponding signing key is generated automatically and stored at the node), or to prolong the name. The secret or mnemonic of the updating key must be provided for this operation.

Request body:
RegisteredNameSecret
Response:
Result
Authentication (read more):
admin
Errors:
Code Description
naming.operation-pending another operation with the registered name is pending currently
registeredNameSecret.empty the registered name secret or mnemonic are not provided
registered-name.name-absent the registered name/generation is not provided and not known by the node
registered-name. various errors returned by naming server (see the list)

DELETE /registered-name

Delete all the information related to the registered name (including the signing key) from the node. The name record on the naming server is not touched.

Response:
Result
Authentication (read more):
admin
Errors:
Code Description
naming.operation-pending another operation with the registered name is pending currently

Timeline object

Timeline - all postings that user is permitted to read. The postings are sorted by moment, descending.

GET /timeline

Get general information about the timeline.

Response:
TimelineInfo[]
Authentication (read more):
none

GET /timeline/postings

Get a slice of the timeline, delimited by before or after moments (but not both) and the given limit. If neither before nor after are provided, the latest postings are returned. The node may decide to return less postings than the given limit. The postings are always sorted by moment, descending.

Parameters:
int before - filter postings posted at or before this moment
int after - filter postings posted strongly after this moment
int limit - maximum number of postings returned
Response:
TimelineSliceInfo
Authentication (read more):
none
Errors:
Code Description
timeline.before-after-exclusive before and after parameters are not allowed together
limit.invalid limit parameter has an invalid value

Tokens object

The authentication token. Read more about token-base authentication in the Overview section.

GET /tokens/{token}

Get information about the token.

Parameters:
String token - the token
Response:
TokenInfo
Authentication (read more):
none

POST /tokens

Sign in and create a token.

Request body:
Credentials
Response:
TokenCreated
Authentication (read more):
none
Errors:
Code Description
credentials.not-created credentials are not created yet
credentials.login-incorrect login or password is incorrect

Who Am I object

Brief information about the node.

GET /whoami

Get brief information about the node.

Response:
WhoAmI
Authentication (read more):
none


Structures

Choice

Type Name Description
String value
String title user-readable title for the value

Credentials

Type Name Description
String login
String password
Validation errors:
Code Description
credentials.login.blank the login is empty
credentials.password.blank the password is empty

CredentialsCreated

Type Name Description
boolean created true if the credentials are initialized already, false otherwise

DomainInfo

Type Name Description
String name domain's hostname or _default_ for the default domain
UUID nodeId domain's node ID
Validation errors:
Code Description
domainInfo.name.blank the domain name is empty
domainInfo.name.wrong-hostname the domain name is not a valid hostname
domainInfo.nodeId.wrong-uuid the node ID is not a valid UUID

NameToRegister

Type Name Description
String name
Validation errors:
Code Description
nameToRegister.name.blank the name is empty
nameToRegister.name.invalid the name is reserved, too long or contains invalid characters

PostingFeatures

Type Name Description
Choice[] sourceFormats List of source text formats the node understands. The well-known values are:
  • plain-text - plain text with newlines and paragraphs delimited by empty line;
  • html - HTML-formatted text, the node may allow only limited set of tags;
  • markdown - text in Markdown format.

PostingInfo

Type Name Description
UUID id
UUID revisionId ID of the current revision of the posting
int totalRevisions total number of revisions the posting has
String ownerName registered name of the posting's owner
int ownerGeneration registered name generation of the posting's owner
String bodyPreviewHtml preview of the posting's body (HTML), may be absent
String bodySrc the source text of the posting, may be absent if not requested
byte[] bodySrcHash hash of the source text of the posting
String bodySrcFormat format of the source text of the posting, the list of available formats is returned in PostingFeatures
String bodyHtml body of the posting (HTML)
String heading heading of the posting
timestamp createdAt posting creation timestamp - the real time when the posting was created
timestamp publishedAt posting publication timestamp - the time the posting is published under at the timeline
timestamp editedAt posting editing timestamp - the last time the posting was updated
timestamp deletedAt posting deletion timestamp - the time when the posting was deleted, may be absent
byte[] signature the posting's owner signature (the fingerprint see below)
int moment
String -> String[] operations list of the supported operations (see below) and the corresponding access hints
Operations (read more):
Name Description
edit edit the posting
delete delete the posting
revisions view the posting's revisions
Fingerprint (read more):
Type Value
String ownerName
int ownerGeneration
byte[] bodySrcHash
String bodySrcFormat
String bodyHtml
int createdAt (of the current revision)

PostingRevisionInfo

Type Name Description
UUID id
String bodyPreviewHtml preview of the revisions's body (HTML), may be absent
byte[] bodySrcHash hash of the source text of the revision
String bodySrcFormat format of the source text of the revision, the list of available formats is returned in PostingFeatures
String bodyHtml body of the revision (HTML)
String heading heading of the revision
timestamp createdAt revision creation timestamp - the real time when the revision was created
timestamp publishedAt revision publication timestamp - the time the revision is published under at the timeline
timestamp deletedAt revision deletion timestamp - the time when the revision was deleted, may be absent
byte[] signature the revision's owner signature (the fingerprint see in PostingInfo)
int moment

PostingText

Type Name Description
String bodySrc the source text of the posting
String bodySrcFormat format of the source text of the posting, plain-text by default; the list of available formats is returned in PostingFeatures
String bodyHtml body of the posting (HTML), may be absent
timestamp publishAt posting publication timestamp, the current timestamp by default
Validation errors:
Code Description
postingText.bodySrc.blank body text is empty
postingText.bodySrc.wrong-size body text is too long
postingText.bodySrcFormat.unknown unknown body text format
postingText.bodyHtml.wrong-size body HTML is too long

Profile

Type Name Description
String fullName node owner's full name
String gender node owners's gender
String email node owner's E-mail address
Validation errors:
Code Description
profile.fullName.wrong-size the full name is too long
profile.gender.wrong-size the gender string is too long
profile.email.wrong-email the E-mail is not a well-formed E-mail address

ProfileInfo

Type Name Description
String fullName node owner's full name
String gender node owners's gender
String email node owner's E-mail address
String -> String[] operations list of the supported operations (see below) and the corresponding access hints
Operations (read more):
Name Description
edit change the profile

RegisteredNameInfo

Type Name Description
String name
int generation
OperationStatus operationStatus status of the latest operation with the registered name
timestamp operationStatusUpdated the last time the operation status was updated
String operationErrorCode if the operation with the registered name was failed, the code of the failure
String operationErrorMessage if the operation with the registered name was failed, the human-readable description of the failure
String -> String[] operations list of the supported operations (see below) and the corresponding access hints
Operations (read more):
Name Description
manage any modification of the registered name, prolonging it etc.

RegisteredNameSecret

Type Name Description
String name
int generation
String[] mnemonic human-friendly mnemonic of the updating key
String secret base64-encoded secret of the updating key

Result

Type Name Description
String errorCode error code
String message human-readable error message

TimelineInfo

Type Name Description
String -> String[] operations list of the supported operations (see below) and the corresponding access hints
Operations (read more):
Name Description
add add postings to the timeline

TimelineSliceInfo

Type Name Description
int before the slice contains all postings before this moment, inclusive. May be the far future.
int after the slice contains all postings after this moment, exclusive. May be the far past.
PostingInfo[] postings the postings

TokenCreated

Type Name Description
String token the token
String[] permissions The list of permission groups assigned to the token.

TokenInfo

Type Name Description
String token the token
boolean valid true if the token is valid, false otherwise.
String[] permissions The list of permission groups assigned to the token. See also the list of standard permission groups.

WhoAmI

Type Name Description
String registeredName
int registeredNameGeneration


Enums

OperationStatus

This enum is used to designate the operation status both by the naming server and by the node.

Value Description
WAITING operation is waiting to be sent to the naming server
ADDED operation was accepted by the naming server
STARTED the naming server started to proceed the operation
SUCCEEDED operation completed successfully
FAILED operation failed
UNKNOWN operation status is unknown


HTTP status codes

Code Description
200 No error.
201 Object created successfully. The object location is provided in Location: header.
400 Validation of the request body failed.
401 Invalid authentication token or root secret.
403 Authentication required, but not provided.
404 Unrecognized request or object not found.
409 Operation failed.
500 The node configured incorrectly or a bug in the node software; naming service not available.