Developer Guide

OAuth 2.0 Client Credentials

Authenticate server-side integrations without a user session using the industry-standard Client Credentials flow (RFC 6749 §4.4).

Overview

The Client Credentials grant is designed for server-to-server integrations where there is no user present - CI pipelines, cron jobs, backend services, and SaaS platform integrations. Your application exchanges a client_id / client_secret pair for a short-lived Bearer access token.

Token endpoint

POST https://pollslive.com/api/oauth/token

Token TTL

3600 seconds (1 hour)

Plan required

Pro or Enterprise

When to use OAuth vs API keys

ScenarioRecommended credential
Personal automation / scriptsAPI key (plv_live_…)
Internal server process, one workspaceAPI key
SaaS product integrating PollsLive for multiple customersOAuth Client Credentials per customer workspace
Zero-trust rotation without downtimeOAuth (tokens expire automatically) or API key rotation
Scope-limited third-party accessOAuth with scopes

1. Create an OAuth client

Go to Studio → Developer API → OAuth 2.0 Clients and click Create OAuth client. Give the client a descriptive name (e.g. My Backend Service) and optionally narrow the scopes.

Alternatively, use the management API:

Create an OAuth client
curl -X POST https://pollslive.com/api/oauth/clients \
  -H "Cookie: next-auth.session-token=<your session>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "My Backend Service",
    "scopes": ["polls:read", "polls:write"]
  }'

# Response (save clientSecret - shown exactly once):
# {
#   "client": { "id": "…", "clientId": "plv_cid_…", "name": "My Backend Service", … },
#   "clientSecret": "plv_cs_…"
# }
Save your clientSecret immediately. Like an API key, it is shown exactly once and never stored in plaintext.

2. Get an access token

Send a POST request to the token endpoint using application/x-www-form-urlencoded (the RFC standard) or application/json (for convenience):

Request - form-urlencoded (RFC standard)
curl -X POST https://pollslive.com/api/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials&client_id=plv_cid_…&client_secret=plv_cs_…&scope=polls:read polls:write"
Request - JSON (convenience)
curl -X POST https://pollslive.com/api/oauth/token \
  -H "Content-Type: application/json" \
  -d '{
    "grant_type": "client_credentials",
    "client_id": "plv_cid_…",
    "client_secret": "plv_cs_…",
    "scope": "polls:read polls:write"
  }'
Response
{
  "access_token": "plv_oauth_…",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "polls:read polls:write"
}

Errors follow RFC 6749 §5.2 format: { "error": "invalid_client", "error_description": "…" }

3. Use the token

Include the access_token as a Bearer token on every API request - exactly the same as an API key:

Authenticated request
curl https://pollslive.com/api/v1/polls \
  -H "Authorization: Bearer plv_oauth_…"

Your application should cache the token and re-request only when expires_in is approaching (e.g. refresh when less than 5 minutes remain).

Token lifetime & refresh

Tokens are valid for 1 hour (expires_in: 3600). There is no refresh token - simply request a new token with your client credentials when the current one expires. Since this is a server-side flow, the client secret never leaves your backend.

Token rotation pattern (Node.js)
let token = null;
let expiresAt = 0;

async function getToken() {
  if (token && Date.now() < expiresAt - 5 * 60 * 1000) return token;

  const res = await fetch("https://pollslive.com/api/oauth/token", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      grant_type: "client_credentials",
      client_id: process.env.OAUTH_CLIENT_ID,
      client_secret: process.env.OAUTH_CLIENT_SECRET,
    }),
  });
  const data = await res.json();
  token = data.access_token;
  expiresAt = Date.now() + data.expires_in * 1000;
  return token;
}

Scopes

Scopes let you limit what an OAuth client can do. If you don't specify any scopes when creating the client, it inherits full workspace access (equivalent to an API key).

See the full Scopes Reference for the complete list.

Revoke a client

Revoking a client immediately invalidates all tokens issued for it. Existing in-flight requests using a token will fail with 401 invalid_oauth_token.

Revoke via API
curl -X DELETE https://pollslive.com/api/oauth/clients/CLIENT_DB_ID \
  -H "Cookie: next-auth.session-token=<your session>"

Or go to Studio → Developer API → OAuth 2.0 Clients and click Revoke.

Still have questions?

Our team is happy to help.

Contact us
OAuth 2.0 - PollsLive Developer Docs | PollsLive