Scheduled Customer Energy Billing (Stripe)
Automates monthly energy billing via Stripe. Triggered by a scheduled Billing Event fanned out to each asset in the Billing Group asset group, or by a manual REST API call, the chain fetches the asset’s Stripe customer ID, price, and currency attributes, computes the prior calendar month as the billing period, reads its latest totalConsumption value (maintained by a Calculated Field) for that window, computes amount as price × usage, and creates, itemizes, and finalizes a Stripe invoice.
- Add invoice items
- Save Timeseries
- Save Attributes
- Log RPC from Device
- RPC Call Request
Who it’s for
Tenant admins and platform engineers running energy-monitoring devices who need customers invoiced automatically for their monthly energy usage through Stripe - when the goal is to turn cumulative consumption telemetry into a sent Stripe invoice on a schedule, or on demand.
What it does
Adds a Stripe billing pipeline in front of, and off two outputs of, the root chain’s Message Type Switch node.
- Is Entity Group checks whether the message originator is an asset group. Group-scoped messages carrying a custom
Billing Eventtype are picked and fanned out to every asset in the group by Duplicate To Group Entities - this is what lets one scheduled event addressed to the Billing Group trigger billing for each asset in it. Everything else skips straight to Message Type Switch. - Billing Event switch - is the second entry point into the billing pipeline, reached off
Message Type Switch’s Other and REST API request outputs. It reacts to three cases:- a custom
Billing Eventmessage → Scheduled Billing Event, for Scheduler-driven runs. - a REST API request whose body includes a
stripeBillingEventfield → Manual Billing Event. This path hits ack billing request first, replying to the caller immediately so the API call doesn’t wait on the full flow. - anything else → routed to Log Other, the same node ordinary tenant traffic already logs through.
- a custom
- Get Customer’s Stripe ID, currency & energy price fetches the
stripeCustomer,price, andcurrencyserver attributes onto the message, failing the flow if any of them is missing. - Define billing interval computes the previous full calendar month as
[billingStartTs, billingEndTs], using the server’s own local time zone as the clock that decides where the month starts. The Scheduler event has a separate time zone setting of its own - the two need to agree, or the boundary computed here and the one configured on the Scheduler will disagree by your UTC offset. - Get total consumption during billing period reads the latest value of the
totalConsumptionkey within that window - the consumption total for that billing period, maintained upstream by a Calculated Field pipeline (see Requirements), not summed here. - Compute billed amount & build invoice request multiplies consumption × price into cents and builds the Stripe “create invoice” body (
collection_method=send_invoice,days_until_due=14). - Create draft invoice (Stripe) posts to
/v1/invoicesto create the draft. - Create invoice item request body builds the usage line item - amount, currency, billing period as the description - using the invoice ID just returned.
- Add invoice items posts to
/v1/invoiceitems, attaching that line item to the draft. - Finalize invoice request body pulls the invoice ID back out of that response.
- Finalize invoice posts to
/v1/invoices/{id}/finalize, locking the invoice and sending it to the customer.
Requirements
- A Stripe account and secret API key, stored as the
STRIPE_API_KEYsecret — all three REST API Call nodes authenticate withBearer ${secret:STRIPE_API_KEY;type:TEXT}. stripeCustomer,price, andcurrencyserver-scope attributes set on each billed asset.- A Calculated Field pipeline maintaining a
totalConsumptionkey per asset that holds the consumption total for the current billing period, reset on calendar-month boundaries - not a lifetime running total. Billing multiplies whatever is in this key by price, so a counter that never resets will invoice a customer their entire lifetime consumption every month. It’s normally three steps:- Convert each meter’s cumulative reading into a delta.
- Aggregate those deltas into a monthly total per meter, using the same template as above but with the aggregation period changed from daily to monthly.
- Roll the per-meter monthly totals up onto the asset you actually bill. There’s no published template for this step, since it depends on how your meters map onto billable assets - implement it as a Calculated Field (or other logic) that sums the step-2 outputs across the meters belonging to each billed asset, writing the result to
totalConsumption.
- A Billing Group asset group containing the assets to bill.
- A Scheduler event that fires a
Billing Eventmessage to that group monthly, set to the same time zone as your server (see How to set up).
How to set up
- Create the Billing Group asset group. Go to Entities → Assets, switch to the Groups tab, click + Add entity group, name it
Billing Group, and click Add. Open the group and add the assets you want billed. - Create a Scheduler event to fire it. Go to Advanced features → Scheduler, click +, and on the Configuration tab set:
- Event type: Billing Event
- Originator: your
Billing Groupasset group - Message type:
Billing Event(type it explicitly - don’t rely on the event name matching) - On the Schedule tab, set Repeat to Monthly and set the start time to the 1st at 00:00
- Set the event’s time zone to match your server’s - Define billing interval uses the server clock to decide where the month starts, and the two need to agree
- Click Install on the rule chain and set it as the root chain - it already bundles the default routing plus the billing flow. If you’d rather not disturb your existing root chain, extract the billing pipeline - everything from Billing Event switch onward - into a nested rule chain and connect it to the Other and REST API request outputs of your existing root’s Message Type Switch. Then open Post attributes or RPC request in your own root chain and add
Billing Eventunder Select message types - without it the scheduled event never reaches Duplicate To Group Entities, so billing never runs for the assets in the group.
- Manual-trigger caveat: a REST API request routes to its originator’s asset-profile default rule chain first, falling back to root only when that profile has no default chain set. So the manual
stripeBillingEventcall only reaches this flow for as long as none of your billed assets’ profiles have a default chain of their own. The scheduled path isn’t affected by this - it’s addressed to the entity group, which always falls back to root. If you later assign a default chain to one of those profiles, that asset’s manual billing calls will stop reaching this flow; either avoid setting profile defaults for billed asset profiles, or wire the manual path into whatever chain you do bind to that profile.
- Add a tenant/system secret named
STRIPE_API_KEYwith your Stripe secret key, via Secrets Storage - that’s what the${secret:STRIPE_API_KEY;type:TEXT}reference in each REST API Call node’s Authorization header resolves against, so you’re not pasting the key into three separate nodes. - On each asset you intend to bill, set the
stripeCustomer,price, andcurrencyserver attributes. - Verify by sending a REST API request with
{"stripeBillingEvent": true}in the body against a configured asset - you should get an immediate ack, then see a finalized invoice appear in your Stripe dashboard.
How to customize
- To bill assets directly without the asset group - skip the Is Entity Group branch and point your scheduler’s REST API request calls at each asset individually.
- To change how the billing period is calculated - edit the TBEL script in Define billing interval (e.g. bill month-to-date instead of the previous full month).
- To auto-charge the customer instead of emailing an invoice - change
collection_method=send_invoicetocollection_method=charge_automaticallyin Compute billed amount & build invoice request, and dropdays_until_due. - To review invoices before they go out - remove the connection from Finalize invoice request body to Finalize invoice; drafts will then sit in Stripe for manual review.
- To bill a different consumption metric - point Time series keys on Get total consumption during billing period at a different key.
- To add an audit trail - there’s currently no logging on the billing path itself. Add a node after Finalize invoice that writes invoice ID, amount, and status to timeseries on success, and a parallel failure branch off each REST API Call node’s “Failure” output that logs the HTTP status and Stripe error body - useful for reconciling billing runs after the fact.
Share Your Rule Chain with the Community
Built a useful automation workflow? From a simple alarm recipe to a complex multi-cloud integration — publish it to the IoT Hub. Share it with thousands of ThingsBoard developers.