Authentication: API keys and OAuth 2.1
FreshlyCited accepts two kinds of credentials. Use an API key for scripts, CI and MCP clients where you can set a header. Use OAuth for connectors like Claude.ai and ChatGPT, where you sign in instead of pasting a secret.
The story · 3 steps
Get an API keyFree plan: 10 free links to try (once you verify your email), then 100 free checks a month, no card.
| API key | OAuth 2.1 | |
|---|---|---|
| Best for | Scripts, REST, Claude Code, Cursor, VS Code | Claude.ai, ChatGPT, Claude Desktop connectors, any MCP client that supports OAuth |
| Works on | REST API and MCP | MCP only (/mcp) |
| Acts as | The key (its workspace and role) | You, in the workspace you pick on the consent screen |
| Lifetime | Until revoked | Access token 1 hour, refresh token 30 days (rotated) |
| Revoke | API keys page | API keys › Connected apps, or /oauth/revoke |
API keys
Create a key under API keys in the app (admins and owners). The secret starts with ipk_ and is shown once. Send it as a bearer token:
bash
curl https://freshlycited.com/api/v1/me -H "Authorization: Bearer ipk_YOUR_KEY"X-Api-Key: ipk_… works too. A key belongs to one workspace (your agency or a client) and sees only that workspace and the clients under it. Its role decides what it can do: client_viewer keys are read-only. Each key can have its own rate limits and daily credit cap.
OAuth 2.1 for connectors
FreshlyCited implements the MCP authorization spec, so compliant clients discover everything from the server URL:
- The client calls
https://freshlycited.com/mcpwithout a token and gets 401 withWWW-Authenticate: Bearer resource_metadata="…/.well-known/oauth-protected-resource/mcp", scope="mcp". - It reads the protected resource metadata (RFC 9728), which names FreshlyCited as the authorization server.
- It reads the authorization server metadata (RFC 8414).
- It identifies itself with a Client ID Metadata Document (an https
client_idURL) or registers through dynamic client registration at/oauth/register(RFC 7591). - It sends you to
/oauth/authorizewith PKCE S256 andresource=https://freshlycited.com/mcp(RFC 8707). - You sign in with your normal FreshlyCited login and see the consent screen: pick the workspace and the access level.
- The client exchanges the code at
/oauth/tokenand calls the MCP server withAuthorization: Bearer fca_….
Scopes
| Scope | Access |
|---|---|
mcp | Full access with your role in the chosen workspace: push links, run checks (spends credits), manage clients if your role allows |
mcp:read | Read-only: pushes, checks, results, credits and reports. Tools that change anything return 403 |
Tokens
- Access tokens (
fca_…) last 1 hour and only work on/mcp; they're bound to that resource and rejected by the REST API. - Refresh tokens (
fcr_…) last 30 days and rotate on every use. If an old refresh token is used again, the whole connection is revoked for safety. - The authorization response includes
iss(RFC 9207). Redirect URIs must match exactly, except loopback URIs (http://127.0.0.1/localhost), where the port may differ. - Revoke with
POST /oauth/revoke(RFC 7009), or disconnect the app under API keys › Connected apps. Removing you from the workspace also cuts the connection off.
Errors
| Status | Meaning |
|---|---|
| 401 | No credentials, an unknown or revoked key, or an expired access token. MCP responses include WWW-Authenticate so OAuth clients can sign in again. |
| 403 | Your role (or a read-only connection) doesn't allow this, or the account is waiting for approval |
| 429 | Rate limit reached: wait for Retry-After seconds |