Skip to main content
RecordUsage is the action you call each time a billable consumes units under a metered plan. It persists a usage record to subscribd_usage_records and forwards the report to the configured gateway. At the end of each billing period, the gateway sums all reported units and produces the final invoice. This pattern is suited to API call billing, cloud resource consumption, or any service measured in discrete units.

When to call RecordUsage

Call RecordUsage at the point of consumption — typically at the end of a queued job, after an API request completes, or in a batch at regular intervals. You must have a SubscriptionItem reference to pass to the action. Retrieve it from the subscription.
$subscription = $user->subscription('default');
$subscriptionItem = $subscription->items()->firstOrFail();

execute() signature

app(RecordUsage::class)->execute(
    $subscriptionItem,
    $unitsConsumed,
    idempotencyKey: $jobId,
);
ParameterTypeRequiredDescription
$subscriptionItemSubscriptionItemYesThe subscription item associated with the metered plan
$unitsintYesNumber of units consumed in this report
$idempotencyKey`stringnull`NoA unique key to prevent duplicate records on retries

Full example

use Pixelworxio\Subscribd\Actions\RecordUsage;

// At the end of a job, API request, or batch:
app(RecordUsage::class)->execute(
    $subscriptionItem,
    $unitsConsumed,
    idempotencyKey: $jobId,  // prevents duplicate records on retries
);

Idempotency

Passing an idempotencyKey prevents the same usage from being counted twice if the action is called more than once with identical arguments — for example, when a job is retried after a transient failure.
  • If no record with that key exists, the usage is recorded normally.
  • If a record with the same key already exists, the call is a no-op and the existing record is returned.
  • Concurrent calls with the same key are handled safely — only one record is saved regardless of race conditions.
Use your job’s unique identifier — such as a job UUID, a request ID, or a database row ID — as the idempotency key. This makes retries safe without any extra coordination logic.
When you omit idempotencyKey, each call creates a new record. This is appropriate for batch-style reporting where each call represents a distinct consumption event, but risky in job contexts where retries are possible.

Relation to the metered plan rule

RecordUsage is only meaningful on subscriptions backed by a plan with 'rule' => 'metered'. The plan’s rule_config.unit_price defines the per-unit charge that the gateway applies when summing usage at period end.
// Example metered plan definition in config/subscribd.php
'compute' => [
    'name'        => 'Compute',
    'rule'        => 'metered',
    'price'       => 0,             // base price is 0; usage drives the bill
    'currency'    => 'USD',
    'interval'    => 'month',
    'interval_count' => 1,
    'rule_config' => [
        'unit_price' => 2,          // $0.02 per unit
    ],
],

Getting the subscription item

The SubscriptionItem model sits between the Subscription and the gateway’s line-item representation. For metered plans there is typically one item per subscription.
use Pixelworxio\Subscribd\Models\Subscription;

$subscription = $user->subscription('default');

// Get the first (and usually only) item
$subscriptionItem = $subscription->items()->firstOrFail();

app(RecordUsage::class)->execute(
    $subscriptionItem,
    units: 150,
    idempotencyKey: "batch-{$batchId}",
);
Do not confuse RecordUsage with TrackFeatureUsage. RecordUsage reports billable consumption to the gateway and results in charges on the next invoice. TrackFeatureUsage tracks discrete resource counts (like the number of projects created) for entitlement limit enforcement and does not create gateway billing records.