HTTP routing table

PriorityDomainPathDescription
1 (highest)any/native*Native endpoints
2root/common*Common endpoints
3root*Root endpoints
4service/common*Common endpoints. Registered services only.
5 (lowest)service*Service-provided endpoints. Registered services only.

The above table describes how psinode normally routes HTTP requests. Only the highest-priority rule is fixed. The http-server service, which handles the remaining routing rules, is customizable, both by distinct networks and by individual infrastructure providers.

CORS and authorization

psinode always accepts CORS requests, since services would break without it. psinode does not currently handle any HTTP authentication or authorization.

Native endpoints

psinode's native code handles any target which begins with /native, regardless of domain. Targets which begin with /native but aren't recognized produce a 404.

The primary endpoint needed by front-end developers is the /native/push_transaction endpoint. The rest of the native endpoints are primarily useful for node administration and can therefore be found documented in the administration docs.

Push transaction

POST /native/push_transaction pushes a transaction. The user must pack the transaction using fracpack and pass in the binary as the request body. See Pack transaction for an RPC request which packs transactions.

➕ TODO: describe how to pack without using RPC; currently waiting for the transaction format to stabilize, for schema support, and for WASM ABI support.

If the transaction succeeds, or if the transaction fails but a trace is available, then psinode returns a 200 reply with a JSON body (below). If the transaction fails and a trace is not available, then it returns a 500 error with an appropriate message.

{
    "actionTraces": [...],  // Detailed execution information for debugging.
    "error": "..."          // Error message. Field will be empty or missing on success.
    // TODO: events?
}

If a transaction succeeds, the transaction may or may not make it into a block. If it makes it into a block, it may get forked back out.

➕ TODO: add lifetime tracking and reporting to psinode.

Future psinode versions may trim the action traces when not in a developer mode.

Common endpoints

The common-api service endpoints which start with the /common* path across all domains. It handles RPC requests and serves files.

MethodURLDescription
GET/common/tapos/headReturns TaPoS for the current head block
GET/common/thisserviceReturns a JSON string containing the service associated with the domain. If it's the root domain, returns "common-api"
GET/common/rootdomainReturns a JSON string containing the root domain, e.g. "psibase.127.0.0.1.sslip.io"
POST/common/pack/TransactionPacks a transaction
POST/common/pack/SignedTransactionPacks a signed transaction
GET/common/<other>Common files

Tapos

GET /common/tapos/head returns the TaPoS information for the current head block. To learn more about TaPoS and its purpose, see the the specification document.

The TaPoS information returned from this endpoint has these fields:

{
  "refBlockIndex": ...,   // Identifies block
  "refBlockSuffix": ...   // Identifies block
}

TaPoS must be attached to every transaction submitted to a psibase network. In addition to the refBlockIndex and refBlockSuffix, TaPoS information in a transaction requires an additional expiration field identifying a time after which the transaction is considered expired and can no longer be applied.

Pack transaction

POST /common/pack/Transaction and POST /common/pack/SignedTransaction use fracpack to convert unsigned and signed transactions to binary. They accept JSON as input and return the binary data.

Transaction has these fields:

{
  "tapos": {                // See [tapos](#tapos)
    "refBlockIndex": ...,   // Identifies block
    "refBlockSuffix": ...,  // Identifies block
    "expiration": "..."     // When transaction expires (UTC)
                            // Example value: "2022-05-31T21:32:23Z"
                            // Use `new Date(...)` to generate the correct format.
  },
  "actions": [],            // See Action
  "claims": []              // See Claim
}

SignedTransaction has these fields:

{
  "transaction": {},    // This may be the Transaction object (above),
                        // or it may be a hex string containing the packed
                        // transaction.
  "proofs": []          // See Proof
}

Action has these fields. To pack the action arguments, see pack_action in the service-provided endpoints.

{
  "sender": "...",      // The account name authorizing the action
  "service": "...",     // The service name to receive the action
  "method": "...",      // The method name of the action
  "rawData": "..."      // Hex string containing packed action arguments
}

Claim has these fields. See Signing (js) to fill claims and proofs.

{
  "service": "...",     // The service which verifies the proof meets
                        // the claim, e.g. "verifyk1"
  "rawData": "..."      // Hex string containing the claim data.
                        // e.g. `verifyk1` expects a public key
                        // in fracpack format.
}

Proof is a hex string containing data which proves the claim. e.g. verifyk1 expects a signature in fracpack format. See Signing (js) to fill claims and proofs.

Pack signed transaction

➕ TODO

Common files

common-api serves files stored in its tables. Chain operators may add files using the storeSys action (psibase upload). Booting the network with either the psibase CLI tool or with the x-admin app will automatically install this default set of files:

PathDescription
/common/SimpleUI.mjsDefault UI for services under development (Learn more)
/common/common-lib.jsSimple RPC wrappers (js)
Conversions (js)
Transactions (js)
Signing (js)
Key Conversions (js)
/common/useGraphQLQuery.mjsReact GraphQL hooks (js)

Root endpoints

The root document at / is the homepage of the network.

Service-provided endpoints

When you define a custom RPC handler, you have the ability to implement custom endpoints that your service can handle.

However, there are several reference libraries that have been developed to simplify serving some common and helpful service-specific endpoints. To learn how to use these libraries to enable these endpoints for your service, please reference either the C++ Web Services or Rust Web Services documentation depending on whatever is relevant to you.

The endpoints that can currently be enabled are:

Action templates

A request to GET /action_templates returns a JSON object containing a field for each action in Service. The field names match the action names. The field values are objects with the action arguments, each containing sample data.

Pack action

POST /pack_action/x is an endpoint that can help you pack calls to actions in a service. x is the name of the service action defined on this service, and the body of the request should be a JSON object containing all of the arguments to that action. To get a sample JSON object for an action and its arguments, you can use the action_templates endpoint.

This endpoint will parse the JSON body, packs the action and its arguments using fracpack, and then return the result as an application/octet-stream. This is helpful for when you're manually packing a transaction.

Simple UI

If this endpoint is enabled and called, then it will return a very small HTML body:

<html>
<div id="root" class="ui container"></div>
<script src="/common/SimpleUI.mjs" type="module"></script>
</html>

This simply calls the SimpleUI.mjs endpoint to present a simple user-interface that can be helpful during service development.