Semaphore leases
A lease is one held slot on a semaphore. A test takes one around the part that uses the shared resource, renews it while it works and releases it when done; a lease that is not renewed ends after its TTL, so a test that dies frees its slot. Leases take the run token that starting a run, a shard or a retry returns as semaphores.token, not an API key, and semaphores.url is where their routes start. An unpublished run has no run token, so it holds none.
The SemaphoreLease object
One held slot on a semaphore, until it is released, expires or its holder finishes.
Attributes
leasestringRequiredThe lease's ID. Renew and release the lease by it.
semaphorestringRequiredThe semaphore's name.
expiresAtstringRequiredWhen the lease ends unless it is renewed, as an ISO 8601 timestamp. Its slot frees itself then.
{ "lease": "Ls4TnV8qWm2C", "semaphore": "payments-sandbox", "expiresAt": "2026-10-14T09:41:20.000Z"}Take a lease
POST/Takes a slot on the semaphore, creating it with capacity on first use. When every slot is held, the request waits up to 20 seconds for one to free, then fails with Busy and retryAfter; ask again until your own timeout. Another capacity than the semaphore's fails with Conflict. The lease belongs to the shard or retry whose run token took it, and finishing that shard or retry releases it.
Path parameters
slugstringRequiredThe workspace's slug or ID, such as acme.
namestringRequiredThe semaphore's name, such as payments-sandbox: 1 to 100 lowercase letters, digits, dots, underscores or hyphens, starting with a letter or digit.
Body parameters
capacitynumberRequiredHow many leases the semaphore allows at once, 1 to 100. The first lease creates the semaphore with it; every later lease must send the same.
ttlSecondsnumberHow long the lease lasts from now, in whole seconds, from 5 to 600; 60 by default. Renew it every third of that.
testnullable stringThe test taking the lease, as members see it on the semaphore, up to 200 characters.
Returns
Returns the SemaphoreLease object. Status 201.
Errors
- 400
InvalidInputThe request is malformed, or a value is not allowed.- 401
UnauthorizedThe request has no valid API key.- 403
ForbiddenThe key's user or role may not do this.- 404
NotFoundThe workspace or object does not exist, or the caller cannot see it.- 409
- The change conflicts with current data, such as a slug that is already in use.
- 500
InternalClanker Ship failed to handle the request. Retry, or report the response's x-request-id.
curl -X POST https://api.clankership.com/v1/workspaces/acme/semaphores/{name}/leases \ -H "Authorization: Bearer $CLANKER_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "capacity": 1, "ttlSeconds": 60, "test": "checkout › applies a coupon" }'{ "lease": "Ls4TnV8qWm2C", "semaphore": "payments-sandbox", "expiresAt": "2026-10-14T09:41:20.000Z"}Renew a lease
POST/Extends a lease to ttlSeconds from now and returns its new expiry. A lease that was released or expired, or that another run holds, fails with NotFound: take a new one.
Path parameters
slugstringRequiredThe workspace's slug or ID, such as acme.
namestringRequiredThe semaphore's name, such as payments-sandbox: 1 to 100 lowercase letters, digits, dots, underscores or hyphens, starting with a letter or digit.
leasestringRequiredThe lease's ID, from taking it.
Body parameters
ttlSecondsnumberHow long the lease lasts from now, in whole seconds, from 5 to 600; 60 by default. Renew it every third of that.
Returns
Returns the SemaphoreLease object. Status 200.
Errors
- 400
InvalidInputThe request is malformed, or a value is not allowed.- 401
UnauthorizedThe request has no valid API key.- 403
ForbiddenThe key's user or role may not do this.- 404
NotFoundThe workspace or object does not exist, or the caller cannot see it.- 409
ConflictThe change conflicts with current data, such as a slug that is already in use.- 500
InternalClanker Ship failed to handle the request. Retry, or report the response's x-request-id.
curl -X POST https://api.clankership.com/v1/workspaces/acme/semaphores/{name}/leases/{lease}/renew \ -H "Authorization: Bearer $CLANKER_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "ttlSeconds": 60 }'{ "lease": "Ls4TnV8qWm2C", "semaphore": "payments-sandbox", "expiresAt": "2026-10-14T09:41:20.000Z"}Release a lease
DELETE/Frees the lease's slot for the next test. Releasing a lease that already ended succeeds too.
Path parameters
slugstringRequiredThe workspace's slug or ID, such as acme.
namestringRequiredThe semaphore's name, such as payments-sandbox: 1 to 100 lowercase letters, digits, dots, underscores or hyphens, starting with a letter or digit.
leasestringRequiredThe lease's ID, from taking it.
Returns
Returns no content. Status 204.
Errors
- 400
InvalidInputThe request is malformed, or a value is not allowed.- 401
UnauthorizedThe request has no valid API key.- 403
ForbiddenThe key's user or role may not do this.- 404
NotFoundThe workspace or object does not exist, or the caller cannot see it.- 409
ConflictThe change conflicts with current data, such as a slug that is already in use.- 500
InternalClanker Ship failed to handle the request. Retry, or report the response's x-request-id.
curl -X DELETE https://api.clankership.com/v1/workspaces/acme/semaphores/{name}/leases/{lease} \ -H "Authorization: Bearer $CLANKER_API_KEY"