# crontab — every 15 minutes curl -s \ -H "Authorization: Bearer tou_…" \ ".../query/current?zip_code=94103"
~2,880 calls/month to notice a 4 PM flip. Miss the minute, or hammer the quota.
TOU webhooks
A signed POST when a time-of-use period flips — off-peak to on-peak, and every other boundary. No cron. No polling /query/current.
A 15-minute cron on /query/current spends quota to learn something that happens a handful of times a day. The webhook is the flip itself.
# crontab — every 15 minutes curl -s \ -H "Authorization: Bearer tou_…" \ ".../query/current?zip_code=94103"
~2,880 calls/month to notice a 4 PM flip. Miss the minute, or hammer the quota.
POST /hooks/tou
{
"type": "tou.period.changed",
"previous_period": "off_peak",
"period": "on_peak"
}
One signed delivery at the boundary. Your server reacts. Polling quota stays unused.
How it works
Three steps in the dashboard. The first observation of each plan is recorded silently — you only get events on real transitions.
Paste an HTTPS URL. You get a signing secret (tousec_…), shown once. Store it.
Add (ZIP, customer_class) pairs. One endpoint can cover every location in your plan.
When period is on_peak, peak started. Respond 2xx. Shed load, pause chargers, raise reserve.
The event
A tou.period.changed body for one rate plan at one watched ZIP. Copy it, then wire a 2xx handler. Signature, retries, and headers live in the docs — this page does not duplicate them.
{
"id": "evt_8f3a2c104b6d4e9a9f12",
"type": "tou.period.changed",
"created_at": "2026-05-16T16:00:00-07:00",
"zip_code": "94103",
"customer_class": "residential",
"previous_period": "off_peak",
"period": "on_peak",
"next_change_at": "2026-05-16T21:00:00-07:00",
"rate_plan": {
"id": "8f3a2c10-4b6d-4e9a-9f12-7c5e1d8a0b34",
"utility_number": 14328,
"utility_name": "Pacific Gas & Electric Co",
"code": "E-TOU-C",
"name": "Residential Time-of-Use"
}
}
A ZIP that resolves to several plans sends one event per plan that changed. previous_period / period use the same names as the REST API.
# POST /hooks/tou # verify Tou-Signature first — /docs/#webhooks @app.post("/hooks/tou") def on_period_changed(): event = request.get_json() if event["period"] == "on_peak": pause_chargers(event["zip_code"]) return ("", 200)
That is the whole job: branch on period, ack with 2xx. Set the endpoint up in the webhooks dashboard.
What to fire
Pause Wall Connectors and depot stalls when period becomes on_peak. Resume on off_peak or super_off_peak.
Pre-cool from next_change_at on the prior event, then coast when this one says on-peak. No hardcoded 4 PM.
Raise reserve and discharge at peak start. Period names only — this API never sends ¢/kWh.
One endpoint, many ZIPs. Shed HVAC and lighting in each territory as that utility’s peak starts, not yours.
Hold charging across service territories until off-peak returns. High-volume sites stay off the polling loop.
Flask, FastAPI, n8n, Temporal — anything that accepts a POST. Home Assistant can keep polling; webhooks are for a server you own.
Each delivery is HMAC-SHA256 over {timestamp}.{body}, Stripe-style.
Verify Tou-Signature before you trust the JSON.
Respond 2xx or we retry: immediately, then 1 min, 5 min, 30 min, 2 h.
Every attempt lands in the webhooks dashboard with status, HTTP code, and attempt count. The full verify recipe is in the period-change docs.
tousec_… secret.id. Deliveries retry, so dedupe on this.Register a webhook endpoint and watch a ZIP. When that location’s period changes, tou.tools sends a signed tou.period.changed event. If previous_period is off_peak and period is on_peak, peak just started.
A signed HTTP POST fired when a time-of-use period changes — off-peak to on-peak, and every other boundary — for a location you watch. It replaces polling GET /query/current just to learn that the clock flipped.
Not for period changes. Poll when you need the period right now — a dashboard, a one-shot agent call. Use the webhook when your server should react as the tariff clock flips.
No. Webhooks start on Builder: 3 endpoints, 10 on Growth, 25 on Business, unlimited on Enterprise. Each endpoint can watch any of the locations in your plan. Get a free key, then upgrade when you are ready to push events.
No. tou.tools is the timing layer: period names and clock boundaries. The payload has previous_period, period, next_change_at, ZIP, and the rate plan — not prices.
Non-2xx and timeouts retry: immediately, then 1 min, 5 min, 30 min, 2 h. Dedupe on Tou-Webhook-Id. Every attempt is logged on the webhooks dashboard.
No credit card. Webhooks ship on Builder — three endpoints, any of your locations. Create the key first, upgrade when you want the POST.