Locks & Inventory API
Atomic locks and inventory reservations over REST. All endpoints are scoped to a repository and branch and require the locks subsystem to be enabled.
A 409 Conflict means the lock is currently held, or the pool is sold out — it
is the normal "you lost the race" outcome, not an error.
Acquire a lock
POST /api/{repo}/{branch}/locks/acquire
Request:
{
"key": "seat:AA123:14A",
"ttl_ms": 5000,
"owner": "booking-service"
}
owner is optional and informational. Response (200):
{
"acquired": true,
"key": "seat:AA123:14A",
"token": 42,
"expires_at_ms": 1750000000000
}
When the key is already held (409):
{ "acquired": false }
The token is a monotonically increasing fence token. Store it on whatever the
lock protects and reject writes that carry an older token to stay correct under
rare timing edge cases.
Release a lock
POST /api/{repo}/{branch}/locks/release
{ "key": "seat:AA123:14A", "token": 42 }
Response:
{ "released": true }
released is false if the lock was already gone or held by someone else.
Releasing is idempotent and safe to call from a finally block.
Renew a lock
Extend the lease before it expires (for long-running work).
POST /api/{repo}/{branch}/locks/renew
{ "key": "seat:AA123:14A", "token": 42, "ttl_ms": 5000 }
{ "renewed": true }
renewed is false if the lease was already lost.
Claim inventory
Atomically take n units from a pool, seeding it to capacity the first time
it is touched.
POST /api/{repo}/{branch}/inventory/claim
{ "pool": "flight:AA123", "n": 1, "capacity": 180 }
Response (200):
{ "claimed": true, "remaining": 179 }
When fewer than n units remain (409):
{ "claimed": false }
Release inventory
Return units to a pool.
POST /api/{repo}/{branch}/inventory/release
{ "pool": "flight:AA123", "n": 1 }
{ "remaining": 180 }