Preview — pending review
This reference is generated from the platform API contract and is still under review. Operations, fields, and descriptions can change before publication.
Accept a volume transfer offer into this project
Called in the RECEIVING project's scope with the transferId and authKey the donor was
given. On success the volume belongs to this project: the provider reassigns it, this
API's inventory row follows, and billing follows with it.
The tenant boundary is enforced here, not by the key. The provider would honour a key
presented from anywhere in the cloud; this route refuses a transfer whose source volume does
not sit under the SAME tenant as the accepting scope, and refuses it as 404 NOT_FOUND rather
than 403 so an offer from another tenant is indistinguishable from one that does not exist.
Billing. The hour bucket containing the acceptance belongs in full to the SOURCE
subscription; the first bucket starting at or after it is the destination's. That is the
same cut-over fixed for project moves, applied to one volume, and it is why usage
is sealed against the source in the same transaction that flips the owner. No hour is
split, duplicated or dropped.
Validation: unknown or already-accepted transferId, a wrong authKey, and an offer
from another tenant are ALL 404 NOT_FOUND — distinguishing them would let a caller probe for
offers they cannot see. The receiving subscription's q-volumes / q-gigabytes quota must
cover the volume (→ 409 QUOTA_EXCEEDED): accepting is the one way a project gains a volume
without passing the create gate. Caller needs owner|admin|contributor on the receiving scope.
Async & state: Asynchronous — 202 with an Operation. On completion the volume appears in
this project's inventory and a resource.updated SSE frame (kind storage.volume) is
emitted in the receiving scope.
Errors: 401; 403; 404 unknown scope, unknown/spent offer, wrong key, or cross-tenant
offer; 409 QUOTA_EXCEEDED; 422 malformed body; 500 provider failure.
Idempotency/Concurrency: Idempotency-Key is optional (recommended); the replay returns
the original
202. The offer itself is single-use at the provider, so two racing accepts cannot both win.
bearerTokenAuthorizationBearer <token>An API token (pc_live_…) or a service-account key (sak_live_…), created in Identity & Access Management and sent as Authorization: Bearer <token>. Requests are rate limited per credential and per tenant: every response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset, and a refused request gets 429 RATE_LIMITED with Retry-After.
scopeId*stringOpaque ownership+authorization scope resolving to tenant + subscription + project.
Idempotency-Key?stringOptional; recommended for safe retries. When sent, the same key+body within 24h replays the original result and the same key with a different body is 409 CONFLICT; keys are unique per tenant. When an API token or service-account (bearer) caller omits it, the request is applied once with no replay protection (a retry may apply it again). A console session gets one from the edge.
uuidapplication/json- body
Payload for accepting a transfer offer into the calling scope's project.
transferId*stringIdentifier of the offer, from the donor.
1 <= length <= 255authKey*stringThe one-shot authorization key the donor received when the offer was opened.
1 <= length <= 255Acceptance accepted; track it through the returned Operation.
application/json- response
A long-running operation record. GET /operations/{operationId} returns its current state.
id*stringOperation identifier, unique platform-wide.
action*stringCanonical action id that started this operation, e.g. compute.instance.create.
state*OperationStateState machine for long-running operations. PENDING and RUNNING are transitional; the rest are terminal.
"PENDING""RUNNING""SUCCEEDED""FAILED""CANCELLED"resourceKind?|Kind of the target resource (matches RealtimeEvent.kind), null for resource-less actions.
resourceId?|Identifier of the target resource; null until the resource is allocated.
resourceName?|Human-readable name of the target resource captured when the operation was opened; null when unknown or the resource has been deleted (clients fall back to resourceId).
principalId?|Subject id (user id/email or service-account id) of the actor that initiated this operation, captured at the create chokepoint; null on internal/worker paths with no request-scoped principal or for historical rows. This is the real actor the Activity feed renders.
sourceIp?|Source IP address of the request that initiated this operation; null when unavailable (internal/worker paths, historical rows).
progressPercent?|Best-effort progress; null when the action does not report progress.
0 <= value <= 100error?|nullPopulated only when state is FAILED (or CANCELLED with partial rollback notes).
warning?|nullNon-fatal degradation recorded on an operation that still SUCCEEDED - the primary action completed but something explicitly requested could not be delivered (e.g. publicIp was requested at instance create but no floating IP could be assigned). On a CANCELLED create it reports that the provider resource had already been created and was kept (live and billed until deleted; details.disposition = left_in_place). Same code+message shape as error so clients render both uniformly; null when the operation ran without degradation.
startedAt?|When the worker began executing; null while PENDING.
finishedAt?|When a terminal state was reached; null while transitional.
createdAt*stringupdatedAt*stringcurl -X POST "https://example.com/scopes/string/storage/volume-transfers/actions/accept" \ -H "Content-Type: application/json" \ -d '{ "transferId": "string", "authKey": "string" }'{ "id": "string", "action": "string", "state": "PENDING", "resourceKind": "string", "resourceId": "string", "resourceName": "string", "principalId": "string", "sourceIp": "string", "progressPercent": 0, "error": { "code": "string", "message": "string", "field": "string", "details": {}, "retryable": false }, "warning": { "code": "string", "message": "string", "field": "string", "details": {}, "retryable": false }, "startedAt": "string", "finishedAt": "string", "createdAt": "string", "updatedAt": "string"}