import type { Wallet, Plan, PricingStrategy, TenantPricingOverride, IsvPricingOverride, WholesaleAgreement, SettlementStatement, Settlement, FeatureDefinition, PlanFeatureAllocation, FeatureUsage, UsageEvent, CompositeOperation, Subscription, Application } from "../_internal/types.gen"; import type { RequestOptions } from "../base-client"; import { RequestBuilder } from "../request-builder"; /** * Attributes for creating a subscription plan. * * @example * ```typescript * // Free tier (under platform ceiling of 1000 req/min). * await admin.billing.plans.create({ * name: "Free", * slug: "free", * monthly_price: { amount: "0.00", currency: "USD" }, * monthly_credits: 0, * rate_limit_requests: 100, * rate_limit_period_seconds: 60, * }); * * // Pro tier (paid; no platform ceiling). * await admin.billing.plans.create({ * name: "Pro", * slug: "pro", * monthly_price: { amount: "49.00", currency: "USD" }, * monthly_credits: 10_000, * rate_limit_requests: 10_000, * rate_limit_period_seconds: 60, * concurrent_operations_limit: 25, * }); * * // Per-customer override (tightening one tenant below their plan's default). * await admin.billing.subscriptions.setRateLimitOverrides(subscriptionId, { * rate_limit_requests_override: 50, * rate_limit_period_seconds_override: 60, * }); * ``` */ export type CreatePlanAttributes = { name: string; slug: string; monthly_price: { amount: string; currency: string; }; monthly_credits: number; capability_tiers?: string[]; is_addon?: boolean; /** * Credits allocated per seat at renewal for seat-type plans. * When set, renewal allocates `credits_per_seat × active_seat_count` credits. * Ignored for non-seat plans. */ credits_per_seat?: number; /** * Per-plan request-count ceiling for the `:tenant_plan` HammerRateLimit * scope. Tenants on this plan can make up to this many requests per * `rate_limit_period_seconds`. Nullable — when `null` or omitted, the * plug falls back to the next link in the resolution chain * (per-ApiKey override, then plug-static default). * * Must be `>= 1` when set. Zero-priced plans (free tier) are additionally * capped at the platform-set ceiling * (`config :gpt_core, :platform_free_tier_max_rpm`, default 1000). Exceeding * the ceiling on a free-tier plan returns * `422 :free_tier_rate_limit_exceeds_platform_ceiling`. */ rate_limit_requests?: number | null; /** * Window in seconds for `rate_limit_requests`. Must be `>= 1` when set. * Typical: `60` (per minute), `3600` (per hour). Nullable — falls through * the same resolution chain as `rate_limit_requests`. */ rate_limit_period_seconds?: number | null; /** * Maximum number of concurrent in-flight billable operations per tenant. * Attribute is accepted and persisted for future enforcement; runtime * enforcement is NOT in scope today (only `rate_limit_requests` / * `rate_limit_period_seconds` drive the live plug). Must be `>= 1` when set. */ concurrent_operations_limit?: number | null; }; /** * Attributes for updating a subscription plan. * * Extends `CreatePlanAttributes` with two optional acknowledgement arguments * threaded through Phase 3 of the plan-versioning pin-policy work: * * - `ack_plan_revision` — set `true` to acknowledge that this edit changes * pricing-relevant attributes on a `Plan` with active subscribers. Without * it, the API returns `422 :plan_edit_affects_subscribers` and refuses the * edit (warn-then-confirm gate). Existing subscribers stay pinned to their * original snapshot regardless — the gate exists so the ISV can confirm the * change is intentional and accept that NEW subscribers will receive the * updated terms. * - `reason` — required when `ack_plan_revision: true`. Free-form string ≤ 280 * chars recorded on the `audit:plan_revised_with_active_subscribers` audit * row alongside actor + counts. * * Pass neither when editing a Plan with zero active subscribers — the edit * proceeds normally. */ export type UpdatePlanAttributes = Partial & { /** * Acknowledge that this edit affects existing subscribers' Plan revision. * Required when the Plan has ≥ 1 active subscriber AND the edit changes any * pricing-relevant attribute. See the type description for details. */ ack_plan_revision?: boolean; /** * Free-form reason for the edit (≤ 280 chars). Required when * `ack_plan_revision: true`; recorded on the * `audit:plan_revised_with_active_subscribers` audit row. */ reason?: string; }; /** Attributes for creating a pricing strategy. */ export type CreatePricingStrategyAttributes = { service_id: string; metric?: string; floor_price: { amount: string; currency: string; }; margin_percent?: number; }; /** Attributes for creating a tenant pricing override. */ export type CreateTenantPricingOverrideAttributes = { service_id: string; tenant_id: string; application_id: string; floor_price: { amount: string; currency: string; }; margin_percent?: number; expires_at?: string; reason: string; }; /** Attributes for creating a wholesale agreement. */ export type CreateWholesaleAgreementAttributes = { isv_tenant_id: string; settlement_frequency?: "monthly" | "weekly" | "daily"; hold_days?: number; minimum_payout_cents?: number; permitted_capability_tiers?: Array<"core" | "standard" | "premium">; overdraft_limit_credits?: number | null; per_seat_fee_cents?: number | null; refund_reversal_days?: number | null; /** * Per-ISV one-time signup-grant amount in credits, deposited to the * `Platform:Application:*` wholesale account when the ISV-tenant's first * Application is created (after proof-of-life passes). Pass `null` (or omit) * to fall back to the platform default * (`config :gpt_core, :default_isv_signup_grant_credits`). */ signup_grant_credits?: number | null; minimum_retail_floors?: Array<{ service_id: string; minimum: { amount: string; currency: string; }; }>; layer1_dunning_config?: Record | null; notes?: string | null; effective_date?: string | null; }; /** Shape returned by `wholesaleAgreements.grantSignupCredits` and `getSignupGrantStatus`. */ export type SignupGrantStatus = { id?: string; isv_tenant_id?: string; application_id?: string; status?: "pending" | "granted" | "insufficient_proof_of_life"; credits?: number | null; source?: "default" | "pre_seeded"; proof_of_life_path?: "pre_seeded" | "admin_manual" | "email_plus_card" | "unknown" | null; granted_at?: string | null; reason?: string | null; }; /** Attributes for creating a platform-managed ISV pricing override. */ export type CreateIsvPricingOverrideAttributes = { application_id: string; operation_key: string; rate_credits?: number | null; margin_percent?: number | null; is_enabled?: boolean | null; notes?: string | null; }; /** Attributes accepted when updating a platform-managed ISV pricing override. */ export type UpdateIsvPricingOverrideAttributes = Pick; /** Attributes for initiating a settlement. */ export type CreateSettlementAttributes = { period_start: string; period_end: string; isv_tenant_id: string; }; /** Attributes for creating a feature definition. */ export type CreateFeatureDefinitionAttributes = { key: string; name: string; metering_mode: "unlimited" | "counted" | "credit_cost"; default_limit?: number; credit_cost?: number; platform_capability?: string; metadata?: Record; }; /** Attributes for creating a plan-feature allocation. */ export type CreatePlanFeatureAllocationAttributes = { plan_id: string; feature_definition_id: string; enabled?: boolean; limit?: number; credit_cost?: number; activation_cost?: number; }; /** * Admin billing namespace — wallet management, plans, pricing, and wholesale economics. * * Accessed via `admin.billing.*`. All operations require `sk_srv_` or `sk_sys_` API keys. * These bypass tenant-level authorization and are for platform admin use only. */ export declare function createBillingNamespace(rb: RequestBuilder): { wallet: { /** * Fetch the wallet for the current authenticated context. * * @param options - Optional request-level overrides. * @returns A promise resolving to the {@link Wallet}. * * @example * ```typescript * const admin = new GptAdmin({ apiKey: 'sk_srv_...' }); * const wallet = await admin.billing.wallet.get(); * console.log(`Balance: ${wallet.attributes?.balance_credits} credits`); * ``` */ get: (options?: RequestOptions) => Promise; /** * Change the subscription plan on the wallet. * * Upgrades charge a prorated amount immediately against the default payment * method. Downgrades are deferred to the end of the current billing period. * * @param walletId - The wallet UUID from `wallet.get()`. * @param planSlug - The slug of the target plan (e.g. `"pro-monthly"`). * @param options - Optional request-level overrides. * @returns A promise resolving to the updated {@link Wallet}. * * @example * ```typescript * const admin = new GptAdmin({ apiKey: 'sk_srv_...' }); * const wallet = await admin.billing.wallet.get(); * await admin.billing.wallet.changePlan(wallet.id as string, 'enterprise-annual'); * ``` */ changePlan: (walletId: string, planSlug: string, options?: RequestOptions) => Promise; /** * Purchase a credit package ("credit-package") for the wallet. * * Application owners can author the credit-package catalog through the * platform API; this admin wallet helper consumes an existing package by * slug for top-ups. * * @param walletId - The wallet UUID from `wallet.get()`. * @param packageSlug - The slug of the credit package to purchase. * @param paymentMethodId - Optional payment method UUID. Uses the default if omitted. * @param options - Optional request-level overrides. * @returns A promise resolving to the updated {@link Wallet}. * * @example * ```typescript * const admin = new GptAdmin({ apiKey: 'sk_srv_...' }); * const wallet = await admin.billing.wallet.get(); * await admin.billing.wallet.adjustCredits(wallet.id as string, 'starter-1000'); * ``` */ adjustCredits: (walletId: string, packageSlug: string, paymentMethodId?: string, options?: RequestOptions) => Promise; /** * Get credit usage history for the wallet. * * @param tenantId - Optional tenant ID to scope the usage query. * @param options - Optional request-level overrides. * @returns A promise resolving to a {@link Wallet} with usage data. * * @example * ```typescript * const admin = new GptAdmin({ apiKey: 'sk_srv_...' }); * const usage = await admin.billing.wallet.getUsage('tenant_abc123'); * ``` */ getUsage: (tenantId?: string, options?: RequestOptions) => Promise; }; /** * Plan management — create, read, update, delete subscription plans available to tenants. * * Plans define subscription tiers with monthly prices, credit grants, storage quotas, * and capability tiers. ISVs configure their plan catalogue here. */ plans: { /** * List all plans for the application. * * @param options - Optional request options. * @returns Array of `Plan` objects. */ list: (options?: RequestOptions) => Promise; /** * Get a plan by ID. * * @param planId - The plan UUID. * @param options - Optional request options. * @returns The matching `Plan`. */ get: (planId: string, options?: RequestOptions) => Promise; /** * Create a new plan. * * @param attrs - Plan attributes (name, slug, monthly_price, monthly_credits, etc.) * @param options - Optional request options. * @returns The newly created `Plan`. * * @example * ```typescript * const plan = await admin.billing.plans.create({ * name: "Pro", * slug: "pro", * monthly_price: { amount: "49.00", currency: "USD" }, * monthly_credits: 10000, * }); * ``` */ create: (attrs: CreatePlanAttributes, options?: RequestOptions) => Promise; /** * Update an existing plan. * * When the Plan has ≥ 1 active subscriber AND the edit changes any * pricing-relevant attribute (`monthly_price`, `monthly_credits`, * `billing_interval`, `capability_tiers`, `plan_tier`, seats/storage * limits, `credits_per_seat`), the API returns `422 * :plan_edit_affects_subscribers` unless the caller passes * `ack_plan_revision: true` + a `reason` string. Existing subscribers * always remain pinned to their original snapshot — the gate exists so * the ISV explicitly confirms the change is intentional and accepts * that NEW subscribers will receive the updated terms. * * @param planId - The plan UUID. * @param attrs - Attributes to update. Pass `ack_plan_revision: true` + * `reason` when editing a Plan with active subscribers. * * @example * ```typescript * // Routine edit on a plan without active subscribers — no ack needed. * await admin.billing.plans.update(planId, { name: 'Pro (renamed)' }); * * // Pricing edit on a plan with active subscribers — ack required. * await admin.billing.plans.update(planId, { * monthly_price: { amount: '29.00', currency: 'USD' }, * ack_plan_revision: true, * reason: 'Raising headline price to match competitive market rates.', * }); * ``` */ update: (planId: string, attrs: UpdatePlanAttributes, options?: RequestOptions) => Promise; /** Delete a plan by ID. */ delete: (planId: string, options?: RequestOptions) => Promise; /** * Transition an `:active` plan to `:deprecated`. * * Deprecated plans are hidden from public catalogs and reject new * subscriptions, but existing subscribers continue renewing on this * plan. Use this before scheduling a sunset to stop new sign-ups while * giving existing subscribers a graceful runway. * * Rejected when the plan is not currently `:active`. * * Requires Platform Admin or Application Owner role. * * @param planId - UUID of the plan to deprecate. * @param options - Optional request-level overrides. * @returns The updated `Plan` with `lifecycle_status: "deprecated"`. * * @example * ```typescript * const admin = new GptAdmin({ apiKey: 'sk_sys_...' }); * * // Full plan lifecycle: * // 1. Stop new sign-ups while existing subscribers keep their plan. * const deprecated = await admin.billing.plans.deprecatePlan(planId); * * // 2. Later, when ready to retire the plan entirely: * await admin.billing.plans.scheduleSunset( * planId, * '2026-12-01T00:00:00Z', * replacementPlanId, * ); * * // 3. PlanSunsetWorker force-migrates remaining subscribers at sunset_at, * // then transitions the plan to :archived automatically. * const archived = await admin.billing.plans.listPlansByLifecycleStatus( * appId, * 'archived', * ); * ``` */ deprecatePlan: (planId: string, options?: RequestOptions) => Promise; /** * Schedule a plan for sunset. * * At `sunsetAt`, remaining subscribers will be force-migrated to * `replacementPlanId` by the `PlanSunsetWorker` (hourly cron). The plan * transitions to `:sunset_pending` immediately. When migration completes, * the worker transitions the plan to `:archived`. * * Constraints: * - The plan must be `:active` or `:deprecated`. * - `sunsetAt` must be at least 1 hour in the future. * - `replacementPlanId` is **required** when the plan has active * subscribers (no-orphan-subscribers invariant). When provided, it * must reference an `:active` Plan in the same Application. * * Subscribers receive 30 / 7 / 1-day countdown email reminders leading up * to `sunsetAt` (the schedule itself is communicated via the * `billing.plan.sunset_scheduled` webhook fired by this action). * * Requires Platform Admin or Application Owner role. * * @param planId - UUID of the plan to schedule for sunset. * @param sunsetAt - ISO-8601 timestamp at which subscribers are * force-migrated (must be ≥ 1 hour in the future). * @param replacementPlanId - UUID of the replacement plan. Required * when active subscribers remain on the plan; optional otherwise. * @param options - Optional request-level overrides. * @returns The updated `Plan` with `lifecycle_status: "sunset_pending"`. */ scheduleSunset: (planId: string, sunsetAt: string, replacementPlanId?: string, options?: RequestOptions) => Promise; /** * Transition a `:sunset_pending` plan to `:archived`. * * This is a terminal state. The action is rejected if any active * subscribers remain on the plan — typically `PlanSunsetWorker` calls * this automatically after force-migration completes, but it can be * invoked manually if all subscribers have already moved off the plan * by other means. * * Requires Platform Admin or Application Owner role. * * @param planId - UUID of the plan to archive. * @param options - Optional request-level overrides. * @returns The updated `Plan` with `lifecycle_status: "archived"`. */ archivePlan: (planId: string, options?: RequestOptions) => Promise; /** * List plans for an application, optionally scoped to a lifecycle stage. * * Sends a filtered `GET /admin/plans?filter[application_id]=…&filter[lifecycle_status]=…` * request. Useful for surfacing only `:active` plans in a pricing page, * auditing `:archived` plans, or watching `:sunset_pending` plans. * * @param applicationId - UUID of the application to scope to. * @param lifecycleStatus - Optional lifecycle filter. Omit to list all * plans regardless of lifecycle stage. * @param options - Optional request-level overrides. * @returns Array of matching `Plan` objects. * * @example * ```typescript * const active = await admin.billing.plans.listPlansByLifecycleStatus( * appId, * 'active', * ); * const pending = await admin.billing.plans.listPlansByLifecycleStatus( * appId, * 'sunset_pending', * ); * ``` */ listPlansByLifecycleStatus: (applicationId: string, lifecycleStatus?: "active" | "deprecated" | "sunset_pending" | "archived", options?: RequestOptions) => Promise; }; /** * Pricing strategy management — configure per-service floor prices and margins * for your application. These are the Tier 2 prices in the 5-tier pricing resolution. */ pricingStrategies: { /** * List all pricing strategies for the application. * * @param options - Optional request options. * @returns Array of `PricingStrategy` objects. */ list: (options?: RequestOptions) => Promise; /** * Get a pricing strategy by ID. * * @param id - The pricing strategy UUID. * @param options - Optional request options. * @returns The matching `PricingStrategy`. */ get: (id: string, options?: RequestOptions) => Promise; /** * Create a pricing strategy for a service. * * @param attrs - Strategy attributes: `service_id`, `metric`, `floor_price`, `margin_percent`. * The `floor_price` cannot be below the ISV minimum retail floor set in the WholesaleAgreement. */ create: (attrs: CreatePricingStrategyAttributes, options?: RequestOptions) => Promise; /** * Update a pricing strategy. * * @param id - The pricing strategy UUID. * @param attrs - Attributes to update (`floor_price`, `margin_percent`). */ update: (id: string, attrs: Partial, options?: RequestOptions) => Promise; }; /** * Tenant pricing override management — set per-tenant, per-service custom prices. * These are Tier 1 in the 5-tier pricing resolution (highest priority). * * Use for enterprise contracts, volume discounts, and promotional pricing. * Always provide a `reason` for audit trail purposes. */ tenantPricingOverrides: { /** * List all tenant pricing overrides for the application. * * @param options - Optional request options. * @returns Array of `TenantPricingOverride` objects. */ list: (options?: RequestOptions) => Promise; /** * Get a tenant pricing override by ID. * * @param id - The tenant pricing override UUID. * @param options - Optional request options. * @returns The matching `TenantPricingOverride`. */ get: (id: string, options?: RequestOptions) => Promise; /** * Create a tenant-specific pricing override. * * @param attrs - Override attributes: `service_id`, `tenant_id`, `application_id`, * `floor_price`, `margin_percent`, `expires_at`, `reason`. * The `reason` field is required for audit compliance. */ create: (attrs: CreateTenantPricingOverrideAttributes, options?: RequestOptions) => Promise; /** * Update a tenant pricing override. * * @param id - The override UUID. * @param attrs - Attributes to update (`floor_price`, `margin_percent`, `expires_at`, `reason`). */ update: (id: string, attrs: Partial, options?: RequestOptions) => Promise; /** * Delete a tenant pricing override. The tenant's pricing reverts to the * PricingStrategy (or platform default) immediately. * * @param id - The override UUID to delete. */ delete: (id: string, options?: RequestOptions) => Promise; }; /** * Wholesale agreement management — configure the economic relationship between * your ISV account and the platform. Defines take rates, minimum retail floors, * and settlement terms. * * Wholesale agreements are typically configured once during ISV onboarding and * updated only when contract terms change. */ wholesaleAgreements: { /** List all wholesale agreements for the ISV account. */ list: (options?: RequestOptions) => Promise; /** Get a wholesale agreement by ID. */ get: (id: string, options?: RequestOptions) => Promise; /** * Create a wholesale agreement. * * @param attrs - Agreement attributes: `model` (`"percentage"` or `"interchange_plus"`), * `take_rate_percent`, `minimum_retail_floors`, `settlement_frequency`, etc. */ create: (attrs: CreateWholesaleAgreementAttributes, options?: RequestOptions) => Promise; /** * Update a wholesale agreement. * * @param id - The wholesale agreement UUID. * @param attrs - Attributes to update. */ update: (id: string, attrs: Partial, options?: RequestOptions) => Promise; /** * Issue a Platform-Admin manual signup-grant on the wholesale account. * * Normally the signup grant fires automatically on the ISV-tenant's first * Application creation via `IsvSignupGrantProvisioner`. This method is the * explicit manual override — useful when sales is onboarding an ISV outside * the automatic proof-of-life path, or when granting promotional credits. * * The grant is recorded as a `PlatformUsageEvent` row with * `operation_type: "signup_grant"` and `reason` persisted on metadata. * Re-running this method is NOT idempotent — every call fires a fresh * grant. * * Requires a `sk_sys_` platform-admin API key. * * @param id - The wholesale agreement UUID. * @param credits - Grant amount in credits (must be positive). * @param reason - Optional free-form rationale (≤ 280 chars) — persisted * on the resulting `PlatformUsageEvent.metadata` for auditability. * * @example * ```typescript * const admin = new GptAdmin({ apiKey: 'sk_sys_...' }); * await admin.billing.wholesaleAgreements.grantSignupCredits( * 'wa-uuid', * 25_000, * 'sales-onboarding promo Q3-2026', * ); * ``` */ grantSignupCredits: (id: string, credits: number, reason?: string, options?: RequestOptions) => Promise; /** * Read the current signup-grant state for a wholesale agreement. * * Returns the grant lifecycle status (`pending` / `granted` / * `insufficient_proof_of_life`), the configured credit amount, the * resolved proof-of-life path, and (when granted) the timestamp of the * most recent grant. * * Requires a `sk_sys_` platform-admin API key. * * @param id - The wholesale agreement UUID. * * @example * ```typescript * const status = await admin.billing.wholesaleAgreements.getSignupGrantStatus('wa-uuid'); * if (status.status === 'granted') { * console.log(`Granted ${status.credits} credits at ${status.granted_at}`); * } * ``` */ getSignupGrantStatus: (id: string, options?: RequestOptions) => Promise; }; /** * ISV pricing override management — platform-owned per-application Schedule A * operation overrides. These are Layer 1 economics and use operation keys * from platform pricing config, not tenant-facing feature keys. */ isvPricingOverrides: { /** List all platform-managed ISV pricing overrides. */ list: (options?: RequestOptions) => Promise; /** Get a platform-managed ISV pricing override by ID. */ get: (id: string, options?: RequestOptions) => Promise; /** Create a platform-managed ISV pricing override. */ create: (attrs: CreateIsvPricingOverrideAttributes, options?: RequestOptions) => Promise; /** Update mutable fields on a platform-managed ISV pricing override. */ update: (id: string, attrs: UpdateIsvPricingOverrideAttributes, options?: RequestOptions) => Promise; }; /** * Settlement statement management — Layer 1 platform-to-ISV statements. * * These are distinct from legacy `settlements`; statements are the auditable * period documents generated from immutable platform usage events. */ settlementStatements: { /** List all settlement statements. */ list: (options?: RequestOptions) => Promise; /** Get a settlement statement by ID. */ get: (id: string, options?: RequestOptions) => Promise; /** Mark a settlement statement paid. */ markPaid: (id: string, options?: RequestOptions) => Promise; /** Mark a settlement statement reconciled. */ markReconciled: (id: string, options?: RequestOptions) => Promise; /** Mark a settlement statement disputed. */ markDisputed: (id: string, options?: RequestOptions) => Promise; }; /** * Settlement management — view and initiate ISV revenue settlements. * * The platform calculates net position (retail collected minus wholesale owed) * and releases settlements based on your WholesaleAgreement terms. */ settlements: { /** List all settlements for the ISV account. */ list: (options?: RequestOptions) => Promise; /** Get a settlement by ID. */ get: (id: string, options?: RequestOptions) => Promise; /** * Initiate a settlement calculation for a given period. * * @param attrs - Settlement attributes: `period_start`, `period_end`, `isv_tenant_id`. */ create: (attrs: CreateSettlementAttributes, options?: RequestOptions) => Promise; }; /** * Account credit management — grant promotional or purchased credits to tenant applications. * * Use this for: * - Onboarding bonuses * - Service credits (compensation for downtime) * - Referral rewards * - Marketing campaigns */ accounts: { /** * Grant credits to an application (and its tenants). * * @param applicationId - The application UUID. * @param opts - Credit grant options: `amount` (integer credits), `tenant_id`, * and optional `description`. * * @example * ```typescript * // Apology credits — permanent, no expiry * await admin.billing.accounts.grantCredits(applicationId, { * amount: 10000, * tenant_id: 'tenant_abc123', * description: 'Service incident 2026-03-04 compensation', * }); * * // Promotional trial credits * await admin.billing.accounts.grantCredits(applicationId, { * amount: 25000, * tenant_id: 'tenant_abc123', * }); * ``` */ grantCredits: (applicationId: string, opts: { amount: number; tenant_id: string; description?: string | null; }, options?: RequestOptions) => Promise; }; /** * Feature definition management — define ISV-specific features with metering modes. * * Feature definitions describe what features an ISV application offers (e.g. "meal_plans", * "report_generation") and how they are metered (unlimited, counted, or credit-cost). */ featureDefinitions: { /** * List all feature definitions. * * @param options - Optional request options. * @returns Array of `FeatureDefinition` objects. */ list: (options?: RequestOptions) => Promise; /** * Get a feature definition by ID. * * @param id - The feature definition UUID. * @param options - Optional request options. * @returns The matching `FeatureDefinition`. */ get: (id: string, options?: RequestOptions) => Promise; /** List feature definitions for a specific application. */ listByApplication: (applicationId: string, options?: RequestOptions) => Promise; /** Create a new feature definition. */ create: (attrs: CreateFeatureDefinitionAttributes, options?: RequestOptions) => Promise; /** Update a feature definition. */ update: (id: string, attrs: Partial, options?: RequestOptions) => Promise; /** Delete a feature definition. */ delete: (id: string, options?: RequestOptions) => Promise; }; /** * Plan-feature allocation management — configure per-plan overrides for features. * * Allocations link feature definitions to plans, allowing per-plan limits, * credit costs, activation costs, and enable/disable toggles. */ planFeatureAllocations: { /** * List all plan-feature allocations. * * @param options - Optional request options. * @returns Array of `PlanFeatureAllocation` objects. */ list: (options?: RequestOptions) => Promise; /** Get a plan-feature allocation by ID. */ get: (id: string, options?: RequestOptions) => Promise; /** List allocations for a specific plan. */ listByPlan: (planId: string, options?: RequestOptions) => Promise; /** Create a plan-feature allocation. */ create: (attrs: CreatePlanFeatureAllocationAttributes, options?: RequestOptions) => Promise; /** Update a plan-feature allocation. */ update: (id: string, attrs: Partial, options?: RequestOptions) => Promise; /** Delete a plan-feature allocation. */ delete: (id: string, options?: RequestOptions) => Promise; }; /** * Feature usage tracking — view per-tenant feature usage records. * * Usage records track how many times each tenant has used a feature in the * current billing cycle. Read-only in the admin SDK. */ featureUsages: { /** * List all feature usage records. * * @param options - Optional request options, including pagination via `page` and `pageSize`. * @returns Array of `FeatureUsage` records. */ list: (options?: { page?: number; pageSize?: number; } & RequestOptions) => Promise; /** * Get a feature usage record by ID. * * @param id - The feature usage record UUID. * @param options - Optional request options. * @returns The matching `FeatureUsage` record. */ get: (id: string, options?: RequestOptions) => Promise; /** List usage records for a specific tenant. */ listByTenant: (tenantId: string, options?: { page?: number; pageSize?: number; } & RequestOptions) => Promise; }; /** * Usage event tracking — view per-tenant usage events for billing and cost visibility. * * Usage events record individual billable operations (LLM calls, extractions, etc.) * with credits charged, operation type, and metadata. Use for tenant usage dashboards * and ISV cost visibility reports. */ usageEvents: { /** * List usage events for a tenant within a date range. * * Defaults to the last 30 days. Use for tenant usage dashboards and * ISV cost visibility reports. * * @param tenantId - The tenant ID to scope the query. * @param filters - Optional date range filters. * @param filters.startDate - ISO 8601 start date (default: 30 days ago). * @param filters.endDate - ISO 8601 end date (default: now). * @param options - Optional request-level overrides. * @returns A promise resolving to an array of {@link UsageEvent} objects. */ list: (tenantId: string, filters?: { startDate?: string; endDate?: string; page?: number; pageSize?: number; }, options?: RequestOptions) => Promise; /** Get a usage event by ID. * * @param id - The usage event ID. * @param options - Optional request-level overrides. * @returns A promise resolving to a {@link UsageEvent} object. */ get: (id: string, options?: RequestOptions) => Promise; /** * List usage events for a specific user within a date range. * * Defaults to the last 30 days. Use for per-user usage breakdown. * * @param tenantId - The tenant ID to scope the query. * @param userId - The user ID to filter by. * @param filters - Optional date range filters. * @param filters.startDate - ISO 8601 start date (default: 30 days ago). * @param filters.endDate - ISO 8601 end date (default: now). * @param options - Optional request-level overrides. * @returns A promise resolving to an array of {@link UsageEvent} objects. */ listByUser: (tenantId: string, userId: string, filters?: { startDate?: string; endDate?: string; page?: number; pageSize?: number; }, options?: RequestOptions) => Promise; /** * Get usage summary for a tenant within a date range. * * Returns usage events for dashboard aggregation. Defaults to last 30 days. * * @param tenantId - The tenant ID to scope the query. * @param filters - Optional date range filters. * @param filters.startDate - ISO 8601 start date (default: 30 days ago). * @param filters.endDate - ISO 8601 end date (default: now). * @param options - Optional request-level overrides. * @returns A promise resolving to an array of {@link UsageEvent} objects. */ summary: (tenantId: string, filters?: { startDate?: string; endDate?: string; page?: number; pageSize?: number; }, options?: RequestOptions) => Promise; }; /** * Estimate capacity for a credit budget across an operations mix. * * ISV-facing endpoint that calculates how many of each operation * a given credit budget supports. * * @param params - Estimation parameters. * @param params.creditBudget - Total credits to estimate capacity for. * @param params.operationsMix - List of operations with weights (should sum to ~1.0). * @param options - Optional request-level overrides. * @returns A promise resolving to an {@link EstimateCapacityResponse} with capacity breakdown per operation. * * @example * ```typescript * const result = await admin.billing.estimateCapacity({ * creditBudget: 100000, * operationsMix: [ * { operationKey: "clinical_note_generation", weight: 0.5 }, * { operationKey: "llm_input_tokens", weight: 0.5 }, * ], * }); * console.log(result.capacity); * ``` */ estimateCapacity: (params: { creditBudget: number; operationsMix: Array<{ operationKey: string; weight: number; }>; }, options?: RequestOptions) => Promise; /** * Composite operation management — define ISV feature-to-operation mappings * for pricing estimation and capacity calculators. * * Composite operations map user-facing features (e.g., "AI Clinical Notes") * to platform operations (e.g., LLM tokens + agent steps). The pricing * estimator sums Schedule A rates for each component. */ compositeOperations: { /** * List all composite operations for the application. * * @param options - Optional request-level overrides. * @returns A promise resolving to an array of {@link CompositeOperation}. */ list: (options?: RequestOptions) => Promise; /** * Get a composite operation by ID. * * @param id - The composite operation UUID. * @param options - Optional request-level overrides. * @returns A promise resolving to a {@link CompositeOperation}. */ get: (id: string, options?: RequestOptions) => Promise; /** * Create a composite operation. * * @param attrs - Composite operation attributes. * @param options - Optional request-level overrides. * @returns A promise resolving to the created {@link CompositeOperation}. * * @example * ```typescript * const op = await admin.billing.compositeOperations.create({ * key: "clinical_note_generation", * display_name: "AI Clinical Notes", * components: [ * { operation_key: "llm_input_tokens", quantity: 2000, unit: "tokens" }, * { operation_key: "agent_execution_step", quantity: 3, unit: "steps" }, * ], * default_model: "gpt-4o", * is_public: true, * }); * ``` */ create: (attrs: CreateCompositeOperationAttributes, options?: RequestOptions) => Promise; /** * Update a composite operation. * * @param id - The composite operation UUID. * @param attrs - Attributes to update. * @param options - Optional request-level overrides. * @returns A promise resolving to the updated {@link CompositeOperation}. */ update: (id: string, attrs: Partial, options?: RequestOptions) => Promise; /** * Delete a composite operation. * * @param id - The composite operation UUID. * @param options - Optional request-level overrides. */ delete: (id: string, options?: RequestOptions) => Promise; }; /** * Aggregate-authoring surface for ISV plan publishing (§4.10). * * `planBundles` composes six existing Billing resources (Plan, * FeatureDefinition, PlanFeatureAllocation, CompositeOperation, * CreditPackage, PricingStrategy) into one atomic call. Four endpoints: * * - `publish` — atomic + idempotent + dry-run + hard-block on below-floor * margin (with `ackBelowFloor: true, reason: "..."` override). * - `previewEconomics` — pure CFO modeling: per-tier wholesale spend, * retail revenue, blended margin, sensitivity bands. * - `listTemplates` — four starter templates (seat-based, metered, * freemium-with-overage, developer-tier-prosumer). Every numeric and * money field is `"placeholder_unset"` — replace before publishing. * - `canEnable` — four-gate resolver across WholesaleAgreement / * Application bundles / Plan tiers / FeatureDefinition. */ planBundles: { /** * Atomically publish a plan bundle. Runs the §4.9 pre-publish checklist * (capability refs, permitted tiers, Schedule A ops, blended-margin * floor, placeholder sentinels) and either persists everything inside * one transaction or returns the offending payload — no orphan rows. * * Below-floor publishes are HARD-BLOCKED unless both `ackBelowFloor: * true` and a non-empty `reason` (≤ 280 chars) are supplied. An * acknowledged below-floor publish writes an * `audit:plan_published_below_floor` audit row after the transaction * commits. * * Re-publishing the same `plan.slug` upserts cleanly (idempotent on * resource identities — `Plan.slug`, `FeatureDefinition.key`, * `CreditPackage.slug`, etc.). * * @param bundle - The full PlanBundleSpec. * @param opts - Optional flags (`dryRun`, `ackBelowFloor`, `reason`). * @param options - Optional request options. * @returns Atomic publish result with entity ids + per-gate checklist. * * @example * ```typescript * // Agentless SDK happy path (spec §4.9.1): * // 1. Start from a template; replace every placeholder. * const [seatBased] = await admin.billing.planBundles.listTemplates({ * vertical: "vertical-saas", * }); * * const bundle: PlanBundleSpec = { * ...seatBased.bundle, * plan: { * ...seatBased.bundle.plan, * slug: "pro", * name: "Pro", * monthly_price: { amount: "499.00", currency: "USD" }, * monthly_credits: 50_000, * }, * }; * * // 2. Dry-run first — surface every checklist gate without persisting. * const dry = await admin.billing.planBundles.publish(bundle, { * dryRun: true, * }); * if (dry.checklist.gate_4_margin_floor === "red") { * // Adjust pricing OR explicitly acknowledge below-floor. * } * * // 3. Publish for real. * const published = await admin.billing.planBundles.publish(bundle); * console.log(published.entity_ids.plan_id); * ``` */ publish: (bundle: PlanBundleSpec, opts?: PlanBundlePublishOptions, options?: RequestOptions) => Promise; /** * CFO modeling for a plan bundle. Pure computation — no side effects. * * Computes per-tier expected wholesale spend, retail revenue, blended * margin, and sensitivity bands (±20% / ±50% on cost basis and usage). * Optionally accepts a `mix` parameter describing the tier-mix * assumption; defaults to a sample mix derived from * `plan.capability_tiers`. * * @param bundle - The PlanBundleSpec to model. * @param mix - Optional tier-mix assumption. Falls back to defaults. * @param options - Optional request options. * @returns Per-tier economics + blended margin + sensitivity bands. * * @example * ```typescript * const preview = await admin.billing.planBundles.previewEconomics( * bundle, * { core: { count: 100 }, premium: { count: 10 } }, * ); * console.log(preview.blended_margin_pct); * ``` */ previewEconomics: (bundle: PlanBundleSpec, mix?: PlanBundleMix, options?: RequestOptions) => Promise<{ [key: string]: unknown; }>; /** * Returns the four starter plan-bundle templates. Every numeric and * money field is `"placeholder_unset"` — the ISV MUST replace every * placeholder before calling `publish()` (which refuses to publish a * bundle containing the sentinel). * * @param filter - Optional `vertical` filter. * @param options - Optional request options. * @returns Array of `PlanBundleTemplate` records. * * @example * ```typescript * const all = await admin.billing.planBundles.listTemplates(); * const saas = await admin.billing.planBundles.listTemplates({ * vertical: "vertical-saas", * }); * ``` */ listTemplates: (filter?: { vertical?: string; }, options?: RequestOptions) => Promise; /** * Four-gate resolver answering "can this capability be enabled for this * Application (and optionally this Plan)?". Replaces the manual * reproduction of the gating chain by dashboards. * * Gates evaluated: * 1. `wholesale_agreement.permitted_capability_tiers` * 2. `application.bundles` (via `enabled_capabilities`) * 3. `plan.capability_tiers` (skipped when `planSlug` omitted) * 4. `feature_definition.platform_capability` (skipped when no * FeatureDefinition references this capability) * * @param args - `applicationId` + `capabilityKey` (required), `planSlug` (optional). * @param options - Optional request options. * @returns Per-gate breakdown with `allowed` boolean. * * @example * ```typescript * const verdict = await admin.billing.planBundles.canEnable({ * applicationId: "app-uuid", * planSlug: "pro", * capabilityKey: "news_monitoring", * }); * if (!verdict.allowed) console.log(verdict.checks); * ``` */ canEnable: (args: { applicationId: string; capabilityKey: string; planSlug?: string; }, options?: RequestOptions) => Promise; }; /** * Capability-revocation cascade management — dry-run preview and listing * of subscriptions in the capability-revocation grace period. * * Use before calling `Tenancy.disable_capability` to assess billing impact. * Zero `affected_count` means the disable is safe to proceed without notifying tenants. */ capabilityRevocations: { /** * Preview which subscriptions would be affected by disabling a capability * on an Application, **without applying any changes**. * * Delegates to the server-side `CapabilityRevocationCascade` with * `dry_run: true`. No subscriptions are transitioned, no events are emitted, * and no tenant notifications fire. * * Requires a `sk_sys_` platform-admin API key. * * @param applicationId - UUID of the Application whose capability is being * considered for disablement. * @param capability - The capability atom name (e.g. `"meeting_intelligence"`). * @param options - Optional request-level overrides. * @returns A {@link CapabilityRevocationPreview} with `affected_count` and * `subscription_ids` — review before calling `disable_capability`. * * @example * ```typescript * const admin = new GptAdmin({ apiKey: 'sk_sys_...' }); * * // Safe-check before disabling the capability on the Application. * const preview = await admin.billing.capabilityRevocations.previewCascade( * 'app-uuid-here', * 'meeting_intelligence', * ); * * if (preview.affected_count > 0) { * console.log(`⚠️ ${preview.affected_count} subscriptions will enter grace period:`); * preview.subscription_ids.forEach(id => console.log(` - ${id}`)); * } else { * console.log('✓ No active subscriptions affected — safe to disable.'); * } * ``` */ previewCascade: (applicationId: string, capability: string, options?: RequestOptions) => Promise; }; /** * Subscriptions namespace — manage and query billing subscriptions. * * The `listCapabilityRevoked` method lists subscriptions in the * `:capability_revoked_grace` state (and optionally `:canceled_capability_revoked`) * for platform-admin triage after an ISV disables a capability. * * The `listSubscriptionsByPlanRevision` method lists subscribers pinned to * a specific Plan revision — used to audit which subscribers remain on the * old pricing terms before deprecating or sunsetting a plan. */ subscriptions: { /** * List subscriptions in the capability-revocation grace period. * * Defaults to grace-only (`:capability_revoked_grace`). Pass * `includeCanceled: true` to also return `:canceled_capability_revoked` * subscriptions that already passed their `current_period_end`. * * Both `applicationId` and `capability` are optional filters. Omit both * to list all revoked subscriptions across the platform. * * Requires a `sk_sys_` platform-admin API key. * * @param filters - Optional filter parameters. * @param filters.applicationId - Scope to subscriptions whose plan belongs * to a specific Application UUID. * @param filters.capability - Scope to a specific revoked capability name * (e.g. `"meeting_intelligence"`). * @param filters.includeCanceled - When `true`, includes * `:canceled_capability_revoked` subscriptions (default: `false`). * @param options - Optional request-level overrides. * @returns An array of {@link Subscription} objects in revocation state, * sorted by `revoked_at` descending. * * @example * ```typescript * const admin = new GptAdmin({ apiKey: 'sk_sys_...' }); * * // List all grace-period subscriptions for an Application. * const graceList = await admin.billing.subscriptions.listCapabilityRevoked({ * applicationId: 'app-uuid-here', * }); * console.log(`${graceList.length} subscriptions in grace period`); * * // Also include already-canceled ones for full audit. * const fullList = await admin.billing.subscriptions.listCapabilityRevoked({ * applicationId: 'app-uuid-here', * capability: 'meeting_intelligence', * includeCanceled: true, * }); * ``` */ listCapabilityRevoked: (filters?: { applicationId?: string; capability?: string; includeCanceled?: boolean; }, options?: RequestOptions) => Promise; /** * List subscriptions pinned to a specific Plan revision. * * Each Subscription carries an immutable `plan_revision_id` audit tag of * the form `":"` captured * at create time (Phase 1 of the plan-versioning pin-policy work). When * an ISV edits a Plan, existing subscribers keep their original pinned * revision; only NEW subscribers see the new revision. This method lets * the ISV (or platform admin) enumerate subscribers grouped by which * revision they are still on — useful for deciding whether the old * revision is sparse enough to deprecate the plan, or for force-migrating * stragglers off an outdated revision before sunset. * * Internally calls `GET /admin/subscriptions?filter[plan_id]=…&filter[plan_revision_id]=…`. * The Subscription resource exposes `plan_id` and `plan_revision_id` as * public attributes, so AshJsonApi's default filter parser handles this * with no extra read action. * * Pass `revisionId` to scope to a single revision; omit it to return all * subscribers on the plan regardless of revision (group the results by * `attributes.plan_revision_id` client-side to inspect drift). * * Requires Platform Admin or the Application Owner whose application * owns the plan. * * @param planId - UUID of the Plan to scope to. * @param revisionId - Optional `:` revision tag. * Omit to return all subscribers on the plan regardless of revision. * @param options - Optional request-level overrides. * @returns Array of {@link Subscription} objects (single page; the * underlying `GET /admin/subscriptions` supports JSON:API pagination * via `options.query.page` if a deeper drill-in is needed). * * @example * ```typescript * const admin = new GptAdmin({ apiKey: 'sk_srv_...' }); * * // Find every subscriber still pinned to the pre-price-bump revision * // before we sunset the plan. * const stale = await admin.billing.subscriptions * .listSubscriptionsByPlanRevision( * 'plan-uuid', * 'pro-monthly:1715812345678901', * ); * console.log(`${stale.length} subscribers still on the old revision`); * * // Snapshot all subscribers on the plan and bucket them by revision. * const all = await admin.billing.subscriptions * .listSubscriptionsByPlanRevision('plan-uuid'); * const byRevision = all.reduce>((acc, sub) => { * const rev = sub.attributes?.plan_revision_id ?? '(unpinned)'; * acc[rev] = (acc[rev] ?? 0) + 1; * return acc; * }, {}); * console.log(byRevision); * ``` */ listSubscriptionsByPlanRevision: (planId: string, revisionId?: string, options?: RequestOptions) => Promise; /** * Set per-subscription rate-limit overrides. * * Restricted to Platform Admin and Application Owner. Tenant owners * are forbidden — overrides are platform/ISV concessions, not * customer-writable. Pass any subset of the three override fields; * `null` clears an existing override and the subscription falls back * to the plan-level limit. Resolution chain (first non-nil): * * subscription override > plan default > per-ApiKey override * > plug-static default * * Calls `PATCH /admin/subscriptions/:id/set-rate-limit-overrides`. * * @param subscriptionId - UUID of the subscription to update. * @param overrides - Override values. `null` clears; `undefined` is a * no-op (only the keys you supply are touched). * @param options - Optional request-level overrides. * @returns The updated {@link Subscription} with the new override values. * * @example * ```typescript * // Tighten one tenant to 50 req/min for the next billing cycle. * await admin.billing.subscriptions.setRateLimitOverrides( * subscriptionId, * { * rate_limit_requests_override: 50, * rate_limit_period_seconds_override: 60, * }, * ); * * // Clear all overrides (subscription returns to plan defaults). * await admin.billing.subscriptions.setRateLimitOverrides( * subscriptionId, * { * rate_limit_requests_override: null, * rate_limit_period_seconds_override: null, * concurrent_operations_limit_override: null, * }, * ); * ``` */ setRateLimitOverrides: (subscriptionId: string, overrides: { rate_limit_requests_override?: number | null; rate_limit_period_seconds_override?: number | null; concurrent_operations_limit_override?: number | null; }, options?: RequestOptions) => Promise; }; }; /** Attributes for creating a composite operation. */ export type CreateCompositeOperationAttributes = { key: string; display_name: string; application_id?: string; description?: string; components?: Array<{ operation_key: string; quantity: number; unit?: string; }>; default_model?: string; is_public?: boolean; sort_order?: number; }; /** Response from the estimate-capacity endpoint. */ export interface EstimateCapacityResponse { credit_budget: number; capacity: Array<{ operation_key: string; display_name: string; allocated_credits: number; credits_per_use: number; estimated_count: number; is_estimate: boolean; }>; is_estimate: boolean; } /** * Aggregate-authoring spec for `admin.billing.planBundles.publish` / * `previewEconomics`. Mirrors the §4.10 contract: a single payload composing * Plan + FeatureDefinitions + PlanFeatureAllocations + CompositeOperations + * CreditPackages + PricingStrategies. * * The fields are intentionally loose-typed (the server-side Ash resources are * the source of truth for nested shapes — see `lib/gpt_core/billing/`). * Replace `placeholder_unset` sentinel values returned by `listTemplates()` * before calling `publish()`. */ export interface PlanBundleSpec { plan: { slug: string; name?: string; monthly_price?: { amount: string; currency: string; }; monthly_credits?: number; capability_tiers?: string[]; [key: string]: unknown; }; feature_definitions?: Array<{ key: string; platform_capability?: string; [key: string]: unknown; }>; plan_feature_allocations?: Array<{ feature_key: string; credit_cost?: number; enabled?: boolean; [key: string]: unknown; }>; composite_operations?: Array<{ key?: string; feature_key?: string; components?: Array<{ operation_key: string; quantity: number; unit?: string; }>; [key: string]: unknown; }>; credit_packages?: Array<{ slug: string; credits: number; price?: { amount: string; currency: string; }; [key: string]: unknown; }>; pricing_strategies?: Array<{ service_id: string; [key: string]: unknown; }>; } /** * Tier-mix assumption supplied to `previewEconomics`. Keys are tier slugs * (`"core"`, `"standard"`, `"premium"`); values are per-tier subscriber * counts and average ops/month per feature. When omitted, the server uses * a sample mix derived from `plan.capability_tiers`. */ export interface PlanBundleMix { [tier_slug: string]: { count: number; avg_ops_per_month?: { [feature_key: string]: number; }; }; } /** Optional flags accepted by `planBundles.publish()`. */ export interface PlanBundlePublishOptions { /** Run the §4.9 pre-publish checklist without persisting. */ dryRun?: boolean; /** Override the §4.5 margin floor hard-block. Requires `reason`. */ ackBelowFloor?: boolean; /** ≤ 280 chars. Required when `ackBelowFloor: true`. */ reason?: string; /** Resolved from the x-application-key header when omitted. */ applicationId?: string; } /** Result envelope returned by `planBundles.publish()`. */ export interface PlanBundlePublishResult { status: "ok" | "dry_run" | "below_floor_blocked"; entity_ids: { plan_id: string | null; feature_definition_ids: string[]; plan_feature_allocation_ids: string[]; composite_operation_ids: string[]; credit_package_ids: string[]; pricing_strategy_ids: string[]; }; checklist: { gate_1_capability_refs: string; gate_2_permitted_tiers: string; gate_3_schedule_a_ops: string; gate_4_margin_floor: string; gate_5_placeholder_unset: string; }; audit_event_emitted: boolean; audit_row_id: string | null; } /** Single template entry returned by `planBundles.listTemplates()`. */ export interface PlanBundleTemplate { slug: string; vertical?: string; pattern?: string; description?: string; schema_version?: string; bundle: PlanBundleSpec; [key: string]: unknown; } /** Result envelope returned by `planBundles.canEnable()`. */ export interface CanEnableResult { allowed: boolean; checks: Array<{ gate: string; status: "pass" | "fail" | "skip"; reason: string; }>; } /** * Result returned by `billing.capabilityRevocations.previewCascade()`. * * Reports how many subscriptions would enter the `:capability_revoked_grace` * period if the capability were disabled, and which subscription IDs they are. * `dry_run` is always `true` — no changes are applied. */ export interface CapabilityRevocationPreview { /** Number of active subscriptions that would be affected. */ affected_count: number; /** UUIDs of the affected subscriptions. */ subscription_ids: string[]; /** Always `true` for this operation. */ dry_run: true; } //# sourceMappingURL=billing.d.ts.map