Skip to main content
If you’re running a white-labeled energy product on Nomos, your customers should never see our brand. The same API that powers our own portal is available to you: the contract, the invoices, the meter readings, the historical consumption. This guide is the recipe for the most common “self-service” surface area: a logged-in user views their subscription details, pulls their invoices, and submits a meter reading.

What you’ll need

  • Server-side auth, with whichever flow fits: Client Credentials for organization-wide access, Authorization Code when you’re acting on behalf of a single customer.
  • A way to identify the requesting customer in your own app. You’ll map your user record to a Nomos subscription.id (or customer.id).

1. Read the active subscription

Most “portal home” pages need exactly one thing: the customer’s current contract.
const res = await fetch(
  `https://api.nomos.energy/subscriptions/${subscriptionId}`,
  { headers: { Authorization: `Bearer ${access_token}` } },
);

const subscription = await res.json();
The response includes the plan, status, delivery address, start/end dates, and the projected annual usage. That’s enough to render a “your contract” card. The full shape is documented under Get a subscription.

2. List invoices

Invoices live under the subscription, paginated and filterable:
const res = await fetch(
  `https://api.nomos.energy/subscriptions/${subscriptionId}/invoices?filter[status][eq]=finalized`,
  { headers: { Authorization: `Bearer ${access_token}` } },
);

const { items, has_more, next_page } = await res.json();
Each invoice has a period_start, period_end, total amount, and a hosted PDF URL. Link directly to that PDF rather than re-rendering the document yourself. See Filtering for the full operator list and Pagination for the cursor pattern.

3. Submit a meter reading

For customers without a smart meter, monthly readings are how billing happens. Let them submit one from your portal:
const res = await fetch(
  `https://api.nomos.energy/subscriptions/${subscriptionId}/meter_readings`,
  {
    method: "POST",
    headers: {
      Authorization: `Bearer ${access_token}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      reading_at: "2026-04-28",
      value: 12345,
    }),
  },
);
If the value is implausibly high or low compared to recent readings, the API rejects it with UNPROCESSABLE_ENTITY. Show that as a “this number looks off, double-check” hint in your UI, not as a hard error. See the errors reference.

4. Show consumption history

For smart-metered customers, you can pull historical consumption directly:
const res = await fetch(
  `https://api.nomos.energy/subscriptions/${subscriptionId}/meter_readings?filter[type][eq]=automatic`,
  { headers: { Authorization: `Bearer ${access_token}` } },
);
Pair this with the price time series to show “you used X kWh during cheap hours and Y kWh during expensive hours.” That’s a number customers actually want to see.

5. Keep state fresh with webhooks

Don’t poll subscriptions or invoices to detect status changes. Subscribe to webhooks instead; your portal stays in sync without a single cron job.
switch (event.topic) {
  case "subscription.activated":
    // unlock the "live contract" portal view
    break;
  case "subscription.terminated":
    // show the offboarding state
    break;
  case "subscription.ended":
    // archive the user
    break;
}

What’s next

Build the checkout that feeds it

Where customers come from before they ever reach this portal.

Display dynamic prices

Add a price chart next to the consumption chart.

Pagination + filtering

Patterns for invoice lists and meter reading history.

Webhooks

Drive portal state off real-time events.