driptab/Docs

Subscriptions

A subscription places a customer on a plan. It is the central object in Driptab: it drives billing period management, event aggregation, and invoice generation.


Creating a subscription

dtab subs create \
  --external-id your-system-sub-id \
  --customer <customer_id_or_external_id> \
  --plan <plan_code_or_id>

Or via the API:

POST /v1/subscriptions
X-Project-Id: <project_id>
Authorization: Bearer dtab_…

{
  "external_id": "your-system-sub-id",
  "customer_id": "uuid-of-customer",
  "plan_id": "uuid-of-plan"
}

When a subscription is created:

  • A SubscriptionMeter Durable Object is initialised for this subscription.
  • current_period_start is set to now (UTC); current_period_end is calculated from the plan's interval.
  • An alarm is scheduled on the DO to fire at current_period_end.
  • Status is set to active.

Subscription properties

Some plans use quantity_formula: subscription_property.node_count on a charge, which means the quantity for that charge comes from the subscription's properties object. Set properties at creation time:

{
  "external_id": "k8s-cluster-prod",
  "customer_id": "...",
  "plan_id": "...",
  "properties": { "node_count": 5 }
}

Properties are stored as JSON on the subscription row and are immutable after creation. To change the node count, terminate and re-create the subscription.


Statuses

Status Meaning
pending Created but not yet started. Not currently in use at MVP.
active Billing is running. Events are accepted. Period alarms are scheduled.
suspended Billing is paused. Events are rejected. Invoked by dunning; your system decides when to suspend.
terminated Permanently ended. The current period's usage is invoiced; no further billing.
canceled Administratively closed with no final invoice.

Status transitions:

pending → active → suspended → active    (if payment received)
                 → terminated
         active  → terminated
         active  → canceled

Driptab does not automatically suspend or terminate subscriptions. It fires webhooks at dunning milestones; your system calls POST /v1/subscriptions/:id/terminate when it decides to act. This is intentional — suspension and termination are business decisions that depend on grace periods, retry logic, and customer communication that Driptab does not own.


Billing periods

Periods are owned by the SubscriptionMeter Durable Object, not by SQL. The D1 subscriptions table reflects the last known period boundaries but the DO is authoritative.

With billing_time: 'calendar' (the only mode in MVP), periods align to calendar boundaries:

  • monthly — 1st of the month at 00:00:00 UTC to the last day at 23:59:59 UTC.
  • yearly — Jan 1 to Dec 31 UTC.
  • weekly — Monday 00:00 UTC to Sunday 23:59 UTC.

The first period starts when the subscription is created. If a subscription starts on the 15th of the month with a monthly plan, the first period is the 15th to the last day of that month (prorated in future; full period in MVP). The second period starts on the 1st of the following month.


Terminating a subscription

dtab subs terminate <subscription_id>

Termination:

  1. Marks the subscription terminated_at and sets status to terminated.
  2. The DO generates a final invoice for any usage accrued in the current period.
  3. No further period alarms are scheduled.

A terminated subscription cannot be reactivated. Create a new subscription if the customer restarts.


External IDs

external_id is your system's ID for this subscription. It must be unique per project. The recommended convention is to use your internal subscription record's primary key.

Use external_id (prefixed with ext:) anywhere the API accepts a subscription ID:

dtab subs get ext:your-system-sub-id
dtab ev ingest --subscription ext:your-system-sub-id ...

This avoids storing Driptab's UUID in your system.


Querying a subscription

dtab subs get <id_or_external_id>

Response includes current_period_start, current_period_end, status, plan, and a summary of charges. It does not include live in-period usage counters (those live in the DO). To see usage mid-period, use the analytics endpoint or query the events table.