Enforce Entitlements
Check or atomically consume a subject's plan quota.
First create a meter, add it as a plan limit, assign a subject to the plan, and
create an API key with plans:read and usage:write.
Use atomic consumption for product actions that must remain correct under concurrency. Use a separate check for previews and advisory UI; quota can change between a check and a later usage write.
Atomically Consume Quota
POST /v1/entitlements/consume decides and records in one transaction. Give
every product action a stable idempotency key so network retries return the
original decision without consuming twice.
curl -X POST "$BASE_URL/v1/entitlements/consume" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"idempotency_key": "api-call-001",
"subject": "org_123",
"meter": "api_calls",
"quantity": 1
}'The response contains accepted, replayed, the recorded event when accepted,
and the quota decision. A hard limit returns HTTP 429 without recording usage
when the projected value exceeds the limit. An advisory limit accepts the event
and reports the warning or exceeded state.
Open Spanner persists accepted and rejected decisions. Reusing an idempotency key returns its original result even if quota later resets. Generate a new key only for a new product action.
Preview Availability
POST /v1/entitlements/check evaluates without recording usage:
curl -X POST "$BASE_URL/v1/entitlements/check" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"subject": "org_123",
"meter": "api_calls",
"quantity": 1
}'| Field | Meaning |
|---|---|
allowed | Whether the requested quantity fits the active policy. |
state | ok, warning, exceeded, no_plan, or not_in_plan. |
current | Usage already recorded in the active period. |
remaining | Units remaining after the requested quantity. |
plan_name | Plan used for the decision. |
from / to | UTC quota period. |
warning still allows usage. exceeded, no_plan, and not_in_plan deny it.
If a preview is allowed, record the accepted action with POST /v1/usages and a
stable idempotency key.
Failure Policy
Use failure_policy: fail_open when preserving usage facts is more important
than enforcing quota during an evaluation failure. Use fail_closed when the
action must be rejected unless quota can be verified. The defaults are advisory
enforcement and fail_open.
Read Progress And Decisions
curl "$BASE_URL/v1/plans/subjects/org_123/progress" \
-H "Authorization: Bearer $API_KEY"
curl "$BASE_URL/v1/entitlements/states?subject=org_123&meter=api_calls" \
-H "Authorization: Bearer $API_KEY"
curl "$BASE_URL/v1/entitlements/decisions?subject=org_123&meter=api_calls" \
-H "Authorization: Bearer $API_KEY"Progress is useful for customer-facing quota views. State events show warning and exceeded transitions. Decision history provides an immutable audit of accepted, rejected, and replayed consumption attempts.
Language-specific consume, check, progress, and decision clients are documented
under SDKs. Runnable examples live in
examples/rest/advance/entitlement-check and
examples/stream/advance/entitlement-gate.