{
"command": "tx.submit",
"version": 1,
"externalId": "id1",
"preimage": [ ... ],
"signature": "BASE64SIG",
"ghost": { ... }
}| Field | Type | Description |
|---|---|---|
command | string | The operation identifier (e.g., "tx.submit", "element.create") |
version | integer | Protocol version used in the request (e.g., 1) |
externalId | string/null | Unique identifier for correlating responses; required in batch mode |
preimage | array | Signed parameters including metadata and public key |
signature | string (Base64) | Signature over the serialized preimage |
ghost | object/null | Optional, unsigned payload (e.g., secrets, OTPs); not persisted |
{
"type": "array",
"items": {
"type": "object",
"properties": {
"command": {
"type": "string",
"description": "The UBP command to execute."
},
"version": {
"type": "integer",
"description": "API version of the UBP protocol used in the message."
},
"externalId": {
"type": ["string","null"],
"description": "Optional external identifier for tracking or correlating the request. Required for batch input."
},
"preimage": {
"type": ["array","null"],
"items": {
"type": ["array","null"],
"items": {
"description": "Individual preimage element, representing command parameters or data to be registered or updated in the blockchain."
},
"description": "Preimage entry, which may be a list of values or null."
},
"description": "List of preimage data, containing the core payload for the UBP command."
},
"signature": {
"type": ["string","null"],
"description": "Cryptographic signature for verifying the authenticity and integrity of the message.",
"format": "Base64"
},
"ghost": {
"type": ["object","null"],
"properties": {},
"description": "Transactional data used only during request processing (e.g., passwords, TOTP codes, or other sensitive information). Not saved on the blockchain and not part of the main UBP protocol"
}
},
"description": "UBP Message (6-element tuple) representing a single blockchain operation.",
},
"description": "UBP Batch: an array of UBP messages for batch processing."
}preimage is an array containing command-specific parameters, always ending with:[
...,
{ ... },
"BASE64SPKI"
]| Position | Field | Type | Description |
|---|---|---|---|
| 0...N | custom params | any | Command-specific arguments |
| N+1 | metadata | object/null | Contextual info; values used for signature canonicalization |
| N+2 | publicKey | string (Base64) | Signer’s public key in SPKI DER Base64 format |
The positions of metadataandpublicKeyare always the last two in thepreimagearray. Only the values ofmetadata, sorted by key, are used in the signature preimage.
metadata is an object:| as a delimiter.[
"TYPE",
null,
123.45,
{ "y": "b", "x": "a", "z": "c" },
"BASE64SPKI"
]TYPE||123.45|a|b|c|BASE64SPKImetadata)123.45 → "123.45"metadata is used, it must be a flat JSON object with only string keys and string values.{ "a": "123", "x": "yz" }{ "a": 123, "x": "yz", "object": {} }| Field | Required | Notes |
|---|---|---|
| command | Yes | Must be a string |
| version | Yes | Must match the expected version |
| externalId | Yes* | Required only in batch mode |
| preimage | Yes | Must be a list with the defined layout |
| signature | Yes | Must be valid Base64 |
The UBP protocol version must always be explicitly declared in the message body ( version) and must not be inferred from the transport layer (e.g., URL path). This ensures transport-agnostic compatibility, batch version heterogeneity, and future-proof validation logic.
address.generate, the preimage must be [] (empty).metadata and publicKey.metadata must be null or an object.publicKey must decode to a valid value.object or nullmetadata != null, it must be a flat JSON object.object or null[
{
"command": "tx.submit",
"version": 1,
"externalId": "id1",
"preimage": [...],
"signature": "sig1",
"ghost": { "otp": "123456" }
},
{
"command": "tx.submit",
"version": 1,
"externalId": "id2",
"preimage": [...],
"signature": "sig2",
"ghost": { "otp": "654321" }
}
]externalId must be unique within the batchPOST /v1/ubp — Submit UBP messagesGET /.well-known/ubp — Discover protocol version{
"protocol": "UBP",
"versions": ["1"],
"current": "1",
"endpoints": ["https://api.norsh.org/v1/ubp"]
}{
"command": "element.create",
"version": 1,
"externalId": "id1",
"status": 200,
"timestamp": "2025-08-31T21:00:00Z",
"success": true,
"result": { ... },
"info": { ... }
}| Field | Type | Description |
|---|---|---|
command | string | The command executed (e.g., "element.create", "tx.submit") |
version | integer | Protocol version used in the request (typically 1) |
externalId | string | Identifier from the original message; helps the client track responses |
status | integer | HTTP status code representing the result of the operation |
timestamp | string | Response timestamp in ISO 8601 UTC format |
success | boolean | true if the command succeeded; false if there was an error |
result | object | Command-specific response on success, or error details on failure |
info | object | Additional operation metadata: ledger, transaction, block, processing time |
{
"command": "element.create",
"version": 1,
"externalId": "id1",
"status": 200,
"timestamp": "2025-08-31T21:00:00Z",
"success": true,
"result": {
"elementId": "NSH012345",
"status": "created"
},
"info": {
"ledger": "bigledger",
"transaction": "05036377...",
"block": "e0e8a311...",
"durationMs": 1575
}
}{
"command": "element.create",
"version": 1,
"externalId": "id1",
"status": 400,
"timestamp": "2025-08-31T21:00:00Z",
"success": false,
"result": {
"code": -1,
"message": "Error message"
},
"info": {
"ledger": null,
"transaction": null,
"block": null,
"durationMs": 32
}
}{
"type": "array",
"items": {
"type": "object",
"properties": {
"command": {
"type": "string",
"description": "The UBP command that was executed."
},
"version": {
"type": "integer",
"description": "API version of the UBP protocol used in the response."
},
"externalId": {
"type": ["string","null"],
"description": "External identifier for tracking or correlating the request. Required for batch input."
},
"status": {
"type": "integer",
"description": "HTTP status code representing the result of the operation."
},
"timestamp": {
"type": "string",
"description": "Timestamp when the response was generated, in ISO 8601 format."
},
"success": {
"type": "boolean",
"description": "Indicates whether the operation was successful."
},
"result": {
"type": "object",
"properties": {},
"description": "Result object containing the output or data returned by the command."
},
"info": {
"type": "object",
"properties": {
"ledger": {
"type": ["string","null"],
"description": "Ledger identifier where the transaction was recorded."
},
"transaction": {
"type": ["string","null"],
"description": "Transaction identifier for the blockchain operation."
},
"block": {
"type": ["string","null"],
"description": "Block identifier containing the transaction."
},
"durationMs": {
"type": "integer",
"description": "Processing duration in milliseconds."
}
},
"description": "Additional information about the blockchain operation, including ledger, transaction, block, and processing duration.",
"required": ["durationMs"]
}
},
"description": "UBP Response message representing the result of a single blockchain operation.",
"required": ["info","success","timestamp","status","version","command"]
},
"description": "UBP Batch Response: an array of UBP response messages for batch processing."
}status field in each response object reflects the HTTP status code of the operation result.200, all 403), the HTTP response itself will also use that same status code.status field.