Reference for the decentralised.art HTTP APIs: the chain API for operations, simulation, publication and execution, and the services API for sign-in, profiles and Worlds.
Overview
decentralised.art has two HTTP APIs. Both speak JSON over HTTPS.
API
Base URL
What it does
Chain API
https://api.decentralised.art/chain
Connectors, transformations and conditions: reading them, creating drafts, simulating,
publishing on chain and executing. Also accounts, formats and the event feed.
Services API
https://api.decentralised.art/services
Sign-in, user profiles, follows, and publishing and serving Worlds.
Reading needs no account. The SDK wraps the chain API for
JavaScript and Python, and the MCP server offers it to AI
agents. For the ideas behind it, see About.
Try it
# Read a connectorcurl https://api.decentralised.art/chain/connector/pitch
# Run it on chain for four steps (no login, no gas)curl -X POST https://api.decentralised.art/chain/execute \
-H "Content-Type: application/json" \
-d '{"connector_name":"pitch","particles_count":4}'
Authentication
Each API has its own sign-in, and both prove that you control an Ethereum address by signing a
message. Send the resulting token as Authorization: Bearer <token>.
Chain API
Services API
Needed for
Creating drafts and publishing
Your profile, follows, and uploading Worlds
Steps
GET /nonce/{address}, sign Login nonce: <nonce>, then POST /auth
POST /auth/siwe/challenge, sign the message, then POST /auth/siwe/verify
Signature
EIP-191 personal_sign
Sign-In with Ethereum (EIP-4361), signed with EIP-191
Token
JWT access token
Session token
Valid for
5 minutes
24 hours, or until sign-out
The two tokens are not interchangeable. Reading, simulating and executing need neither.
Conventions
Names and addresses
Operation names start with a letter or underscore and contain letters, digits and
underscores, up to 128 characters. They are global and cannot be changed.
Addresses are 40 hexadecimal characters, with or without 0x. The chain API
returns owner addresses in lowercase without 0x; the services API returns
checksummed addresses with 0x.
A draft reports the address "0x0" until it is published.
Field names
The chain API and the user endpoints use snake_case (format_hash, display_name). World endpoints use camelCase (entryUrn, acceptedFormatHashes). Publication transactions use the Ethereum JSON-RPC
spelling with hex quantities (chainId, maxFeePerGas).
Pagination
Chain API lists take a required limit (1–256) and return a cursor. Pass cursor.next_after back as after (or, for the feed, cursor.next_before as before) while cursor.has_more is
true.
Services API lists take a zero-based page and a limit.
Errors
Errors use HTTP status codes. Chain API errors carry a JSON body with a message; publication errors can add status, tx_hash, missing and mismatched. Services API errors carry the status, and
World endpoints add a plain-text message.
Chain API error
{ "message": "Connector not found" }
Chain API
Base URL https://api.decentralised.art/chain. This part of the reference is generated from the OpenAPI specification.
Creating and publishing need a bearer token. Ask for a nonce, sign the message Login nonce: <nonce> with the account (EIP-191 personal_sign) and exchange the signature for an access token. Tokens are valid for five minutes.
GET/nonce/{address}No auth
Get nonce
Get a one-time nonce for an address. Sign Login nonce: <nonce> and submit it to /auth.
sol_src is the body of function run(uint32 x, uint32[] args) returns (uint32); args_count is derived from the highest args[i] it uses. Solidity source is never returned.
GET/transformation/{name}No auth
Get transformation by name
HEAD /transformation/{name} answers 200 or 404 without a body.
Compile and deploy a transformation locally for simulation. The name must not be reserved on chain. Publish it on chain through /publish/transformation.
Chain events, newest first, as connectors, transformations and conditions are published. Items move through observed, safe and finalized, or become removed after a reorganisation.
GET/feedNo auth
List feed items
Returns a newest-first page of feed items. Each item is keyed by a stable feed_id and includes compact payload metadata identifying the changed entity. Use /connector/{name}, /transformation/{name}, or /condition/{name} to hydrate full entity details.
Parameters
Name
In
Type
Description
limitrequired
query
integer
Page size. The current server requires this parameter. (1–256)
before
query
string
History cursor from a previous response cursor.next_before.
type
query
FeedEventType
Optional event type filter.
include_unfinalized
query
0 | 1
Set to 1 to include observed and safe events. Set to 0 to return only finalized events. When omitted, the current server includes unfinalized events.
Opens a Server-Sent Events stream. The response starts with a bounded replay from since_seq, then emits a stream_meta event describing the replay window, and then tails live feed deltas. Delta event names match their feed event type (connector_added, transformation_added, or condition_added). The JSON in each delta data: frame conforms to schemas/feedStreamDelta.yaml; stream_meta frame data conforms to schemas/feedStreamMeta.yaml. Idle live streams emit keepalive comments.
Parameters
Name
In
Type
Description
since_seq
query
integer (int64)
Replay stream deltas with stream_seq greater than this value. (≥ 0, default 0)
limit
query
integer
Maximum number of replay deltas returned before live tailing. (1–2048, default 200)
Simulate drafts for free in the server's local EVM, or execute published connectors on chain. Neither needs a login. particles_count is the number of steps; dynamic_ri sets running instances by position for one run.
POST/simulateNo auth
Simulate locally
Run a connector in the server's local simulation EVM: drafts created on this server, and published connectors. A connector that exists only on chain is first deployed locally with its dependencies from their verified artifacts. No login is required, and the result carries no chain provenance.
eth_call of Runner.gen on the configured runner, pinned to the block the server's execute block tag resolves to. The chain decides whether the connector exists; the server's own registry is not consulted. No login is required: an eth_call sends no transaction and costs no gas.
Publish one of your drafts on chain, paid from your own wallet. Prepare, send the transaction (with a browser wallet, or signed offline and relayed through /send), then confirm. Dependencies must be published first, and publications from one owner must be made one at a time.
POST/publish/{kind}/prepareChain bearer token
Prepare publication
Rebuild the entity from the definition retained when it was created, store its artifact durably, and return the unsigned registry transaction. The caller must own the entity. A connector's dependencies must already be registered with the artifacts it was built against; they are never published recursively. Deterministic reverts (name taken, stale nonce, identity mismatch) are reported here, before the owner pays.
Entity name. Starts with a letter or '_', contains only letters, digits and '_', at most 128 characters.
relay
boolean
Also return signing, what an offline signer needs to complete the transaction for POST /publish/{kind}/send. Leave unset for a browser wallet, which chooses its own nonce and fees. (default false)
Responses
Status
Description
Body
200
Prepared transaction, or the existing identical publication.
Broadcast a publication transaction the owner signed offline, through the server's own chain provider, so the owner needs no RPC endpoint. The owner still pays for it. The server forwards it only when the caller signed it, it calls the configured registry on its chain with no value, it publishes exactly the named entity with this content hash, and a dry run succeeds within its gas limit. Confirm it with POST /publish/{kind}.
Look the transaction receipt up once. Repeat the request while it answers 202; that is the status check. The registry projection of the event, not this response, is what the read endpoints serve.
Sign-In with Ethereum (EIP-4361). Ask for a challenge, sign its message with the wallet (EIP-191), and verify it to get a session token. Send the token as Authorization: Bearer <token>. Sessions last 24 hours. This session is separate from the chain API's access token.
POST/auth/siwe/challengeNo auth
Request a sign-in message
Creates a single-use SIWE message for the address, valid for five minutes. Its domain and URI come from the request's Origin header (or app_origin), which must be an allowed origin. At most five unexpired challenges can exist per address.
Request body application/json
Field
Type
Description
addressrequired
string
The wallet's Ethereum address.
chain_idrequired
integer
The wallet's chain. Must be a chain the server allows (by default Ethereum mainnet 1, Sepolia 11155111 and local development chains).
app_origin
string
The page's origin, used when the request carries no Origin header.
Responses
Status
Description
Body
200
The message to sign and when it expires.
{ message, expires_at }
400
Invalid address, chain not allowed, or invalid origin.
{
"message": "decentralised.art wants you to sign in with your Ethereum account:\n0xfa71Ff…2e4E\n\nSign in to decentralised.art.\n\nURI: https://decentralised.art/auth/siwe/verify\nVersion: 1\nChain ID: 11155111\nNonce: …\nIssued At: …\nExpiration Time: …",
"expires_at": "2026-10-02T10:05:00Z"
}
POST/auth/siwe/verifyNo auth
Verify the signed message
Checks the signature against an unused, unexpired challenge and opens a session. The response body is the session token itself, as a JSON string. The user record is created on first sign-in.
Request body application/json
Field
Type
Description
messagerequired
string
The exact message from the challenge.
signaturerequired
string
The wallet's EIP-191 signature of the message, hex encoded.
Responses
Status
Description
Body
200
The session token: two 64-character hex parts joined by a dot.
string
400
Malformed message or signature.
401
Unknown, used or expired challenge, or the signature does not match.
Request
curl -X POST https://api.decentralised.art/services/auth/siwe/verify \
-H "Content-Type: application/json" \
-d '{"message":"decentralised.art wants you to sign in…","signature":"0x…"}'
Browse and publish Worlds. Uploads are multipart/form-data with the ZIP in a field named bundle (up to 25 MB). The bundle rules are described in SDK → Building a World. World endpoints answer errors with a plain-text message.
The bundle conflicts with the World's current content.
DELETE/worlds/{id}Session · owner only
Delete a World
Removes a World you own from the gallery and stops serving its files.
Parameters
Name
In
Type
Description
idrequired
path
string
World id.
Responses
Status
Description
Body
204
Deleted.
401
Missing, invalid or expired session.
403
You do not own this World.
404
World not found.
World files and SDK
Static files served for Worlds.
GET/world-assets/{id}/{path}No auth
World file
A file from a published World's bundle, such as its entry page. Files are served with a Content-Security-Policy that keeps the World from reaching the network directly; it talks to its host through the World runtime.
Parameters
Name
In
Type
Description
idrequired
path
string
World id.
pathrequired
path
string
File path inside the bundle.
Responses
Status
Description
Body
200
The file.
404
Unknown or deleted World, or no such file.
GET/js/sdk/{file}No auth
World runtime and host scripts
The platform's builds of the SDK's World modules: world-runtime.js (imported by Worlds) and world-host.js (used by pages that embed Worlds).
Registry call ready for eth_sendTransaction; quantities are hex, as wallets expect. The calldata carries an empty owner signature, which the registry accepts because the owner is the sender.
addressrequired
string (Address)
Ethereum-style address, with or without a 0x prefix.
content_hashrequired
string (Hash32)
32-byte hex value.
publication_noncerequired
integer (int64)
Owner's publication nonce bound into the transaction. (≥ 0)
deadlinerequired
integer (int64)
Unix seconds after which the registry refuses the transaction. (≥ 0)
Present only when the request set `relay`. Merged into `transaction`, these complete an EIP-1559 transaction an owner can sign offline. Quantities are hex.
PrepareRequest
Prepare the publication of an entity the caller created on this server.
Field
Type
Description
namerequired
string (EntityName)
Entity name. Starts with a letter or '_', contains only letters, digits and '_', at most 128 characters.
relay
boolean
Also return `signing`, what an offline signer needs to complete the transaction for POST /publish/{kind}/send. Leave unset for a browser wallet, which chooses its own nonce and fees. (default false)
PrepareResponse
Either the transaction the owner's wallet must send, or, when the registry already holds this exact publication, the existing registration.
Publication error. Optional fields appear only when relevant.
Field
Type
Description
messagerequired
string
Human-readable message.
status
"pending"
Present on 202 while the transaction is not mined yet.
tx_hash
string
Transaction the error refers to.
missing
array of string
Connector dependencies absent from the target registry.
mismatched
array of string
Connector dependencies registered with a different artifact.
RunningInstance
Running-instance coordinates pair.
Field
Type
Description
start_pointrequired
integer
Start point index (uint32). (0–4294967295)
transformation_shiftrequired
integer
Transformation shift index (uint32). (0–4294967295)
SendRequest
Broadcast a publication transaction the owner signed offline.
Field
Type
Description
namerequired
string (EntityName)
Entity name. Starts with a letter or '_', contains only letters, digits and '_', at most 128 characters.
content_hashrequired
string (Hash32)
32-byte hex value.
raw_txrequired
string
Signed type-2 transaction: `transaction` merged with `signing` from a relay prepare, as `0x02 || rlp(...)`.
SendResponse
The provider accepted the transaction, or already held it. Confirm it with POST /publish/{kind}.
Field
Type
Description
statusrequired
"pending"
tx_hashrequired
string
Hash of the broadcast transaction.
SigningFields
Present only when the request set `relay`. Merged into `transaction`, these complete an EIP-1559 transaction an owner can sign offline. Quantities are hex.
Field
Type
Description
typerequired
"0x2"
noncerequired
string
The owner's pending account nonce.
maxFeePerGasrequired
string
maxPriorityFeePerGasrequired
string
valuerequired
"0x0"
TransformationCallDef
Transformation invocation in a connector dimension.
Field
Type
Description
namerequired
string
Transformation name
args
array of integer
Transformation arguments. Omitted means no arguments.
TransformationInfoResponse
Transformation information. The Solidity source is an execution input kept in local storage or a verified artifact and is never served.
Field
Type
Description
namerequired
string
Transformation name.
args_countrequired
integer
Number of arguments (uint32), derived from the source and registered on chain. (0–4294967295)
ownerrequired
string (Address)
Ethereum-style address, with or without a 0x prefix.
addressrequired
string
On-chain address once published; "0x0" for a local simulation entity.
UnsignedTransaction
Registry call ready for eth_sendTransaction; quantities are hex, as wallets expect. The calldata carries an empty owner signature, which the registry accepts because the owner is the sender.
Field
Type
Description
fromrequired
string (Address)
Ethereum-style address, with or without a 0x prefix.
torequired
string (Address)
Ethereum-style address, with or without a 0x prefix.
datarequired
string
Hex-encoded calldata.
chainIdrequired
string
Chain id as a hex quantity.
gasrequired
string
Gas limit (estimate plus headroom) as a hex quantity.
VersionResponse
Version information.
Field
Type
Description
build_timestamprequired
string
ISO-8601 build timestamp of the running server
versionrequired
string
Human-readable API version
Services schemas
UserPublic
A user's public record. Fields are snake_case.
Field
Type
Description
idrequired
string
The user's Ethereum address (EIP-55 checksummed). Users are identified by address.
display_namerequired
string, nullable
Name shown on the platform.
statusrequired
"active" | "suspended" | "deleted"
Account status.
rolesrequired
array of "user" | "admin" | "moderator"
Roles of the user.
profile_jsonrequired
object
Free-form profile data, such as public.nickname, public.bio and public.kind.
created_atrequired
string (date-time)
When the user first signed in.
updated_atrequired
string (date-time)
Last profile change.
last_login_atrequired
string (date-time), nullable
Last sign-in.
WorldDescriptor
A published World. Fields are camelCase.
Field
Type
Description
idrequired
string
World id, used in asset URLs.
slug, name, version, descriptionrequired
string
From the World's manifest.
entryUrnrequired
string
Where the World's entry page is served, under /world-assets.
entryPathrequired
string
Entry file inside the bundle.
runtimerequired
"iframe"
How the World runs.
surfacesrequired
array of "world-page" | "studio-plugin"
Where the World can be shown.
permissionsrequired
array of string
Permissions granted to the World.
shortDescription, heroLabel, accentColor, preview
string
Optional presentation details from the manifest.
acceptedFormatHashesrequired
array of string
Formats the World understands.
acceptedConnectorSetsrequired
array of { connectors, optionalConnectors }
Connector names the World understands.
valueLimits
object
Ranges for particlesCount and for values on specific output paths.
ownerIdrequired
string
Address of the user who uploaded it.
bundleHash, manifestHashrequired
string
Hashes of the uploaded bundle and its manifest.
statusrequired
"active" | "deleted"
World status.
createdAt, updatedAtrequired
string (date-time)
Timestamps.
Specification
The chain API is specified in OpenAPI 3.0 in decentralised-art/api-spec,
which is also published as browsable docs. The
specification this reference is built from is also served as openapi/chain.json. The live
server reports its version at GET /version (currently 0.4.0).