> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.videogen.io/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.videogen.io/_mcp/server.

# OAuth 2.1 with VideoGen

> Use OAuth 2.1 (authorization code with PKCE) to let users authorize your application to call the VideoGen API on their behalf. Covers discovery, the authorization flow, scopes, and using the access token.

## Overview

**Sign in with VideoGen** lets your application act on behalf of a VideoGen user without ever handling their API key. Instead of asking each user to create and paste an API key, you send them through a standard OAuth 2.1 flow: they sign in to VideoGen, approve the access your app requests, and VideoGen returns an access token your app uses to call the API.

Use OAuth when you're building a product that connects to *other people's* VideoGen accounts — an integration platform, an AI agent or MCP client, or any multi-tenant app. If you're calling the API from your own backend, an [API key](/authentication) is simpler.

> **Note**
>
> Both auth methods produce the same kind of credential: a bearer token sent in the `Authorization` header. Everything else in these docs — endpoints, request shapes, pagination, webhooks — works identically whether you authenticated with an API key or an OAuth access token.

## Discovering the authorization server

The API advertises its authorization server using [OAuth 2.0 Protected Resource Metadata (RFC 9728)](https://datatracker.ietf.org/doc/html/rfc9728). Fetch it to learn which authorization server issues tokens for the API:

```bash
curl https://api.videogen.io/.well-known/oauth-protected-resource
```

```json
{
  "resource": "https://api.videogen.io",
  "authorization_servers": ["https://<authorization-server>"],
  "bearer_methods_supported": ["header"],
  "resource_documentation": "https://docs.videogen.io"
}
```

Take the entry in `authorization_servers` and read *its* metadata document at `/.well-known/oauth-authorization-server` to get the concrete `authorization_endpoint`, `token_endpoint`, and supported PKCE methods. Discovering endpoints this way — rather than hardcoding them — keeps your integration working if they ever change.

Unauthenticated requests to the API also return a `WWW-Authenticate` challenge pointing back at the metadata, which is how OAuth-aware clients (including AI agents and MCP clients) can discover the flow automatically:

```
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="VideoGen API", resource_metadata="https://api.videogen.io/.well-known/oauth-protected-resource"
```

## Registering your application

To obtain a `client_id` (and, for confidential clients, a `client_secret`), register your application with VideoGen. Reach out through [the developer dashboard](https://app.videogen.io/api) to register a client, providing:

* Your application name and logo (shown to users on the consent screen)
* One or more **redirect URIs** (where VideoGen sends users back after they approve)
* The **client type**: `public` (mobile, CLI, SPA, or any client that can't keep a secret — uses PKCE) or `confidential` (a server-side app that can hold a `client_secret`)

AI agents and MCP clients that support [Dynamic Client Registration (RFC 7591)](https://datatracker.ietf.org/doc/html/rfc7591) can register automatically via the authorization server's `registration_endpoint`.

## The authorization code flow (with PKCE)

VideoGen uses OAuth 2.1, so **PKCE is required for every client** (public and confidential alike).

#### Create a PKCE code verifier and challenge

Generate a random `code_verifier`, then derive its `code_challenge` as the base64url-encoded SHA-256 of the verifier (`code_challenge_method=S256`).

#### Redirect the user to the authorization endpoint

Send the user to the `authorization_endpoint` from discovery with your query parameters:

```
GET {authorization_endpoint}
  ?response_type=code
  &client_id=YOUR_CLIENT_ID
  &redirect_uri=YOUR_REDIRECT_URI
  &scope=email%20profile
  &state=RANDOM_STATE
  &code_challenge=CODE_CHALLENGE
  &code_challenge_method=S256
```

The user signs in to VideoGen and approves the scopes your app requested. VideoGen redirects back to your `redirect_uri` with `?code=...&state=...`. Verify `state` matches what you sent.

#### Exchange the code for tokens

Exchange the authorization code at the `token_endpoint`, including the `code_verifier` you generated in step 1. Confidential clients also send their `client_secret`.

```bash
curl -X POST {token_endpoint} \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d grant_type=authorization_code \
  -d code=AUTHORIZATION_CODE \
  -d redirect_uri=YOUR_REDIRECT_URI \
  -d client_id=YOUR_CLIENT_ID \
  -d code_verifier=CODE_VERIFIER
```

```json
{
  "access_token": "...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "..."
}
```

#### Call the API with the access token

Send the access token as a bearer token, exactly like an API key:

```bash
curl https://api.videogen.io/v1/me \
  -H "Authorization: Bearer ACCESS_TOKEN"
```

#### Refresh when the token expires

Access tokens are short-lived. When one expires (or the API returns `401`), use the `refresh_token` to get a new access token:

```bash
curl -X POST {token_endpoint} \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d grant_type=refresh_token \
  -d refresh_token=REFRESH_TOKEN \
  -d client_id=YOUR_CLIENT_ID
```

## Scopes

An OAuth access token acts on behalf of the user with the **same access their account has**. It can call every endpoint an API key for that user's team can. The `scope` parameter currently controls only which identity claims are shared; it does not narrow API access. Users see a plain-language summary of each requested scope on the consent screen before they approve.

| Scope     | Shown to the user as                                      |
| --------- | --------------------------------------------------------- |
| `email`   | View your email address                                   |
| `profile` | View your basic profile                                   |
| `openid`  | Verify your identity (returns an OpenID Connect ID token) |

Combine scopes with a space, e.g. `scope=email profile`. Requesting no scope defaults to `email`.

> **Note**
>
> Granular API scopes (e.g. read-only vs. read-write access) are planned. Until then, treat any access token as full-access on the user's behalf and store it as securely as an API key.

## Managing connected apps

Users can review and revoke the apps they've connected at any time from the **Connected apps** section of the [developer dashboard](https://app.videogen.io/api). Revoking access immediately invalidates that app's tokens.

## Using OAuth with AI agents

Because the API publishes protected-resource metadata and returns a `WWW-Authenticate` challenge on `401`, OAuth-aware AI clients can discover and complete the flow on their own. See [Use with AI agents](/use-with-ai-agents) and the [MCP server](/libraries/mcp) guide for connecting ChatGPT, Claude, and other agents.