Skip to content
OAOpenAppPhysical Security as a Service
Login

Billing

The Billing OpenAPI tag covers catalog plans, per-organization subscription surfaces (/orgs/{id}/billing/...), operator quota overrides (/admin/quota_overrides), and provider webhooks (POST /billing/webhooks/{provider} with application/octet-stream raw bodies). Shapes include PlansResponse, BillingPlanResponse, QuotaReport, CheckoutRequest / SubscriptionRef, PortalRequest / PortalResponse, QuotaOverrideRequest, BillingWebhookResponse — see the API reference.

Auth: Many routes omit an explicit security block in the published bundle; assume bearer_auth where your gateway applies API keys, and treat /admin/... as operator-only in production. Webhook posts are usually verified by provider signatures at the edge, not end-user SDK keys.

Org context: Org-scoped billing routes encode the organization id in the path (/orgs/{id}/billing/...); they do not use X-Org in the canonical YAML (unlike Devices lists).

ConcernHTTPoperationIdNotes
Plan catalogGET /plansget_plansPlansResponse.
Current planGET /orgs/{id}/billing/planget_org_billing_planBillingPlanResponse.
Upgrade optionsGET /orgs/{id}/billing/upgrade-optionsget_org_billing_upgrade_optionsPlansResponse.
Usage / quotasGET /orgs/{id}/billing/usageget_org_billing_usageQuotaReport. Each QuotaUsage carries a machine-readable unit (count or seconds); the response also includes an optional degradation block when the org is over capacity.
Degradation statusGET /orgs/{id}/billing/degradationget_org_billing_degradationDegradationStatus — stage, friction level, overages, flagged resources, selection policy. Requires billing:read.
Selection policyPUT /orgs/{id}/billing/degradation/policyput_org_billing_degradation_policyBody SetSelectionPolicyRequestDegradationStatus. Requires billing:manage.
Keep/drop a resourcePOST /orgs/{id}/billing/degradation/resourcepost_org_billing_degradation_resourceBody SetResourceKeepRequestDegradationStatus. Pin which excess resources survive a downgrade. Requires billing:manage.
Checkout sessionPOST /orgs/{id}/billing/checkoutpost_org_billing_checkoutBody CheckoutRequestSubscriptionRef. A downgrade below current usage is allowed (new creates are blocked and excess resources are wound down); an unknown/unpublished tier returns 400 unknown_tier.
Customer portal URLPOST /orgs/{id}/billing/portalpost_org_billing_portalBody PortalRequestPortalResponse. 501 if the provider has no portal.
Quota overrides (admin)GET / POST /admin/quota_overridesget_admin_quota_overrides, post_admin_quota_overrideQuotaOverrideRequest on POST.
Provider webhookPOST /billing/webhooks/{provider}post_billing_webhookRaw application/octet-stream body; BillingWebhookResponse. Normally called by the billing provider, not app code.
SurfacePython / Rust (openapp_sdk)GoTypeScript (AsyncClient)
Named sub-clientNot shipped — call paths via the core bridge (AsyncClient._request in Python, transport() + RequestSpec in Rust)Full BillingAPIServiceNot on façade

Go returns typed JSON for most billing calls; GetAdminQuotaOverrides / PostAdminQuotaOverride return raw http.Response (decode yourself). PostBillingWebhook expects an os.File (or compatible stream) for the octet-stream body.

401 / 403 when the caller lacks billing or org permissions. post_org_billing_portal may return 501. Provider errors follow ApiErrorResponse where returned — see Errors & retries.

There is no client.billing yet — use the internal JSON dispatcher on AsyncClient (same transport as sub-clients):

plans = await client._request("GET", "/plans")
plan = await client._request("GET", f"/orgs/{org_id}/billing/plan")

Org billing usage (GET /orgs/{id}/billing/usage)

Section titled “Org billing usage (GET /orgs/{id}/billing/usage)”

Returns a QuotaReport (per-key usage vs limits for the org).

usage = await client._request("GET", f"/orgs/{org_id}/billing/usage")

Over-capacity degradation status (GET /orgs/{id}/billing/degradation)

Section titled “Over-capacity degradation status (GET /orgs/{id}/billing/degradation)”

