Skip to main content

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.

After you’ve authenticated a customer in your own app or system, you can drop them straight into the white-labeled Nomos portal — invoices, meter readings, prices, payment method, account settings — as a fully logged-in user. The entry point is a single endpoint, POST /admin/magic_link, which returns a short-lived URL you hand to the customer. No password, no second sign-in. Keep your existing identity system (your own login, your SSO), and call this endpoint whenever a customer needs to view their energy account.
If you’d rather build your own UI, see Build your own Customer Portal.

Integration

Prerequisites

The plan the customer is on needs a hosted customer portal configured; ask Nomos support to enable one before you start minting links. You’ll also need the Nomos customer.id for the customer you’re signing in. Store this on your end when the subscription is created so you can map your user records to ours. Call POST /admin/magic_link from your backend with the customerId:
const res = await fetch("https://api.nomos.energy/admin/magic_link", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${access_token}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    customerId: "cus_abc123",
  }),
});

const { link } = await res.json();
The response is a magic_link object with a single link field:
{
  "object": "magic_link",
  "link": "https://acme-power.customerportal.energy/auth/confirm?token_hash=…&type=magiclink&next=/overview"
}
When the customer opens the link, the portal verifies the token, creates a server-side session (cookie-based), and redirects to /overview. They stay signed in until the session expires; subsequent visits to the same subdomain reuse the session, no fresh magic link required.
If the customer exists on Nomos but has no subscription yet, the response link points at the hosted checkout for your plan (/start) instead of the portal. You can use the same call regardless of state — the link always lands the customer in the right place.
See Create a magic link.

2. Redirect the customer

The URL itself is safe to send to the browser; only the access token used to mint it must stay server-side. The simplest pattern: a handler in your app mints the link and redirects.
// e.g. GET /portal in your own app
app.get("/portal", requireAuth, async (req, res) => {
  const { link } = await fetch("https://api.nomos.energy/admin/magic_link", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${access_token}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ customerId: req.user.nomosCustomerId }),
  }).then((r) => r.json());

  res.redirect(link);
});
A “View invoices” button in your dashboard becomes a plain link to /portal — every click mints a fresh, single-use URL. In a partner mobile app, mint the link from your backend and open it in an in-app webview (SFSafariViewController on iOS, Custom Tabs on Android, or a WebView component in React Native). The customer stays inside your app shell while the portal renders inside.
// React Native sketch
const { link } = await api.post("/portal-link"); // your own backend
navigation.navigate("PortalWebView", { url: link });

Security and lifecycle

The magic link is a credential. Treat it like one.
  • Server-side only. Only your backend should call POST /admin/magic_link. Your access token (or client_secret) must never reach the browser. The resulting link can be sent to the browser — that’s the whole point — but the call that minted it cannot.
  • One-time use. Once the customer (or anything else) opens the link, the token is consumed. A second click won’t sign them in.
  • Short-lived. The link expires shortly after issuance. Don’t email it days in advance, don’t cache it across sessions, don’t paste it into a notification queue that runs hours later.
  • Mint per request. Generate a fresh link every time the customer clicks “View invoices” (or whatever your entry point is). There is no rate concern at human click frequencies.