> ## 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.

# Third-Party Login

> Designed for customer-consented access.

## Get customer-consented access via OAuth 2.0

Standard authorization-code flow with PKCE. Your app (a HEMS, an EV charger, a home-automation hub) redirects the customer to `/oauth/authorize` with your `client_id` and pre-registered `redirect_uri`. After they approve on a Nomos-hosted consent page, your backend exchanges the resulting code at `/oauth/token` for a short-lived access token plus a rotating refresh token.

<div
  style={{
display: "grid",
gridTemplateColumns: "repeat(3, 1fr)",
gap: "1rem",
}}
>
  <Frame caption="Step 1: customer enters their Nomos email">
    <img src="https://mintcdn.com/riverslate/rFuRSKXuhnC74OsD/images/oauth-sign-in.png?fit=max&auto=format&n=rFuRSKXuhnC74OsD&q=85&s=8d4300a7a3fa87ba1bc223d99ba3bc63" alt="Hosted sign-in page asking the customer for the email address tied to their Nomos contract" style={{ height: "320px", width: "100%", objectFit: "contain" }} width="1260" height="1764" data-path="images/oauth-sign-in.png" />
  </Frame>

  <Frame caption="Step 2: customer enters the one-time code">
    <img src="https://mintcdn.com/riverslate/rFuRSKXuhnC74OsD/images/oauth-verify.png?fit=max&auto=format&n=rFuRSKXuhnC74OsD&q=85&s=63f03fa8d32dfc4d7cc02fb92c6920d6" alt="Hosted verification page with six input boxes for the one-time code" style={{ height: "320px", width: "100%", objectFit: "contain" }} width="1458" height="1768" data-path="images/oauth-verify.png" />
  </Frame>

  <Frame caption="Step 3: customer grants the requested access">
    <img src="https://mintcdn.com/riverslate/rFuRSKXuhnC74OsD/images/oauth-consent.png?fit=max&auto=format&n=rFuRSKXuhnC74OsD&q=85&s=50b965805d4a6f31e10525f34a81d627" alt="Hosted consent screen listing the data scopes the application is requesting, with allow and deny buttons" style={{ height: "320px", width: "100%", objectFit: "contain" }} width="1378" height="1800" data-path="images/oauth-consent.png" />
  </Frame>
</div>

<Warning>
  This is the right flow if you act on behalf of a customer. If you're an
  organization on Nomos and just need server-to-server access to your own data,
  use the [Client Credentials
  grant](/api-references/authentication#client-credentials-grant) instead.
</Warning>

## What you can do with the access token

Tokens minted through this flow are scoped to a single customer. They authorize the same read endpoints the customer sees in their portal: subscriptions, prices, consumption, invoices. They don't authorize writes.

Access tokens last 60 minutes. Refresh tokens rotate on every use, so always persist the new one and call `/oauth/token` again before the access token expires. For full request and response shapes, including PKCE details, see [Authentication](/api-references/authentication#authorization-code-grant).

Once you have tokens, continue with [Load shifting and optimization](/guides/load-shifting) to pull prices and drive flexible loads.

## FAQ

<AccordionGroup>
  <Accordion title="Why PKCE if I'm exchanging on the server?">
    PKCE protects the authorization code from interception in transit, even on a
    server-to-server flow. It costs nothing to add and closes a class of
    redirect-URI attacks.
  </Accordion>

  <Accordion title="What happens when a refresh fails?">
    An `UNAUTHORIZED` response means the customer has revoked access (or the
    refresh token expired). Send them through `/oauth/authorize` again to mint a
    fresh pair.
  </Accordion>

  <Accordion title="Can I refresh from the browser?">
    No. Refresh tokens must stay on the server. Build a thin endpoint on your
    side that proxies the refresh and hands the new access token to the client
    if needed.
  </Accordion>

  <Accordion title="Can a customer authorize multiple third-party apps?">
    Yes. Each app gets its own token pair. Revoking one doesn't affect the
    others.
  </Accordion>
</AccordionGroup>
