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

# Authentication

> Authorize MCP clients with the OAuth 2.0 authorization code flow.

The Lunacal MCP API uses the **OAuth 2.0 authorization code flow**. The user grants consent once in the Lunacal web app. Your client then receives a short-lived access token and a long-lived refresh token, so the user does not have to consent again while the refresh token is valid.

## Tokens

| Token | Lifetime | Used for |
| - | - | - |
| Authorization code | 10 minutes, single use | Exchanging for tokens via `/api/mcp/token` |
| Access token | 1 hour | Authenticating every data request |
| Refresh token | 365 days | Getting a new token pair via `/api/mcp/refresh` |

## Authorization flow

<Steps>
  <Step title="Redirect the user to the consent page">
    Open the user's browser at the Lunacal authorization page:

    ```bash theme={null}
    GET https://app.lunacal.ai/auth/platform/authorize?redirect_uri=<REDIRECT_URI>&state=<STATE>
    ```

    * `redirect_uri` — **required.** Must be registered for your client.
    * `state` — recommended. An opaque random string; it is returned unchanged so you can guard against CSRF.
  </Step>

  <Step title="The user approves access">
    The user signs in (if needed) and clicks **Allow**. Lunacal redirects the browser to your `redirect_uri`:

    ```bash theme={null}
    <REDIRECT_URI>?code=<AUTH_CODE>&state=<STATE>
    ```

    Verify that `state` matches the value you sent.
  </Step>

  <Step title="Exchange the code for tokens">
    Send the code to [`POST /api/mcp/token`](/mcp-api/endpoints/token) within 10 minutes. You receive an `accessToken` and a `refreshToken`.
  </Step>

  <Step title="Call the API">
    Include the access token on every request:

    ```bash theme={null}
    Authorization: Bearer <ACCESS_TOKEN>
    ```
  </Step>

  <Step title="Refresh before expiry">
    When the access token expires (after 1 hour), call [`POST /api/mcp/refresh`](/mcp-api/endpoints/refresh) to get a new token pair.
  </Step>
</Steps>

## Token rotation

Every call to `/api/mcp/refresh` rotates **both** tokens. The refresh token you submit is invalidated immediately.

<Warning>
  Always store the new refresh token returned by `/api/mcp/refresh`. Reusing an old refresh token returns `400`, and the user will need to grant consent again.
</Warning>

## Security best practices

* Keep your client secret on your server. Never ship it in browser or mobile code.
* Store access and refresh tokens encrypted at rest.
* Always send and verify the `state` parameter.
* Refresh tokens proactively using the `expiresAt` value instead of waiting for a `401`.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.