If you’re trying to use your Claude Max subscription with OpenClaw instead of a paid API key, you’re in for a ride. The docs are incomplete, the CLI wizard doesn’t work properly, and you’ll hit multiple 401 errors before figuring it out. Here’s the actual working setup.

The Problem

OpenClaw supports Anthropic as a model provider. You can either use an API key (straightforward) or your Claude Max/Pro subscription via OAuth (not straightforward). The openclaw models auth add wizard offers a “setup-token (claude)” option that asks you to paste a token from the Claude Max webpage. This doesn’t work.

Why It Doesn’t Work

The “Authentication Code” you copy from the Claude Max webpage is not a usable bearer token. It’s a one-time auth code that needs to be exchanged for real OAuth credentials (access token + refresh token). The OpenClaw wizard doesn’t do this exchange. It just stores the raw code and tries to use it directly, which Anthropic rejects.

What You’ll See

Depending on how you configure the auth profile, you’ll cycle through these errors:

  • HTTP 401 authentication_error: invalid x-api-key — OpenClaw is sending the token as an API key instead of Bearer auth
  • HTTP 401 authentication_error: Invalid bearer token — Correct auth method, but the token is the raw auth code, not an exchanged OAuth token
  • No API key found for provider "anthropic" — You set type: "oauth" but OpenClaw doesn’t recognize the profile format

The Fix

Step 1: Log in with Claude Code CLI

Install Claude Code CLI if you haven’t:

npm install -g @anthropic-ai/claude-code

Then log in:

claude auth login

This opens a browser-based OAuth flow. Complete it. Verify with:

claude auth status

You should see subscriptionType: "max" (or “pro”).

Step 2: Find the real OAuth tokens

Claude Code stores the exchanged tokens at:

cat ~/.claude/.credentials.json

You’ll see something like:

{
  "claudeAiOauth": {
    "accessToken": "sk-ant-oat01-...",
    "refreshToken": "sk-ant-ort01-...",
    "expiresAt": 1773867825944,
    "subscriptionType": "max"
  }
}

These are the real tokens you need.

Step 3: Write the OpenClaw auth profile

Edit ~/.openclaw/agents/main/agent/auth-profiles.json:

{
  "version": 1,
  "profiles": {
    "anthropic:default": {
      "type": "oauth",
      "provider": "anthropic",
      "access": "sk-ant-oat01-YOUR_ACCESS_TOKEN_HERE",
      "refresh": "sk-ant-ort01-YOUR_REFRESH_TOKEN_HERE",
      "expires": 1773867825944
    }
  },
  "usageStats": {}
}

Copy the exact values from ~/.claude/.credentials.json:

  • accessToken access
  • refreshToken refresh
  • expiresAt expires

Step 4: Update openclaw.json

Make sure your ~/.openclaw/openclaw.json has a matching auth section:

{
  "auth": {
    "profiles": {
      "anthropic:default": {
        "provider": "anthropic",
        "mode": "oauth"
      }
    }
  }
}

Key detail: mode must be "oauth", not "token".

Step 5: Restart the gateway

openclaw gateway restart --force

Step 6: Verify

openclaw models status

You should see your anthropic profile listed with oauth type. Send a test message through the UI or Discord.

Things That Don’t Work

  • openclaw models auth add “setup-token (claude)” — Stores the raw auth code, doesn’t exchange it. Will always 401.
  • openclaw models auth setup-token — Expects a sk-ant-oat01- prefixed token, but the webpage gives you a raw code without that prefix.
  • openclaw models auth paste-token — Writes a type: "token" profile, which sends the value as x-api-key instead of Bearer auth.
  • Manually prepending sk-ant-oat01- to the webpage code — The code is not a valid token regardless of prefix. It needs the OAuth exchange.

Token Expiry

The access token expires (check the expires timestamp). OpenClaw should handle refresh automatically using the refresh token. If it stops working after a while, repeat steps 2-5 to grab fresh tokens from Claude Code CLI.

TL;DR

Don’t use OpenClaw’s auth wizard. Log in with claude auth login, steal the real OAuth tokens from ~/.claude/.credentials.json, and write them into OpenClaw’s auth-profiles.json manually.