Accept a handover: become the owner
const url = 'https://beta-api.plune.ai/v1/handovers/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/accept';const options = {method: 'POST', headers: {cookie: 'plune_session=<plune_session>'}};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://beta-api.plune.ai/v1/handovers/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/accept \ --cookie plune_session=<plune_session>The member asked, signed in (ADR 0050 §3) — a button on the page the mail leads to, never the link itself. In ONE transaction, everything is read again: the request still open and not run out, the project or the company still there, the member still in it (in a company’s project, in the company too), the one who asked still its owner; then the old owner becomes a manager and the member the owner. A check that fails is 409, and the request is cancelled. Anybody else, and a request no longer open, gets the 404 an id nobody has. Both are told by mail. A reader who accepts takes a write seat (#1439). Recorded on both rows, reason: ownership handed over. The signed-in session alone: an API token gets 403 session_required — the owner holds the secrets, and a CI token neither asks for, answers nor reads a handover.
Authorizations
Section titled “Authorizations ”Parameters
Section titled “ Parameters ”Path Parameters
Section titled “Path Parameters ”The handover.id of the request, as the mail’s page names it
Responses
Section titled “ Responses ”Accepted — the member is the owner now
object
A handover of ownership (ADR 0050 §3): the owner asks one member to take the project or the company over; nothing changes until that member accepts. Seven days to answer, then expired.
object
The member asked, as GET /v1/members (or the company page) lists them
Example
{ "handover": { "id": "6f1c2b3a-0000-4000-8000-0000000000b9", "toUserId": "6f1c2b3a-0000-4000-8000-0000000000a2", "state": "accepted", "expiresAt": "2026-08-04T09:00:00.000Z" }}No / invalid session
An API token
object
Example
{ "error": "a handover takes the signed-in session — an API token neither asks for, answers nor reads one", "code": "session_required"}Not a request to you, or no longer open
object
Example
{ "error": "handover '6f1c2b3a-0000-4000-8000-0000000000b9' not found"}The request no longer holds — the owner, the member or the place changed since it was asked; it is cancelled
object
Example
{ "error": "this handover no longer holds — the owner, you or the place changed since it was asked; it is cancelled"}Two refusals share this status, and what to do about them is opposite. Rate-limited — the per-route throttle, or the per-minute request limit of the plan an API token counts by (#1442, #2092): Retry-After carries the seconds until the window rolls over, and waiting that long is the way out. Quota reached — a ceiling on what the project holds (runs in the last 24 hours, test cases, items waiting in the review queue): { error, quota }. A retry straight away frees nothing, so do not loop on it; the message says what makes room — deleting cases, working the queue down, an operator raising the limit — and the run quota, a rolling 24 hours, frees its oldest runs as they age out. Tell the two apart by the body: a 429 whose body has a quota object is a quota, one without it is a throttle. quota carries kind, limit, used, remaining and resetsAt: the figures behind the sentence, and for the run quota the instant its oldest run ages out (#1258). Retry-After is sent on a quota only where there is such an instant (the run quota: the whole seconds, at least 1, until resetsAt); the case, review-queue and project quotas free only by an action, have resetsAt: null, and send no Retry-After. GET /v1/quotas reads the same figures without a refusal.
object
The body of a 429 that is a quota and not a throttle: the sentence, and the figures behind it.
object
What was reached and the way out.
object
The ceiling. A write that would take used past it is refused with 429.
What the project holds now, counted by the same query that refuses a write.
limit - used, never below 0.
When the oldest counted run ages out of the rolling 24 hours and a slot frees on its own. null for the two quotas only an action frees (delete cases, decide queue items), and for a run quota with no runs in the window.
Example
{ "quota": { "kind": "runsPerDay" }}Headers
Section titled “Headers ”Seconds until the window rolls over on a throttle; on a quota, until quota.resetsAt — sent only for the run quota, which has one