Identity & Access Management

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 subscription and every project beneath it

DELETE
/tenants/{tenantId}/subscriptions/{subscriptionId}

Deprovisions ALL of the subscription's projects (each Keystone project + app-cred) and then removes the subscription itself (issue). Every project's scope projection moves to DEPROVISIONING and one iam.subscription.deprovision Operation is returned (202, PENDING). Safe default: if ANY project beneath the subscription still holds ANY live resource (the same resource count the project delete uses) the delete is refused 409 CONFLICT. The optional body is the cascade consent, the same shape as the project delete's: only acknowledgeAllResourcesDeleted: true PLUS all four categories true is consent; anything less (no body included) takes the safe-default path unchanged. With consent the worker sweeps and verifies every project before deleting it. Imported projects: an IMPORTED project beneath it needs acknowledgeImportedProjectDestruction: true (else 409 IMPORTED_PROJECT_ACK_REQUIRED); inside its protection window a customer cannot destroy it at all (403 IMPORTED_PROJECT_PROTECTED); an import that never completed, or a release in progress, refuses the whole delete (409 IMPORTED_PROJECT_IMPORT_INCOMPLETE / IMPORTED_PROJECT_RELEASE_IN_PROGRESS). Authorization: ANY bearer (API token or service-account key) is refused 403 INTERACTIVE_SESSION_REQUIRED before anything else -- this cascade destroys cloud resources and needs an interactive console session. Then: unreached subscription 404; no SUBSCRIPTION-level owner grant 403 (a project owner is not enough); tenant on non-payment hold 403 TENANT_SUSPENDED. Async & state: 202 + Operation PENDING → RUNNING → SUCCEEDED | FAILED. Errors: 401; 403 (bearer, not owner, hold, imported-project protection); 404; 409 (live resources without consent, imported-project gates, idempotency body mismatch); 422 (unknown body field, non-UUID Idempotency-Key); 500. Idempotency/Concurrency: Idempotency-Key (UUID) is optional (recommended); the consent body is part of the fingerprint, so a replay with different consent is 409, never the recorded 202.

Authorization

bearerToken
headerAuthorizationBearer <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.

Path Parameters

tenantId*string

The tenant id.

subscriptionId*string

The subscription id (unique platform-wide, derived from the tenant id + the subscription's name at creation).

Header Parameters

Idempotency-Key?string

Optional; 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.

Formatuuid

Request Body

application/json
  1. body

OPTIONAL body of the project and subscription deletes. Consent counts only when acknowledgeAllResourcesDeleted AND all four categories are true; anything less keeps the safe default (409 for a non-empty target).

acknowledgeAllResourcesDeleted?boolean
Defaultfalse
categories?

The four per-category cascade-delete consent ticks; every flag defaults to false.

acknowledgeImportedProjectDestruction?boolean

Required when the project (or any project beneath the subscription) is IMPORTED; ignored otherwise.

Defaultfalse

Response Body

Teardown accepted; the PENDING iam.subscription.deprovision Operation.

application/json
  1. response

A long-running operation record. GET /operations/{operationId} returns its current state.

id*string

Operation identifier, unique platform-wide.

action*string

Canonical action id that started this operation, e.g. compute.instance.create.

state*OperationState

State machine for long-running operations. PENDING and RUNNING are transitional; the rest are terminal.

Value in"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.

Range0 <= value <= 100
error?|null

Populated only when state is FAILED (or CANCELLED with partial rollback notes).

warning?|null

Non-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*string
updatedAt*string
curl -X DELETE "https://example.com/tenants/string/subscriptions/string" \  -H "Content-Type: application/json" \  -d '{}'
{  "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"}