PPactDocs
Developers

OAuth in 5 minutes

Connect a third-party app to a Pact workspace with the Authorization Code + PKCE flow.

If you are building an app that other people connect to their Pact workspace, use OAuth — not a shared API key. OAuth lets a workspace admin grant your app a scoped, revocable token without ever handing over a long-lived secret.

Use a static API key only for your own back-office scripts.

Step 1 — Register your app

A workspace admin registers OAuth apps under Admin → API & developers (/admin/api-developers). You receive a client_id and, for confidential clients, a client_secret. You also set:

  • Redirect URIs — exact URLs Pact may send the user back to.
  • Scopes — the permissions your app may request. See the scope reference.

Public clients (single-page apps, mobile, CLIs) must use PKCE and do not get a client secret.

Step 2 — Send the user to authorize

Redirect the workspace user to /oauth/authorize with a PKCE challenge:

text
https://app.pact.place/oauth/authorize
  ?response_type=code
  &client_id=YOUR_CLIENT_ID
  &redirect_uri=https://yourapp.com/callback
  &scope=read:contacts%20write:contacts
  &state=RANDOM_STATE
  &code_challenge=BASE64URL_SHA256_OF_VERIFIER
  &code_challenge_method=S256

The user reviews the requested scopes and approves. Pact redirects to your redirect_uri with ?code=…&state=…. Verify state matches what you sent.

ts
import crypto from "node:crypto";

const verifier = crypto.randomBytes(32).toString("base64url");
const challenge = crypto.createHash("sha256").update(verifier).digest("base64url");
// store `verifier` in the session; send `challenge` in the authorize URL

Step 3 — Exchange the code for tokens

bash
curl -X POST https://app.pact.place/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d grant_type=authorization_code \
  -d code=THE_CODE \
  -d redirect_uri=https://yourapp.com/callback \
  -d client_id=YOUR_CLIENT_ID \
  -d code_verifier=THE_VERIFIER

You get an access token (valid 1 hour), a refresh token (valid 30 days), and the granted scope:

json
{
  "access_token": "…",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "…",
  "scope": "read:contacts write:contacts"
}

Step 4 — Call the API

Use the access token exactly like an API key:

bash
curl https://app.pact.place/v1/contacts?limit=10 \
  -H "Authorization: Bearer ACCESS_TOKEN"

When it expires, refresh it:

bash
curl -X POST https://app.pact.place/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d grant_type=refresh_token \
  -d refresh_token=THE_REFRESH_TOKEN \
  -d client_id=YOUR_CLIENT_ID

Server-to-server (no user)

For backend integrations with no human in the loop, use the client credentials grant with a confidential client:

bash
curl -X POST https://app.pact.place/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d grant_type=client_credentials \
  -d client_id=YOUR_CLIENT_ID \
  -d client_secret=YOUR_CLIENT_SECRET \
  -d scope=read:deals

Revocation

Workspace admins can revoke your app at any time from the Installed tab of Admin → API & developers, and you can revoke a token yourself with POST /oauth/revoke. Always request the minimum scopes — admins approve faster and trust least-privilege apps.

What's next?