> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nomos.energy/llms.txt
> Use this file to discover all available pages before exploring further.

# Customer Portal

> Surface a customer's contract, invoices, meter readings, and consumption inside your own app, with no Nomos UI involved.

If you're running a white-labeled energy product on Nomos, your customers should never see our brand. The same API that powers our hosted portal is available to you: the contract, the invoices, the meter readings, the historical consumption.

## What you'll wire up

<Steps>
  <Step title="Read the active subscription">
    [Retrieve a
    subscription](/api-reference/subscriptions/retrieve-a-subscription) returns
    plan, status, address, start and end dates, and projected annual usage.
    Enough to render a "your contract" card.
  </Step>

  <Step title="List invoices">
    [List invoices](/api-reference/invoices/list-invoices) under the
    subscription, with [filters](/api-references/filtering) (`status`,
    `period_start`) and [pagination](/api-references/pagination). Link directly
    to the hosted PDF rather than re-rendering the document.
  </Step>

  <Step title="Submit a meter reading">
    For analog-meter customers, [Create a meter
    reading](/api-reference/usage/create-a-meter-reading) accepts a `value` in
    kWh and a `timestamp`. If the value is implausible, the API rejects it with
    `UNPROCESSABLE_ENTITY`; show that as a soft hint, not a hard error.
  </Step>

  <Step title="Show consumption">
    [Retrieve consumption data](/api-reference/usage/retrieve-consumption-data)
    returns 15-minute intervals (smart meters) or monthly totals (analog). Pair
    it with [Retrieve a price time
    series](/api-reference/prices/retrieve-a-price-time-series) to show "you
    used X kWh during cheap hours."
  </Step>

  <Step title="Keep state fresh">
    Subscribe to [webhooks](/webhooks/introduction); your portal stays in sync
    without a single cron job.
  </Step>
</Steps>

## State you'll listen for

| Webhook                                                               | What changes in the portal                          |
| --------------------------------------------------------------------- | --------------------------------------------------- |
| [`subscription.activated`](/webhooks/events/subscription-activated)   | Unlock the live-contract view, prices, consumption. |
| [`subscription.terminated`](/webhooks/events/subscription-terminated) | Show the offboarding state and end date.            |
| [`subscription.ended`](/webhooks/events/subscription-ended)           | Archive the user.                                   |

## FAQ

<AccordionGroup>
  <Accordion title="How do I authenticate the customer to my own app?">
    Run your own identity. Map your user record to the Nomos `customer.id` (or
    `subscription.id`) and use server-side [Client
    Credentials](/api-references/authentication#client-credentials-grant) when
    calling Nomos.
  </Accordion>

  <Accordion title="Can the customer download invoice PDFs?">
    Yes. Each invoice has a hosted URL on the response. Link to it; don't proxy
    or re-render the document.
  </Accordion>

  <Accordion title="What if the meter reading I receive looks wrong?">
    The API runs plausibility checks against recent values and rejects with
    `UNPROCESSABLE_ENTITY` when something looks off. Surface the rejection as
    "this number looks off, double-check" rather than a fatal error.
  </Accordion>

  <Accordion title="Should I poll for status changes?">
    No. Drive portal state from [webhooks](/webhooks/introduction). The same
    events that change the subscription's `status` trigger your portal's render
    path.
  </Accordion>
</AccordionGroup>
