Billing & FinOps

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.

Assign one seat of an entitlement to a resource

POST
/scopes/{scopeId}/billing/entitlements/{entitlementId}/actions/assign

Consumes ONE seat of the entitlement's pool for the given resource, so the licence is recorded as being in use there. An entitlement with quantity: N supports N simultaneous assignments to N DISTINCT resources. Deleting the resource RELEASES the seat and leaves the entitlement active and still billing — the entitlement outlives the resource, which is the whole point of an account-level entitlement. Validation: resourceType must be one of instance|volume|load_balancer; resourceId must be a LIVE resource of the caller's own tenant (another tenant's or a deleted resource is 404 NOT_FOUND, never 403 — the check is row-level security, so a foreign id is indistinguishable from a missing one). 409 CONFLICT when the pool is exhausted, with a message naming the entitlement and its seat count; 409 CONFLICT when this resource already holds a seat of this entitlement; 409 CONFLICT when the entitlement's term has ended. A CANCELLED but in-term entitlement is still assignable. Caller needs billing:write, else 403. Async & state: Synchronous. The seat cap is enforced under a row lock, so the (N+1)th concurrent assignment is refused synchronously rather than queued or silently trimmed. Errors: 401; 403; 404 unknown scope, entitlement or resource; 409 pool exhausted / already assigned / term ended; 422 malformed body; 500. Idempotency/Concurrency: Re-assigning the same resource is a 409, not a silent success.

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

scopeId*string

Opaque ownership+authorization scope resolving to tenant + subscription + project.

entitlementId*string

The subscription-scoped entitlement's id.

Request Body

application/json
  1. body
resourceType*EntitlementResourceType

The kind of resource an entitlement seat can be applied to. Extensible — new kinds (a Kubernetes cluster) are added here without a data migration.

Value in"instance""volume""load_balancer"
resourceId*string

Must be a LIVE resource of the caller's own tenant; anything else is 404.

Response Body

The seat is assigned; the entitlement is returned with updated seat counts.

application/json
  1. response
data*

A subscription-scoped add-on or licence the account HOLDS, independent of any one resource. Unlike an instance-scoped add-on (which is born with a VM and dies with it), an entitlement survives the deletion of every resource it was applied to and can be re-applied elsewhere. quantity is a POOL OF SEATS: an entitlement with quantity: N may be assigned to N DISTINCT resources at the same time. Billing charges quantity units per period whether or not every seat is currently assigned — the customer bought the pool, not the occupancy.

curl -X POST "https://example.com/scopes/string/billing/entitlements/string/actions/assign" \  -H "Content-Type: application/json" \  -d '{    "resourceType": "instance",    "resourceId": "string"  }'
{  "data": {    "id": "string",    "itemKind": "addon",    "itemId": "string",    "itemSlug": "string",    "name": "string",    "period": "hour",    "unitPriceMinor": 0,    "currency": "string",    "sku": "string",    "quantity": 1,    "seatsUsed": 0,    "seatsAvailable": 0,    "state": "active",    "autoRenew": true,    "honoured": true,    "termStartedAt": "2019-08-24T14:15:22Z",    "termEndsAt": "2019-08-24T14:15:22Z",    "renewsAt": "2019-08-24T14:15:22Z",    "createdAt": "2019-08-24T14:15:22Z",    "cancelledAt": "2019-08-24T14:15:22Z",    "expiredAt": "2019-08-24T14:15:22Z",    "assignments": [      {        "id": "string",        "resourceType": "instance",        "resourceId": "string",        "assignedAt": "2019-08-24T14:15:22Z"      }    ],    "assignment": {      "id": "string",      "resourceType": "instance",      "resourceId": "string",      "assignedAt": "2019-08-24T14:15:22Z"    }  }}