Machine-facing data, priced per call, paid over x402.
Distributed locks, semaphores, shared rate-limit buckets and monotonic counters for multi-agent fleets. No signup, no Redis, no infrastructure — pay once for a session and coordinate for as long as it lasts.
Settlement on Base takes roughly 1.9 seconds. A lock that takes 1.9 seconds to acquire is not a lock — fine-grained coordination is the entire point. So the payment happens once, up front, and every primitive call after that runs free of the chain.
Measured on production: 57ms median for an uncontended call, 64ms at p95.
| Tier | Operations | Valid | Price | Per 1k |
|---|---|---|---|---|
| Trial | 100 | 1 hour | $0.05 | $0.50 |
| Standard | 1,000 | 24 hours | $0.25 | $0.25 |
| Fleet | 5,000 | 7 days | $1.00 | $0.20 |
Renew and release are free. Not a promotion — a design requirement. If releasing a lock cost an operation, a fleet that exhausted its budget mid-run would be stranded holding locks it could not let go of, for want of two hundredths of a cent. You can always let go of what you hold.
# 1. Buy a session (this is the only call that touches the chain)
POST /v1/coord/session?ops=1000
→ { "session_token": "<64 hex>", "ops_total": 1000, "expires_at": "..." }
# 2. Coordinate. One operation each.
POST /v1/coord/lock/build-cache?limit=1&ttl=60&holder=agent-7
→ { "acquired": true, "fence": 41, "expires_at": "..." }
→ { "acquired": false, "retry_after": 12, "next_expiry": "..." }
POST /v1/coord/lock/build-cache/renew?holder=agent-7&ttl=60 # free
DELETE /v1/coord/lock/build-cache?holder=agent-7 # free
# A semaphore is the same primitive with limit > 1
POST /v1/coord/lock/gpu-pool?limit=4&ttl=300&holder=agent-7
# A rate limit shared across the whole fleet
POST /v1/coord/quota/openai?rate=60&per=60&burst=60
→ { "granted": true, "remaining": 41, "full_at": "..." }
→ { "granted": false, "retry_after_ms": 850 }
# The next number, with no collisions across ten agents
POST /v1/coord/sequence/order-id
→ { "value": 1042 }
Every call carries Authorization: Bearer <session_token>.
This is the part most lock services leave out, so read it before you build on this.
A holder that stalls past its TTL — a long GC pause, a network partition, a suspended VM — wakes up still believing it holds the lock, while another agent has legitimately taken it. Both then act. No TTL fixes this, because the stalled process has no way to know time passed.
The only fix is that the thing you are protecting refuses stale writers. So
every acquire returns a fence, strictly increasing per lock.
Carry it into whatever you are guarding and reject anything with a lower
one:
UPDATE cache SET value = ?, fence = ?
WHERE key = ? AND fence < ? -- a stalled holder's write does nothing
Without a downstream fence check, what you have is an advisory lock. That is often fine — plenty of work is idempotent, or the cost of doing it twice is low. But it is your call to make, and you cannot make it if we let you believe the TTL was doing more than it was.
retry_after worth respecting. You are never charged when we fail.db-write and someone else's are different objects. Pass ns= to run two independent fleets from one wallet.not_held means stop. Your lease lapsed and someone else may hold it. That is reported rather than silently re-granted.Control state and nothing else — a permit, an expiry, a counter, a number of tokens. There is no payload here to leak, and names are not persisted: a primitive is addressed by a hash of your wallet, namespace and name. That is also why there is no “list my locks” endpoint; it would mean holding the names.