Create Usage Limit Plan
Create a reusable Plan and its first draft. Empty rules are allowed until publication.
POST /v1/projects/:project_id/usage-limit-plansAuthentication and scope
Section titled “Authentication and scope”Requires usage_control:write. project_id is the owning project; id (when present) is its Plan ID. The API key supplies the tenant scope. Resources outside that tenant/project are not returned.
Request
Section titled “Request”There are no query parameters.
{ "name": "pro", "title": "Pro daily budget", "description": "Default allowance", "rules": [ { "currency": "USD", "measure": "amount", "selector_type": "all", "period": "day", "limit_amount": "100", "timezone": "UTC", "action": "block", "webhook_event": "usage_limit.exceeded" } ]}| Field | Contract |
|---|---|
name |
Required only on creation; the Plan name cannot be edited. |
title |
Required, nonempty. |
description |
Optional; omission or an empty string clears it. |
rules |
Complete rule array; an empty array can be saved but cannot be published. |
Each rule has this contract:
| Field | Contract |
|---|---|
limit_key |
Omit for a new rule; the server generates it. Echo the original value when editing an existing rule to preserve continuity. |
measure |
Required: amount or quantity. |
selector_type |
Required: all, unit, or metric. |
selector_value |
Required for unit or metric. |
metric_scope |
Optional measurement scope. |
currency |
Required for amount, normalized to uppercase; optional for quantity. |
period |
Required: hour, day, week, month, lifetime, or an anchored duration of at least an hour such as 5h or 2 day. Minutes are unsupported. |
limit_amount |
Required positive decimal amount/quantity; a string is recommended. |
timezone |
Optional IANA timezone for the period. |
action |
Optional limit action, for example block. |
webhook_event |
Optional limit event name. |
Do not submit system-managed root IDs, revision, status, tenant/project IDs, or rule id, plan_version_id, or timestamps.
Response
Section titled “Response”HTTP 201.
{ "id": "ulpv_pro_v1", "tenant_id": "t_001", "project_id": "proj_gateway", "plan_id": "ulp_pro", "name": "pro", "revision": 1, "status": "draft", "title": "Pro daily budget", "description": "Default allowance", "created_at": 1784889000, "updated_at": 1789722000, "rules": [ { "id": "ulpr_budget_v1", "tenant_id": "t_001", "project_id": "proj_gateway", "plan_version_id": "ulpv_pro_v1", "limit_key": "ulrk_budget", "currency": "USD", "measure": "amount", "selector_type": "all", "period": "day", "limit_amount": "100", "timezone": "UTC", "action": "block", "webhook_event": "usage_limit.exceeded", "created_at": 1784890000, "updated_at": 1784890000 } ], "referenced_by_count": 0}Version fields: id (original version ID), tenant_id, project_id, plan_id, name, revision, status, title, optional description, original published_at (omitted for drafts), created_at, Plan updated_at, rules, and referenced_by_count. Detail/list reads can also include has_unpublished_changes and live_revision, derived from actual draft status. Reference counts are populated by detail/list reads; history and mutation responses do not calculate them. Each rule returns the business fields above plus its original id, plan_version_id, ownership, and creation/update timestamps. Empty optional fields may be omitted; timestamps are Unix seconds.
Behavior and errors
Section titled “Behavior and errors”Missing/out-of-scope resources return 404, invalid inputs/lifecycle transitions 400, name/revision conflicts 409, insufficient permission 403, and internal/infrastructure failures 5xx. Failed write transactions leave Plan/history/rules unchanged; cache errors explicitly marked committed are the exception.
Lifecycle and window behavior · Get Usage Limit Plan · Update Usage Limit Plan Draft · Publish Usage Limit Plan · Roll Back Usage Limit Plan · List Usage Limit Plan Revisions