# ProductLift API and MCP authentication

This page explains how to authenticate against the ProductLift REST API and how to connect an MCP client. It is written for developers and AI agents. Product overview: https://www.productlift.dev/llms.txt. Developer resources: https://www.productlift.dev/developers/.

## Overview

ProductLift has two programmatic surfaces:

| Surface | URL | Auth | Best for |
|---|---|---|---|
| REST API v1 | `https://{your-portal}/api/v1` | Portal API key as Bearer token | Integrations, imports, syncs, scripts |
| MCP server | `https://{your-portal}/mcp` | OAuth 2.1 (PKCE, dynamic client registration) | Claude, ChatGPT, Cursor and other agents acting on behalf of a portal admin |

`{your-portal}` is the hostname of your ProductLift portal, for example `feedback.yourcompany.com` or `yourcompany.productlift.dev`. Every portal has its own API keys and its own MCP endpoint. ProductLift's own public portal at `https://app.productlift.dev/mcp` works as a reference instance.

- OpenAPI 3.0 specification: https://www.productlift.dev/openapi.json (YAML: https://www.productlift.dev/openapi.yaml)
- Interactive reference: https://developer.productlift.dev/docs/api
- MCP overview and client setup: https://www.productlift.dev/mcp/

## REST API: getting an API key

1. Sign in to your portal as an admin.
2. Open **Customize**, then **API & Webhooks**.
3. Click **Create API key**. Give it a name, choose **full access** or **read-only**, and optionally set an expiry date.
4. Copy the key and store it in a secret manager. It is shown once.

Requirements:

- API access is included on the Pro and Business plans. Starter portals receive a `403` with the message `API access requires a Pro plan or above.`
- Keys belong to one portal. A key used against another portal's hostname returns `403 API token does not have access to this portal`.
- Read-only keys can only call `GET` endpoints. A write attempt returns `403 This API key is read-only and cannot perform write operations.`

## REST API: using the key

```bash
curl https://your-portal.productlift.dev/api/v1/posts \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json"
```

- Responses are JSON. Request bodies are sent as form fields or JSON.
- Rate limit: 60 requests per minute per key. Over the limit the API returns `429` with a `Retry-After` header.
- Errors are JSON objects with a `message` field. Validation errors (`422`) add an `errors` object keyed by field name. Missing or invalid keys return `401 {"message": "Unauthenticated."}`.

## MCP server: connecting a client

The MCP server exposes the same capabilities as the REST API as tools (posts, comments, votes, users, statuses, categories, tabs, moderation). Transport is Streamable HTTP with JSON-RPC 2.0.

1. Add `https://{your-portal}/mcp` as a remote MCP server in your client (Claude.ai connectors, Claude Code, Cursor, ChatGPT). Use your portal's own hostname; the tools then act on that portal only.
2. The client receives `401` with `WWW-Authenticate: Bearer resource_metadata="https://{your-portal}/.well-known/oauth-protected-resource"` and discovers the authorization server (`https://app.productlift.dev`, shared by all portals) from that document.
3. The client registers itself (RFC 7591 dynamic client registration) and starts an authorization-code flow with PKCE (`S256`). Sign in as a portal admin and approve access on the consent screen.
4. The client receives an access token (valid 1 hour) and a refresh token (valid 30 days) and calls tools with `Authorization: Bearer <token>`.

Metadata documents:

- Authorization server (RFC 8414), same for every portal: https://app.productlift.dev/.well-known/oauth-authorization-server
- Protected resource (RFC 9728), per portal: `https://{your-portal}/.well-known/oauth-protected-resource` (example: https://app.productlift.dev/.well-known/oauth-protected-resource)
- Authorization endpoint: https://app.productlift.dev/oauth/authorize
- Token endpoint: https://app.productlift.dev/oauth/token
- Registration endpoint: https://app.productlift.dev/oauth/register

## Scopes and permissions

- OAuth scope `mcp`: access the portal through the MCP server with the permissions of the admin who authorized the connection. This is currently the only scope. Individual tools apply their own read and write checks.
- REST API keys carry an ability of either full access or `read`. Use read-only keys for reporting integrations and full-access keys only where writes are needed.
- Neither surface can reach portals the authorizing admin cannot access in the dashboard.

## Revoking access

- REST API: delete the key under Customize > API & Webhooks. It stops working immediately.
- MCP: disconnect the server in your MCP client. Access tokens expire after 1 hour and refresh tokens after 30 days. To force-revoke an active connection earlier, contact support via https://www.productlift.dev/contact/.

## Security notes

- Never embed an API key in client-side code or a public repository.
- Rotate keys by creating a new one, switching your integration, then deleting the old one.
- Report security issues via https://www.productlift.dev/security/.

## Machine-readable discovery

- OpenAPI: https://www.productlift.dev/openapi.json
- MCP server card: https://www.productlift.dev/.well-known/mcp/server-card.json
- API catalog (RFC 9727): https://www.productlift.dev/.well-known/api-catalog
- Agentic Resource Discovery catalog: https://www.productlift.dev/.well-known/ard.json
- Pricing: https://www.productlift.dev/pricing.md
