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

# Sign in with CostGraph

> Let your own tools sign people in with CostGraph and read cost and usage for one tenant

Sign in with CostGraph lets an application you build authenticate people with their CostGraph account and read cost and usage data on their behalf. It uses standard OAuth 2.0 and OpenID Connect.

Each client belongs to one tenant. Only users of that tenant can sign in through it, and its tokens can only read that tenant.

## Create a client

Tenant admins create clients in **Settings > OAuth clients**.

* A confidential client runs on a server and can keep a secret. CostGraph shows the client secret a single time, at creation. Rotate it to get a new one.
* A public client, such as a single-page or desktop app, has no secret and sends only its `client_id`.

Every client must use PKCE, public or confidential.

## Endpoints

Read every endpoint from the discovery document:

```text theme={null}
https://api.costgraph.ai/.well-known/openid-configuration
```

The same document is also served at `/.well-known/oauth-authorization-server`.

| Endpoint | URL |
| - | - |
| Authorization | `https://app.costgraph.ai/oauth/authorize` |
| Token | `https://api.costgraph.ai/api/v1/oauth/token` |
| Revocation | `https://api.costgraph.ai/api/v1/oauth/revoke` |
| User info | `https://api.costgraph.ai/api/v1/oauth/userinfo` |
| Signing keys | `https://api.costgraph.ai/.well-known/jwks.json` |

## Sign in

CostGraph uses the authorization code flow with PKCE. The `S256` method is required.

<Steps>
  <Step title="Send the user to CostGraph">
    Generate a random `code_verifier`, then derive `code_challenge` as the base64url SHA-256 of it. Redirect the user to the authorization endpoint:

    ```text theme={null}
    https://app.costgraph.ai/oauth/authorize
      ?response_type=code
      &client_id=YOUR_CLIENT_ID
      &redirect_uri=https%3A%2F%2Fexample.com%2Fcallback
      &scope=openid%20profile%20email%20usage%3Aread
      &state=RANDOM_STATE
      &nonce=RANDOM_NONCE
      &code_challenge=CODE_CHALLENGE
      &code_challenge_method=S256
    ```

    The user reviews the permissions and approves. CostGraph redirects to your `redirect_uri` with `code` and `state`. The code expires after 1 minute.
  </Step>

  <Step title="Exchange the code for tokens">
    Confidential clients authenticate with `client_secret_basic` or `client_secret_post`. Public clients omit the secret and send `client_id` in the body.

    ```shell theme={null}
    curl -X POST https://api.costgraph.ai/api/v1/oauth/token \
      -u "$CLIENT_ID:$CLIENT_SECRET" \
      -d grant_type=authorization_code \
      -d code="$CODE" \
      -d redirect_uri=https://example.com/callback \
      -d code_verifier="$CODE_VERIFIER"
    ```

    The response contains `access_token`, `refresh_token`, `expires_in`, and, when you requested `openid`, `id_token`.
  </Step>

  <Step title="Call CostGraph">
    Send the access token as a bearer token. The user info endpoint requires the `openid` permission and returns `403` without it.

    ```shell theme={null}
    curl https://api.costgraph.ai/api/v1/oauth/userinfo \
      -H "Authorization: Bearer $ACCESS_TOKEN"
    ```
  </Step>
</Steps>

## Permissions

Request permissions with the `scope` parameter. The user sees them on the approval screen.

| Scope | Lets the app |
| - | - |
| `openid` | Sign the user in and receive an `id_token` |
| `profile` | Read the user's name |
| `email` | Read the user's email address |
| `usage:read` | Read resource usage, recommendations, and anomalies |
| `billing:read` | Read cost and billing data |

## Tokens

The following table lists the lifetime of each credential.

| Token | Lifetime | Notes |
| - | - | - |
| Access token | 1 hour | RS256 JWT. Verify it with the signing keys. |
| Refresh token | 30 days | Rotates on every use. |
| Authorization code | 1 minute | Single use. |

Exchange a refresh token with `grant_type=refresh_token`. Each exchange returns a new refresh token, and you must store it. If you present a refresh token that was already exchanged (the previous one), CostGraph signs the user out of your app. Older tokens fail with `invalid_grant`.

The `id_token` carries these claims:

| Claim | Value |
| - | - |
| `sub` | Stable user identifier |
| `aud` | Your `client_id` |
| `nonce` | The `nonce` you sent. Check that it matches. |
| `email` | The user's email, with the `email` scope |
| `name` | The user's name, with the `profile` scope |

## Sign out

Revoke a token when the user signs out of your app. Confidential clients authenticate with the client secret:

```shell theme={null}
curl -X POST https://api.costgraph.ai/api/v1/oauth/revoke \
  -u "$CLIENT_ID:$CLIENT_SECRET" \
  -d token="$REFRESH_TOKEN"
```

Public clients send `client_id` instead:

```shell theme={null}
curl -X POST https://api.costgraph.ai/api/v1/oauth/revoke \
  -d client_id="$CLIENT_ID" \
  -d token="$REFRESH_TOKEN"
```

Revoking any token from a sign-in ends that whole sign-in. Unknown tokens still return `200`.

Users can also remove your app themselves in **Settings > Connected apps**. If a tenant admin deletes the client, everyone is signed out of it.

## Errors

Errors come from three places: the sign-in redirect, the token endpoints, and API calls.

### Sign-in errors

The following errors are returned to your `redirect_uri` as the `error` query parameter.

| Error | Meaning |
| - | - |
| `invalid_scope` | The app asked for a permission the client isn't allowed. |
| `access_denied` | The user denied the request. |
| `invalid_target` | The requested resource is unknown. |

### Token errors

The token and revocation endpoints return these errors as JSON.

| Error | Status | Meaning |
| - | - | - |
| `invalid_request` | 400 | A parameter is missing or malformed. |
| `invalid_client` | 401 | The `client_id` is unknown, or the secret is wrong or missing. |
| `invalid_grant` | 400 | The code or refresh token is expired, already used, or doesn't match the `redirect_uri` or `code_verifier`. |
| `unsupported_grant_type` | 400 | The `grant_type` isn't supported. |

### API errors

If you call an endpoint that your granted permissions don't cover, CostGraph returns `403` with the message `This application is not allowed to access this resource`. Request the missing scope and have the user approve it again.

## Next steps

<CardGroup cols={2}>
  <Card title="MCP" icon="plug" href="/costgraph/mcp/install">
    Connect an AI agent to CostGraph.
  </Card>
</CardGroup>


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