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.
Delete a key pair from the active scope
Deletes the selected key pair, as triggered by the "Delete" action on the key pair detail page and the
row action on the Key pairs page. Deleting a key pair removes it from the scoped registry so it can no
longer be attached to new instances; instances already configured with the key keep their
injected authorized_keys entry (guest state is untouched). The detail UI blocks deletion while
the key is still configured on instances ("Detach … from N instance(s) first") — the backend
enforces the same dependency rule.
Validation: scopeId must be accessible to the caller (404 when unknown); keyPairId must
identify a key pair within that scope (404 NOT_FOUND); the key pair's usedBy set must be empty
— when one or more instances still reference the key the request maps to 409
DEPENDENCY_BLOCKED with the blocking instance references; the resource must not be locked (409
LOCKED is reserved for scope locks).
Async & state: Asynchronous soft delete; returns 202 with an Operation. The key pair
transitions active → deleting → deleted; on completion it disappears from list reads (soft
delete: rows are retained with deleted_at set and excluded from every query) and a
resource.updated SSE frame of kind compute.keyPair announces the removal. Terminal states:
succeeded (deleted) or failed (key pair remains queryable and recoverable).
Errors: 401 unauthenticated; 403 caller lacks destructive-action permission
(owner|admin|contributor); 404 unknown scopeId/keyPairId; 409 dependency blocked while
instances still use the key; 500 delete workflow failure.
Idempotency/Concurrency: Idempotency-Key is optional (recommended); replaying the same
key returns the same
202 Operation. This operation does not check If-Match; a sent one is ignored (an instance
still using the key is the 409 above, evaluated at the time of the delete).
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.
keyPairId*stringIdentifier of the key pair within the active scope.
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.
uuidDeletion accepted; track progress 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 DELETE "https://example.com/scopes/string/compute/key-pairs/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"}