# Bayou Energy Webhooks

[Bayou Energy](https://bayou.energy) is a utility-data API that retrieves customers' utility bills and interval data. Its webhooks report new and updated bills, readiness of the initial bill and interval pulls, and credential status. Every delivery is signed per the Standard Webhooks spec.

## When to Use This Skill

* How do I receive Bayou Energy webhooks?
* How do I verify a Bayou webhook signature?
* Where do I find my Bayou webhook signing secret?
* How do I handle `new_bill`, `bills_ready` or `intervals_ready` events?
* How do I know when a customer must re-authenticate (`customer_must_reauthenticate`)?
* Why is my Bayou `webhook-signature` verification failing?
* How do I dedupe Bayou webhook retries when the payload has no event ID?

## Verification (core)

| Header | Value |
| --- | --- |
| `webhook-id` | Unique message ID |
| `webhook-timestamp` | Unix seconds when the webhook was sent |
| `webhook-signature` | One or more space-separated `v1,<base64 HMAC-SHA256>` entries |

Signed content is `{webhook-id}.{webhook-timestamp}.{raw request body}`. The key is the base64-**decoded** part of the secret after `whsec_`. There is one secret per company. The examples use the `standardwebhooks` library (npm, PyPI), which reads the three headers, tries every `v1` entry in constant time and returns the parsed body.

```javascript
const { Webhook } = require('standardwebhooks');

// rawBody: exact request body string, NOT re-serialised JSON.
// secret: the full "whsec_..." value from Settings in the Bayou dashboard.
function verifyBayouWebhook(rawBody, headers, secret = process.env.BAYOU_ENERGY_WEBHOOK_SECRET) {
  return new Webhook(secret).verify(rawBody, {
    'webhook-id': headers['webhook-id'],
    'webhook-timestamp': headers['webhook-timestamp'],
    'webhook-signature': headers['webhook-signature'],
  }); // returns { event, object }; throws → respond 400
}

```

Python: `from standardwebhooks.webhooks import Webhook`, then `Webhook(secret).verify(await request.body(), headers)` (catch `Exception`, since malformed headers raise a plain `ValueError`).

> **Timestamp window.** The library always enforces a fixed **5-minute** window. Hookdeck retries and replays resend the **original** timestamp, so the library rejects a retry that arrives more than 5 minutes after the first attempt. If you receive through Hookdeck, use the manual verifier in [references/verification.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/bayou-energy-webhooks/references/verification.md), where the window can be dropped or widened.

> **For complete handlers with tests**, see [examples/express/](https://github.com/hookdeck/webhook-skills/tree/main/skills/bayou-energy-webhooks/examples/express/), [examples/nextjs/](https://github.com/hookdeck/webhook-skills/tree/main/skills/bayou-energy-webhooks/examples/nextjs/), [examples/fastapi/](https://github.com/hookdeck/webhook-skills/tree/main/skills/bayou-energy-webhooks/examples/fastapi/). They read the `webhook-*` headers and fall back to `svix-*` when `webhook-id` is absent, as Hookdeck does.

## Event Envelope

```json
{ "event": "customer_must_reauthenticate",
  "object": { "id": 12345, "external_id": "MSCOTT123", "reason": "credentials_are_invalid",
              "onboarding_token": "...", "onboarding_link": "https://bayou.energy/companies/12345/sign_up?key=..." } }

```

`event` sits beside `object` on every example. `object` is the bill or the customer, depending on the event. There is **no event ID** in the payload, so dedupe on the `webhook-id` header.

## Common Event Types

The docs list seven webhooks (the list may not be exhaustive):

| Event | `object` | Fired when |
| --- | --- | --- |
| `new_bill` | Bill | A new bill was discovered |
| `updated_bill` | Bill | A bill was updated |
| `bills_ready` | Customer (`bills_parsed`) | The initial bill discovery finished for a customer |
| `intervals_ready` | Customer (`available_data`) | The initial interval discovery finished for a customer |
| `customer_has_filled_credentials` | Customer | A customer shared valid utility credentials |
| `new_unparsed_bill` | Bill (`status: unparsed`) | A bill was discovered but couldn't be parsed yet |
| `customer_must_reauthenticate` | Customer (`reason`) | A customer must share credentials again (`credentials_are_invalid` or `mfa_factor_has_expired`) |

> **Full payloads:** [references/overview.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/bayou-energy-webhooks/references/overview.md) and [Bayou's webhook docs](https://docs.bayou.energy/reference/list-of-webhooks).

## Delivery Semantics

* Bayou POSTs JSON to the company's **single** webhook URL; every webhook goes there.
* Verification is optional on Bayou's side: deliveries are sent whether or not you verify. Verify anyway.
* Bayou doesn't state a retry policy, so make handlers idempotent and respond with a `2xx` quickly.
* `new_unparsed_bill.object.file_url` is a short-lived pre-signed URL and `customer_must_reauthenticate.object.onboarding_token` is a credential. Don't log them.

## Environment Variables

```bash
BAYOU_ENERGY_WEBHOOK_SECRET=whsec_xxxxx   # full value incl. whsec_; handlers fail closed (500) without it

```

Get it from the [Bayou dashboard](https://bayou.energy/dashboard) under **Settings**, just below the Webhook URL field.

## Local Development

```bash
# Express / Next.js (use 8000 for FastAPI). No install or account required.
npx hookdeck-cli listen 3000 bayou-energy --path /webhooks/bayou-energy

```

Paste the printed URL into the Webhook URL field in **Settings** in the Bayou dashboard. Bayou's fake utility lets you trigger events like `customer_must_reauthenticate` with a test customer.

## Reference Materials

* [references/overview.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/bayou-energy-webhooks/references/overview.md) - Event catalog and payload fields
* [references/setup.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/bayou-energy-webhooks/references/setup.md) - Webhook URL, signing secret, testing
* [references/verification.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/bayou-energy-webhooks/references/verification.md) - Library and manual verification, window handling, debugging