Docs

The Billing run object

Billing helpers process due subscription renewals and invoice retries for your platform. Recurring USDC collection is not a shared Stripe-like backend job you ignore — on Zoneless Cloud the operator runs billing on a schedule; self-hosters trigger it themselves (or enable the optional in-process monitor).

Automatic collection only runs for subscriptions that have a subscription_delegation_pda, use collection_method=charge_automatically, are not paused, and are in active, past_due, or (after trial end) trialing.

Attributes

object string

String representing the object's type. Always billing.run.

processed integer

Total number of subscriptions considered in this pass (succeeded, failed, and skipped).

succeeded integer

Subscriptions that were successfully invoiced and collected in this pass.

failed integer

Subscriptions that failed during processing. See errors for details.

skipped integer

Subscriptions skipped in this pass (for example, already claimed by another runner or not due).

errors array of objects

Per-subscription failure details from this pass.

THE BILLING RUN OBJECT
{
  "object": "billing.run",
  "processed": 12,
  "succeeded": 10,
  "failed": 1,
  "skipped": 1,
  "errors": [
    {
      "subscription": "sub_z_1NGQwV2eZvKYlo2CjrVqXzAb",
      "error": "Insufficient USDC allowance for subscription delegation"
    }
  ]
}

Run billing for your platform

Runs one billing pass for the authenticated platform: retries open subscription invoices that are due for another attempt, then creates and collects cycle invoices for subscriptions whose current period has ended.

ENDPOINTS
POST /v1/billing/run_for_platform

Each subscription is claimed with a short billing_lock_until window so overlapping runners do not create duplicate cycle invoices. Failed automatic payments move the subscription toward past_due / unpaid after repeated attempts.

Parameters

batch_size integer

Maximum number of subscriptions to process in this pass. Defaults to 25 when omitted.

Returns

Returns a billing.run object summarizing how many subscriptions were processed, succeeded, failed, or skipped.

POST/v1/billing/run_for_platform
import { Zoneless } from '@zoneless/node';
const zoneless = new Zoneless('sk_live_z_YOUR_API_KEY', 'https://api.zoneless.com');

const result = await zoneless.billing.runForPlatform({
  batch_size: 25,
});

console.log(`Processed ${result.processed}, succeeded ${result.succeeded}`);
for (const err of result.errors) {
  console.log(`${err.subscription}: ${err.error}`);
}
RESPONSE
{
  "object": "billing.run",
  "processed": 12,
  "succeeded": 10,
  "failed": 1,
  "skipped": 1,
  "errors": [
    {
      "subscription": "sub_z_1NGQwV2eZvKYlo2CjrVqXzAb",
      "error": "Insufficient USDC allowance for subscription delegation"
    }
  ]
}

Retrieve monitor status

Returns whether the optional in-process billing monitor is enabled and running on this API instance, along with its poll interval.

ENDPOINTS
GET /v1/billing/monitor/status

When enabled, the API starts a loop that periodically runs the same billing pass as run_for_platform (across all platforms on that instance). Configure with:

  • BILLING_MONITOR_ENABLED=true — must be exactly true to enable
  • BILLING_POLL_INTERVAL_MS=60000 — poll interval in milliseconds (default 60000)

Parameters

No parameters.

Returns

Returns the billing monitor status for this API instance.

Response attributes

running boolean

Whether the in-process billing monitor loop is active on this API instance.

enabled boolean

Whether BILLING_MONITOR_ENABLED is set to true on this API instance.

poll_interval_ms integer

Configured poll interval in milliseconds, from BILLING_POLL_INTERVAL_MS. Defaults to 60000.

platform_account string

The platform account ID the request was authenticated as.

GET/v1/billing/monitor/status
import { Zoneless } from '@zoneless/node';
const zoneless = new Zoneless('sk_live_z_YOUR_API_KEY', 'https://api.zoneless.com');

const status = await zoneless.billing.monitorStatus();

console.log(`enabled=${status.enabled} running=${status.running}`);
console.log(`interval=${status.poll_interval_ms}ms`);
RESPONSE
{
  "running": false,
  "enabled": false,
  "poll_interval_ms": 60000,
  "platform_account": "acct_z_Platform123abc"
}