Returns a DegradationStatus — lifecycle stage, continuous degradation_level (0–1 friction factor), over_capacity, the active selection_policy, per-key overages, and the list of flagged resources. Requires billing:read. Only meaningful when the over-capacity lifecycle is enabled server-side; otherwise the org reports stage: "none". See Quotas & plan limits for the behavior this drives.

status = await client._request("GET", f"/orgs/{org_id}/billing/degradation")

Set the excess-selection policy (PUT /orgs/{id}/billing/degradation/policy)

Section titled “Set the excess-selection policy (PUT /orgs/{id}/billing/degradation/policy)”

Body SetSelectionPolicyRequestpolicy is one of newest_first, oldest_first, least_recently_used, manual. Chooses which excess resources are wound down first when the org is over capacity. Returns the refreshed DegradationStatus. Requires billing:manage.

status = await client._request(
"PUT",
f"/orgs/{org_id}/billing/degradation/policy",
{"policy": "least_recently_used"},
)

Pin or drop a specific resource (POST /orgs/{id}/billing/degradation/resource)

Section titled “Pin or drop a specific resource (POST /orgs/{id}/billing/degradation/resource)”

Body SetResourceKeepRequestresource (e.g. devices, integrations, zones, entities, api_keys), resource_id, and keep (true pins it as a survivor, false releases it back to the policy). Returns the refreshed DegradationStatus. Requires billing:manage.

status = await client._request(
"POST",
f"/orgs/{org_id}/billing/degradation/resource",
{"resource": "devices", "resource_id": device_id, "keep": True},
)

Org upgrade options (GET /orgs/{id}/billing/upgrade-options)

Section titled “Org upgrade options (GET /orgs/{id}/billing/upgrade-options)”

Eligible upgrade tiers for the org (same PlansResponse shape as the public catalog).

options = await client._request("GET", f"/orgs/{org_id}/billing/upgrade-options")

Start checkout (POST /orgs/{id}/billing/checkout)

Section titled “Start checkout (POST /orgs/{id}/billing/checkout)”

Body CheckoutRequest — required tier_slug (see OpenAPI). Response SubscriptionRef.

sub = await client._request(
"POST",
f"/orgs/{org_id}/billing/checkout",
{"tier_slug": "pro"},
)

Customer billing portal URL (POST /orgs/{id}/billing/portal)

Section titled “Customer billing portal URL (POST /orgs/{id}/billing/portal)”

Body PortalRequest with return_url. Response PortalResponse (url). 501 when the provider exposes no self-service portal — see Typical errors.

portal = await client._request(
"POST",
f"/orgs/{org_id}/billing/portal",
{"return_url": "https://myapp.example/billing-return"},
)

List quota overrides (operator) (GET /admin/quota_overrides)

Section titled “List quota overrides (operator) (GET /admin/quota_overrides)”

Operator-only — requires privileges your deployment maps to this route. The published 200 response has no fixed schema in the bundle; treat the body as JSON and decode it in your process.

overrides = await client._request("GET", "/admin/quota_overrides")

Create or update quota override (operator) (POST /admin/quota_overrides)

Section titled “Create or update quota override (operator) (POST /admin/quota_overrides)”

Body QuotaOverrideRequestsubject_type, subject_id, quota_key, limit_value are required; expires_at, period, reason optional (see OpenAPI).

await client._request(
"POST",
"/admin/quota_overrides",
{
"subject_type": "org",
"subject_id": org_id,
"quota_key": "scripting_executions",
"limit_value": 10_000,
"reason": "support escalation",
},
)

Provider webhook (POST /billing/webhooks/{provider})

Section titled “Provider webhook (POST /billing/webhooks/{provider})”

Normally invoked by the billing provider, not your application SDK — verify signatures at the edge. Payload is raw application/octet-stream.

Prefer the provider’s HTTP target in infrastructure. If you must forward bytes through core-backed HTTP, use httpx / aiohttp with your API base URL, Authorization, Content-Type: application/octet-stream, and the raw webhook body — do not run this on the public SDK façade unless you accept binary handling limits.

Org CRUD and membership are documented under Organizations. For quota keys referenced in usage reports, see QuotaKey in OpenAPI (for example scripting_executions on Scripting).