Read who holds a shipment, who signed each handover, and check that nobody changed the record. Then run your own shipment in the sandbox: every successful write is a real transaction on Stellar's test network. No account, no key.
Base URL
https://rio-miami-rail.vercel.app · JSON · CORS open · no key, no account.
Network
?network=testnet is the default. mainnet reads the mainnet registry CDV7YI7K…. The sandbox runs on testnet only.
Limits
Per IP address, per 10 minutes: 5 new sandbox shipments, 30 sandbox writes, 20 history calls. About 20 new shipments an hour for everyone.
Production access
Want to run your own handovers on the rail? Request access.
Try the APIStellar testnet
Request
Press “Open a shipment”.
Response
—
Each call that writes returns its transaction hash and a link to the public explorer.
Get started
Open a shipment
The sandbox creates five test companies on a route (warehouse, trucker, ship, customs, buyer) and opens the shipment on the registry: two confirmed transactions, about 10 to 15 seconds. The key is shipment.key in the answer. Needs curl and jq.
KEY=$(curl -s -X POST https://rio-miami-rail.vercel.app/api/sandbox/shipments | jq -r .shipment.key)
Then hand it to the next company. Both companies sign:
curl -X POST https://rio-miami-rail.vercel.app/api/sandbox/shipments/$KEY/handover
See the transaction on the explorer
Every write answers with tx.hash and tx.explorer, a stellar.expert link. There you see the contract call, its arguments and the two signatures. Nobody needs our server to read it.
Verify the head
The head is a fingerprint of the whole history: each step hashes the one before it. The history endpoint recomputes it from each transaction's own arguments and compares it with the head stored in the contract.
To trust no server, not even this one, press Verify the record above: your browser fetches each transaction from Stellar's public Horizon, rebuilds the head with the formula below and compares it with the head the contract returns. Any tool that can read Horizon can do the same.
Reference
Examples are real answers from Stellar testnet; long addresses and hashes are shortened here with “…”.
GET/api/shipments/{key}
The shipment's current state, read live from the contract. Works for demo and sandbox shipments. No limit of its own.
Parameters
Name
In
Type
Required
Format
key
path
string
yes
64 lowercase hex characters: sha256 of "<container>|<origin>"
live: read from the contract now. snapshot, not live: testnet could not be reached and a saved copy of a demo shipment is shown (only key, registry, head).
registry, registry_name
The custody_registry contract that holds the shipment: demo, three-machine or sandbox.
status
Open, Delivered or Frozen (by the registry admin).
current_custodian
Stellar address of the company holding the goods now.
route
Every company on the route, in order; the first one holds the goods at opening.
seq
Handovers done so far.
head
Fingerprint of the whole history: each step hashes the one before it (formula below).
holder
Who received the goods at delivery; null before.
token
The asset contract the shipment names. Sandbox shipments name the native XLM contract as a placeholder.
Every registry call for the shipment, with its transaction, and the head recomputed from each call's own arguments. Limit: 20 per 10 minutes per IP address; an answer is reused for 20 seconds.
Parameters
Same as above: key (path, required), network (query, optional).
In ledger order: open, handover, attest, deliver, each with its transaction hash, explorer link, ledger, time and the head_after it.
assurance
Declared by the caller: 3 = both signed in person, 2 = one side by delegation, 1 = external attestation only.
head_matches
true when the recomputed head equals the head in the contract. null when the shipment opened more than about 7 days ago: the testnet RPC keeps contract events that long.
Opens a new test shipment on a five-stop route (warehouse, trucker, ship, customs, buyer). The server creates six throwaway testnet accounts (the five companies and the holder) and calls open: two confirmed transactions, about 10 to 15 seconds. No body. Limit: 5 per 10 minutes per IP address, about 20 an hour for everyone.
Request
curl -X POST https://rio-miami-rail.vercel.app/api/sandbox/shipments
The next handover, signed by both companies: the one giving the goods sends the transaction, the one receiving them signs its authorisation. About 5 seconds. Limit: 30 sandbox writes per 10 minutes per IP address.
Parameters
Name
In
Type
Required
Format
key
path
string
yes
A sandbox shipment key (64 hex).
from
body
string
no
warehouse, trucker, ship, customs or buyer. Default: the current custodian. Another company is sent anyway, so the contract's refusal shows.
assurance
body
integer
no
1, 2 or 3; default 3. Outside 1 to 3 the contract refuses it.
evidence
body
string
no
Any text; its sha256 is stored as the handover's evidence hash.
curl -X POST https://rio-miami-rail.vercel.app/api/sandbox/shipments/$KEY/handover \
-H 'Content-Type: application/json' -d '{"from":"customs"}'
{
"network": "testnet",
"error": {
"code": "E_WRONG_CUSTODIAN",
"message": "The company handing over is not the one holding the shipment.",
"refused_by": "custody_registry",
"contract_error": 1
}
}
The buyer, last on the route, hands the goods to the holder; both sign and the shipment becomes Delivered. Before every handover is done the contract refuses it. Sandbox shipments carry no token, so nothing is burned. Parameters: key (path), network (query). Same limit as handover.
curl -X POST https://rio-miami-rail.vercel.app/api/sandbox/shipments/$KEY/deliver
The answer has the same shape as a handover: call: "deliver", tx, signed_by: ["buyer", "holder"] and the shipment with status: "Delivered" and its holder.
Every error answers { "error": { "code", "message" } }. When the contract itself refused the call, the answer adds "refused_by": "custody_registry" and its error number, and no transaction is sent.
Code
HTTP
Meaning
What this is, and is not
This is the open API of Radox Rail: it reads and writes the open-source custody_registry contract on Stellar's test network. It serves only that contract; Radox's own platform is a separate system and is not exposed here. The companies are test accounts, the keys are test keys, and no real goods or money move. Sandbox shipments go to their own registry (CBTHLS…6ERX), deployed from the same code as the demo registry (wasm 8230ed93…1342); they name the native XLM contract as a placeholder token, and no token is issued or burned.