CommonPaper API Docs
Documentation

Third party integration

In addition to API keys, third-party applications can authenticate users with Common Paper via OAuth 2.0 using the Authorization Code flow with PKCE.

Common Paper registers your application in our identity provider. You supply the details below, receive credentials, and implement the authorize and token exchange steps in your own app.

Register your application

To get started, contact Common Paper at support@commonpaper.com and provide:

FieldRequiredDescription
NameYesA descriptive name for your application
Allowed Callback URLsYesWhere users are redirected after login (e.g. https://app.example.com/callback or a custom scheme like myapp://callback)
ImageRecommendedAn icon or logo for your application shown on the consent / login experience
DescriptionNoShort description of your application
Allowed Logout URLsNoWhere users may be redirected after logout
Allowed Web OriginsNoOrigins allowed for silent auth / CORS (typical for SPAs)
Allowed Origins (CORS)NoAdditional CORS origins if needed

Applications are registered as Regular Web Applications (server-side apps that can keep a client secret).

After registration, Common Paper will provide you with:

  • Client ID
  • Client Secret

Store the client secret securely. Do not expose it in client-side code or public repositories.

Endpoints

PurposeEndpoint
Authorization (start login)GET https://auth.commonpaper.com/authorize
Token exchange / refreshPOST https://auth.commonpaper.com/oauth/token
Revoke refresh tokenPOST https://auth.commonpaper.com/oauth/revoke
User infoGET https://auth.commonpaper.com/userinfo

PKCE flow

Once you have your client credentials, implement the Authorization Code + PKCE flow as follows.

Step 1: Generate PKCE values

Before redirecting the user, generate these values on your side:

  • code_verifier: a cryptographically random string (43–128 characters)
  • code_challenge: BASE64URL-ENCODE(SHA256(code_verifier))
  • code_challenge_method: S256

Keep the code_verifier secret until the token exchange step.

Create a code verifier

The code_verifier is a cryptographically random, Base64URL-encoded value that you later send when exchanging the authorization code for tokens. Example in Node.js (from Auth0's PKCE guide):

JavascriptCode
// Dependency: Node.js crypto module // https://nodejs.org/api/crypto.html#crypto_crypto function base64URLEncode(str) { return str .toString("base64") .replace(/\+/g, "-") .replace(/\//g, "_") .replace(/=/g, ""); } const verifier = base64URLEncode(crypto.randomBytes(32));

Step 2: Redirect the user to authorize

Send the user to the authorization endpoint:

Code
GET https://auth.commonpaper.com/authorize? response_type=code &code_challenge=<code_challenge> &code_challenge_method=S256 &client_id=<CLIENT_ID> &redirect_uri=<CALLBACK_URL> &scope=openid profile email offline_access &audience=https://integration.commonpaper.com/ &state=<random_value>
ParameterDescription
response_typeMust be code
code_challengeThe PKCE challenge from step 1
code_challenge_methodMust be S256
client_idThe Client ID issued at registration
redirect_uriMust match one of your registered Allowed Callback URLs
scopeRecommended: openid profile email offline_access (offline_access is required to receive a refresh token)
audienceMust be https://integration.commonpaper.com/
stateRecommended random value for CSRF protection

After the user authenticates, Auth0 redirects to your redirect_uri with:

Code
?code=<AUTHORIZATION_CODE>&state=<state>

Verify that state matches the value you sent.

Using the state parameter

The state parameter helps prevent CSRF attacks and can also restore application state after login (for example, sending the user back to the page they intended to visit). See Auth0's guide on state parameters for full details.

Recommended flow:

  1. Before redirecting to /authorize, generate a random, non-guessable string (a nonce):

    Code
    xyzABC123
  2. Store it locally (cookie or session for regular web apps; local storage for SPAs; memory or local storage for native apps), along with any app state you want to restore later:

    JSONCode
    { "xyzABC123": { "redirectUrl": "/protectedResource" } }
  3. Include it on the authorize request:

    Code
    https://auth.commonpaper.com/authorize?...&state=xyzABC123
  4. On the callback, compare the returned state to the value you stored. If they match, accept the response and use any stored app state (such as redirectUrl). If they do not match, reject the response.

JavascriptCode
if (receivedState === retrieveStateStoredLocally()) { // Authorized request } else { // This response is not for us, reject it }

Keep state unique and opaque. If you get a 414 Request-URI Too Large error, use a smaller value.

Step 3: Exchange the code for tokens

From your backend, exchange the authorization code for tokens:

Code
POST https://auth.commonpaper.com/oauth/token Content-Type: application/x-www-form-urlencoded grant_type=authorization_code &client_id=<CLIENT_ID> &client_secret=<CLIENT_SECRET> &code=<AUTHORIZATION_CODE> &redirect_uri=<CALLBACK_URL> &code_verifier=<code_verifier>

A successful response looks like:

JSONCode
{ "access_token": "...", "refresh_token": "...", "scope": "...", "token_type": "Bearer", "expires_in": 86400 }

Use the access_token as a Bearer token when calling the Common Paper API:

TerminalCode
curl -X GET "https://api.commonpaper.com/v1/agreements" \ -H "Authorization: Bearer ACCESS_TOKEN"

Refreshing an access token

When the access token expires, use the refresh token to obtain a new one:

Code
POST https://auth.commonpaper.com/oauth/token Content-Type: application/x-www-form-urlencoded grant_type=refresh_token &client_id=<CLIENT_ID> &client_secret=<CLIENT_SECRET> &refresh_token=<REFRESH_TOKEN> &scope=<optional, space-delimited, must be a subset of the original scopes>

Revoking a refresh token

When a user disconnects or you otherwise need to invalidate a refresh token, revoke it from your backend:

Code
POST https://auth.commonpaper.com/oauth/revoke Content-Type: application/x-www-form-urlencoded client_id=<CLIENT_ID> &client_secret=<CLIENT_SECRET> &token=<REFRESH_TOKEN>
ParameterDescription
client_idThe Client ID issued at registration
client_secretThe Client Secret issued at registration
tokenThe refresh token to revoke

A successful revoke returns an empty 200 OK response. After revocation, the refresh token can no longer be used to obtain new access tokens.

User info

You can retrieve the authenticated user's profile with:

Code
GET https://auth.commonpaper.com/userinfo Authorization: Bearer ACCESS_TOKEN
Last modified on