Zorveus LogoZorveusDOCS
Business

Prorate AI allowances on plan upgrades

View Markdown

Set the plan-change policy once and prorate AI allowance increases when customers upgrade.

Proration adjusts the extra AI allowance based on how much of the current cycle is left. Half a cycle left means half the allowance increase

Configure both plan connections with active daily or monthly caps. Use the same period and currency

1. Send the policy

Send the policy on the first request and on later requests while the customer stays on a plan or upgrades. For a downgrade, omit the policy from the switching request; Zorveus does not prorate decreases. Use your app's inference API key

curl https://api.zorveus.com/v1/chat/completions \
	-H "Authorization: Bearer $PLAN_API_KEY" \
	-H "Content-Type: application/json" \
	-H "X-Zorveus-External-User-ID: customer_123" \
	-H "X-Zorveus-Allowance-Change-Policy: prorate_increase" \
	-d '{"model":"YOUR_ALLOWED_MODEL","messages":[{"role":"user","content":"Hello"}]}'

The body value takes precedence over the header. Zorveus records the initial connection without proration

A selected-key allowance read also remembers that connection. Apply a prorated plan change before reading allowance with the new key. The read itself does not apply prorate_increase

Use a native SDK

These calls run on your server. Configure the Pro plan key, select an allowed model, and get the customer ID from your authenticated session

Client SDK / Framework:
import { Zorveus } from "@zorveus/sdk";

const client = new Zorveus({ apiKey: process.env.ZORVEUS_PRO_KEY! });
const response = await client.chat.completions.create({
    model: selectedModelId,
    messages: [{ role: "user", content: "Hello" }],
    zorveusMetadata: {
        externalUserId: authenticatedUserId,
        allowanceChange: "prorate_increase",
    },
});

With a routing key, use the plan alias on the same request as shown in routing keys. Proration is requested by inference metadata or headers, not by a service-client profile upsert

2. Switch the plan's API key

When the customer upgrades, use the API key for the new plan's connection. Keep the same user ID and allowance anchor

A $10 to $50 upgrade increases the allowance by $40. Halfway through the cycle, the customer gets $20 extra:

Current-cycle allowance = $10 + ($50 - $10) × 0.5 = $30
Remaining after $8 used = $30 - $8 = $22

Requests with the same connection reuse the saved allowance. At renewal, the full configured $50 allowance applies

3. Read the remaining allowance

Fetch the product user with your service key:

curl --get https://api.zorveus.com/product-users/by-external-id \
	-H "Authorization: Bearer $SERVICE_API_KEY" \
	--data-urlencode "app_id=$APP_ID" \
	--data-urlencode "external_user_id=customer_123"

Display allowance.available_allowance as the remaining balance. Use allowance.period_end for the renewal date

Complete response for the $10 to $50 upgrade example

The fictional user upgrades on June 16 in a June 1 to July 1 cycle. There are no active reservations or promotional credits

{
	"product_end_user_id": "peu_example",
	"org_id": "org_example",
	"app_id": "app_example",
	"external_user_id": "customer_123",
	"display_name": "Example user",
	"email_hash": null,
	"status": "active",
	"metadata": {
		"plan": "business"
	},
	"allowance_starts_at": "2026-06-01T00:00:00Z",
	"last_app_connection_id": "connection_business",
	"usage": {
		"this_period": {
			"sell_cost": "8.000000000000",
			"input_tokens": 1000,
			"output_tokens": 500,
			"total_tokens": 1500,
			"request_count": 1
		},
		"period_start": "2026-06-01T00:00:00Z",
		"period_end": "2026-07-01T00:00:00Z",
		"total": {
			"sell_cost": "8.000000000000",
			"input_tokens": 1000,
			"output_tokens": 500,
			"total_tokens": 1500,
			"request_count": 1
		}
	},
	"cap": {
		"source": "app_connection",
		"cap_rule_id": "cap_business",
		"amount": "50.000000000000",
		"currency": "USD",
		"period": "monthly",
		"spent_this_period": "8.000000000000",
		"period_start": "2026-06-01T00:00:00Z",
		"period_end": "2026-07-01T00:00:00Z",
		"reset_at": "2026-07-01T00:00:00Z",
		"status": "active",
		"updated_at": "2026-06-01T00:00:00Z"
	},
	"direct_cap": null,
	"credits": {
		"currency": "USD",
		"available_credits": "0.000000000000",
		"active_grant_count": 0,
		"expiring_soon_amount": "0.000000000000",
		"spent_this_month": "0.000000000000",
		"spent_total": "0.000000000000",
		"last_grant_at": null,
		"last_used_at": null
	},
	"allowance": {
		"app_connection_id": "connection_business",
		"cap_source": "app_connection",
		"cap_rule_id": "cap_business",
		"credit_mode": "enforce_if_present",
		"overrun_policy": "limit_output",
		"currency": "USD",
		"period": "monthly",
		"period_start": "2026-06-01T00:00:00Z",
		"period_end": "2026-07-01T00:00:00Z",
		"cap_amount": "30.000000000000",
		"spent_this_period": "8.000000000000",
		"remaining_base_allowance": "22.000000000000",
		"available_credits": "0.000000000000",
		"available_allowance": "22.000000000000",
		"adjustment": {
			"type": "prorate_increase",
			"configured_cap_amount": "50.000000000000",
			"effective_at": "2026-06-16T00:00:00Z"
		}
	}
}

Your app still handles subscription payments. See the proration reference for supported changes, response fields, and audit history

Was this page helpful?
Edit this page on GitHub

On this page