Exploded engineering blueprint of a delivery robot

schematic sheet 01 — hoodly technical documentation

Architecture

How a task becomes a proof, who pays for what, and why each piece is built the way it is.

The whole flow

A robot claims a task, does the work, and submits evidence. Hoodly hashes that evidence, writes the hash onto Robinhood Chain, and hands back a receipt. Anyone can later re-hash the same evidence and compare it against the chain. The flow is built for robot fleets; the API is agent-agnostic — any autonomous system that can claim and submit JSON follows the same lifecycle.

Lifecycle of one task
POST /api/v1/tasks                  robot claims work        status: claimed
      │
      │  ... robot executes, gathers evidence ...
      ▼
POST /api/v1/tasks/:id/complete     robot submits proof
      │
      ├─ hash the proof (keccak256 over canonical JSON)
      ├─ reserve 1 anchor of quota + a gas ceiling
      ├─ send the hash on-chain as transaction calldata
      └─ settle the reservation at the real gas cost
      │
      ▼                                                       status: verified
GET /api/v1/verify/:proofHash       anyone re-checks, free

If anchoring fails at any point the task becomes failed with a reason, and the reservation is returned in full. Nothing is charged for a proof that never reached the chain.

No smart contract

Anchoring is a zero-value transaction from the server wallet to itself, carrying a versioned payload in its calldata:

HOODLY:v1:<robotId>:<taskId>:<proofHash>

That is the entire on-chain design. The record is immutable, carries the block timestamp, and is readable in the block explorer's input-data field. Verification means reading the transaction back and comparing the hash.

There is no contract of ours deployed anywhere, which means no upgrade keys, no audit surface, and nothing that can be paused or rug-pulled. The trade-off is that we cannot express logic on-chain — but proof anchoring does not need any.

Identity is a wallet

There is no email, no password and no external auth provider. An account is an address: you sign a short EIP-4361 style message, the server verifies the signature and starts a session in an HttpOnly cookie. Signing is free and sends no transaction.

This is also what makes payments self-identifying. A transfer from your sign-in wallet needs no memo or reference, because the sender address already says which account it belongs to.

Two credentials, two audiences

FieldTypeDescription
session cookiehumanSet by signing a message in a browser wallet. Guards the dashboard and its API routes.
robot API keymachine`hdly_` plus 40 hex characters, shown once at creation. Only a SHA-256 hash is stored, so a database leak cannot be replayed.

A robot never holds a wallet, a private key or ETH. It holds one bearer token and speaks plain HTTP — that is deliberately the entire integration surface.

Who pays for what

Anchoring draws on two separate prepaid balances, because they pay for two different things. Burning $HOODLY grants anchor quota, the right to use Hoodly — the tokens are destroyed rather than sent to us. A small ETH balance covers the actual chain cost, spent by the server wallet on your behalf.

Gas has to be prepaid because a transaction can only be paid by whoever signs it, and your browser wallet is not reachable when a robot finishes at three in the morning. See credits for the mechanics.

Storage

A single Postgres database (Neon) over HTTP, reached through one privileged connection. Row level security is intentionally unused: every query runs server-side and the API routes are the only path to the data, so authorization lives in one layer rather than two.

The HTTP driver cannot hold a transaction open across statements, which shapes anything that touches money. Balance changes are written as single atomic statements — a conditional UPDATE for a debit, a data-modifying CTE where a ledger entry and a balance change have to happen together. A read-then-write would race whenever two robots finish at the same instant.

No scheduler

Nothing in Hoodly depends on cron. Incoming payments are picked up when the billing page is opened, when you press check payments, and automatically when a robot hits an empty balance. Counter cleanup rides along with that same sync.

An external scheduler can still call POST /api/v1/credits/sync with a shared secret if you want periodic reconciliation, but nothing breaks without one — and that keeps the whole system portable rather than tied to one host.

Failure behaviour

The parts that guard access fail closed: if the token balance cannot be read, the request is refused with 503 rather than allowed through, because a gate that opens when the network hiccups is not a gate.

The parts that merely protect us fail open: if the rate limit counter is unreachable, the request proceeds. Abuse is a smaller problem than an outage that takes every fleet down with it.