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.
Checkout sessionPOST /orgs/{id}/billing/checkoutpost_org_billing_checkoutBody CheckoutRequestSubscriptionRef.
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")

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