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.

Move a project to another subscription of the same tenant

POST
/tenants/{tenantId}/subscriptions/{subscriptionId}/projects/{projectId}/actions/move

Moves the project to targetSubscriptionId. SYNCHRONOUS: nothing in OpenStack changes (the project keeps its id, Keystone project, app-cred, scope projection and every resource); the catalog + billing rewrite is one transaction that either happens completely or not at all. Billing is sealed under the SOURCE at cutoverAt; every usage hour starting before billingBoundary belongs to the source, every hour starting at or after it to the destination. An iam.project.move Operation is recorded already SUCCEEDED for the audit trail (operationId); there is nothing to poll. Authorization: a SUBSCRIPTION-level owner grant on BOTH the source and the destination subscription: unreached project or destination 404, not owner on either end 403. An API token is refused 403 TOKEN_SCOPE_MISSING (iam:write is never grantable); tenant on non-payment hold 403 TENANT_SUSPENDED. Validation / preconditions (checked before anything is written): destination equal to the current subscription 422; different currency 409 CONFLICT; the project's region is not the destination's defaultRegion 409 CONFLICT; destination at its project cap 409 QUOTA_EXCEEDED; the source would be left with no project 409 CONFLICT; unknown body field 422. Errors: 401; 403; 404; 409; 422; 500. Idempotency/Concurrency: Idempotency-Key (UUID) is optional (recommended); a replay returns the FIRST move's cut-over instant instead of re-sealing billing. A refused move leaves no idempotency record.

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).

projectId*string

The project id (also the project's scopeId).

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

Body of the project move.

targetSubscriptionId*string

The destination subscription, in the same tenant.

Response Body

The move, completed.

application/json
  1. response

The 200 body of a project move.

projectId*string
fromSubscriptionId*string
toSubscriptionId*string
cutoverAt*string

The instant the project's billing was sealed under the source subscription.

Formatdate-time
billingBoundary*string

Usage hours starting before this instant belong to the source; at or after it, to the destination.

Formatdate-time
operationId*string

The already-SUCCEEDED iam.project.move Operation (audit trail; nothing to poll).

curl -X POST "https://example.com/tenants/string/subscriptions/string/projects/string/actions/move" \  -H "Content-Type: application/json" \  -d '{    "targetSubscriptionId": "string"  }'
{  "projectId": "string",  "fromSubscriptionId": "string",  "toSubscriptionId": "string",  "cutoverAt": "2019-08-24T14:15:22Z",  "billingBoundary": "2019-08-24T14:15:22Z",  "operationId": "string"}