Skip to main content
OAuth apps let your own software, or a third-party tool, act in Campfire on behalf of a real person without anyone sharing a password or an API key. Each person who connects your app sees exactly what it is asking for, picks the workspace it acts in, and can disconnect it at any time. Every request the app makes shows up in a per-connection activity log. Campfire implements the standard OAuth 2.0 authorization code flow with refresh tokens and optional PKCE, so any OAuth 2.0 client library will work. It is also an OpenID Connect provider, so you can use it for “Sign in with Campfire”.

API keys

A single key for a dedicated API user in your own workspace. Best for internal scripts and back-office jobs.

OAuth apps

Each person authorizes your app themselves, with scoped, revocable, audited access. Best for integrations that other people connect to.
Once connected, an app can also add its own buttons, panels, sidebar pages and event subscriptions to Campfire. You can define the whole app in a manifest that you keep in your repository.

Sample app: FakeTax

An open-source Flask app that implements the full OAuth flow with Sign in with Campfire (OpenID Connect), onboarding, buttons, panels, navigation and events. Clone it to see a working integration end to end.

How it works

1

An admin registers the app

A workspace admin creates the app in Campfire, picks the most it may ever access (its scopes), and gets a client ID and client secret.
2

A person authorizes it

Your app sends the person to Campfire’s authorize URL. They sign in, review what the app is asking for, choose a workspace, and click Authorize.
3

Your app exchanges the code for tokens

Campfire redirects back to your app with a one-time code. Your server exchanges it, along with the client secret, for an access token (valid for 1 hour) and a refresh token (valid for 30 days).
4

Your app calls the API

Your app sends Authorization: Bearer <access_token> on API requests. Campfire treats each request as that person in the chosen workspace, limited to the scopes they granted.
Creating and managing OAuth apps requires a Campfire admin. Anyone in a workspace can authorize an app, but the app can never do more than that person is already allowed to do.

Part 1: Register your app

1

Open the Apps page

Go to Settings > Developer > Apps. If you haven’t created an app yet, you’ll see the empty state. Click Create App. Once you have at least one app, the button is New App in the top right.If you already have a manifest, click Create from Manifest (From Manifest once you have apps) and paste it instead. That sets up the details, permissions and extensions in one step.
The Apps on Campfire page with no apps and a Create App button
If you don’t see Apps under Developer, contact your Campfire support team to have OAuth apps turned on for your workspace.
2

Fill in the app details

The Details tab describes your app to the people who will authorize it.
The Details tab of the Create app dialog
The rest of the Details tab, showing the Connect URL, App icon, and Published toggle
Redirect URLs, the Connect URL, and the Manage URL must use https. Plain http is accepted only for localhost, 127.0.0.1, and [::1], so you can develop locally. URLs can’t contain a #fragment or embedded credentials. At authorization time the redirect_uri must exactly match one of the registered URLs, except that loopback addresses (127.0.0.1, [::1]) may use any port.
3

Choose the app's permissions

Switch to the Permissions tab and check the access your app needs. These scopes are the ceiling: the most the app can ever request. People connecting the app are still limited to their own permissions in the workspace they choose.
The Permissions tab with Read, Draft, Write, and Approve columns for each Accounting resource
Permissions are grouped by module (Accounting, Revenue, Reports, Cash Management, Close Management, Organization, Ember AI). Each row is a resource, and each column is an access tier:A higher tier includes the lower ones. For example, checking Write on Invoice Payments also checks Read and Draft. Only check what your integration actually uses. You can widen the scopes later, through a new version, without affecting existing connections.
You can create an app with no permissions. It can then only confirm who signed in and which workspace they chose. For “Sign in with Campfire”, also add the openid, email, and profile scopes; see OpenID Connect.
4

Save and copy your credentials

Click Create App. Campfire shows the app’s credentials:
The App credentials dialog showing Client ID, Client Secret, Auth URL, Access Token URL, and Refresh Token URL
The client secret is shown only once. Copy it before you click Done. If you lose it, rotate it to get a new one (see Rotating the client secret).
Your app now appears on the Apps page with its scope count and its production version. Click Manage to open it.
The Apps page listing FakeTax with 4 scopes and a v1 Production badge, and a Manage button

Part 2: Implement the authorization flow

The examples below use these endpoints:

Step 1: Send the person to Campfire

Generate a random state value and a PKCE verifier, store both in the person’s session, then redirect them to the authorize endpoint:
PKCE is optional for apps that authenticate with a client secret, but we recommend always using it. If you send a code_challenge, you must send the matching code_verifier when you exchange the code.
Here is how to generate the PKCE pair:

Step 2: The person approves access

If the person isn’t signed in, Campfire asks them to sign in first. They then see the consent screen, which shows your app’s icon, name, tagline, and a plain-language list of what it will be able to do:
The Authorize Acme Collections consent screen listing the requested permissions and the workspace
  • Workspace. For a private app, the workspace is fixed to the one that created the app. For a published and approved app, the person picks one of the workspaces they belong to.
  • Authorize redirects to your redirect_uri with code and state:
  • Cancel redirects to your redirect_uri with an error:
Before doing anything else in your callback, check that state matches the value you stored. If it doesn’t, discard the code.

Step 3: Exchange the code for tokens

From your server, POST the code to the token endpoint within 5 minutes. Each code can be used only once. Authenticate with your client ID and secret, either with HTTP Basic auth (shown) or as client_id and client_secret form fields:
Access tokens start with cfa_ and refresh tokens start with cfr_. Store both securely on your server, keyed to the person who connected. The scope field lists exactly what was granted. If the person granted openid, the response also contains an id_token.

Step 4: Call the API

Send the access token as a bearer token:
To find out who connected and which workspace they chose, call the permissions endpoint. This works for every app, including apps with no scopes:
The permissions map is the effective access for this token: the person’s own permissions intersected with the granted scopes. The response above is shortened. What a request can do. Each request runs as the person who authorized the app, in the workspace they chose. It can do only what both that person’s role and the granted scopes allow. An app never inherits admin privileges, even when an admin authorizes it. When a scope is missing, Campfire returns 403 and tells you which scope you need in the WWW-Authenticate header:
Some endpoints are not available to OAuth apps and return 403 with "This endpoint is not available to OAuth apps." Account and credential management (API keys, OAuth app management, connections) is never available to app tokens.

Step 5: Refresh the access token

Access tokens expire after 1 hour. Use the refresh token to get a new pair:
The response has the same shape as the code exchange and contains a new refresh token.
Refresh tokens rotate and can be used only once. Each refresh revokes the old pair, so save the new refresh token before you use the new access token. If an old refresh token is ever reused, Campfire assumes it was stolen and revokes every token for that connection:
The person must then authorize the app again. If several workers share a connection, make sure only one of them refreshes at a time.
Refresh tokens expire after 30 days. Refreshing regularly keeps a connection alive indefinitely, but if a connection goes unused for longer than that, the person needs to reconnect.

Starting the flow from Campfire

If you set a Connect URL, people can also start from Campfire. Clicking Connect on your app’s page under Settings > Connections sends them to your Connect URL. Campfire doesn’t start the OAuth flow itself, because your app has to own the state and PKCE values. Your Connect URL should do exactly what Step 1 does: generate state and a verifier, store them, and redirect to the authorize URL. Campfire adds a return_to parameter with the page the person came from. After the callback, and any setup of your own, you can send them back there. Only redirect if return_to starts with Campfire’s own origin. See Onboarding after connect.

A complete example

This minimal Flask app implements the whole flow: connect, callback, calling the API, and refreshing.
app.py

Sign in with Campfire (OpenID Connect)

Campfire is an OpenID Connect provider on top of the same authorization code flow. Request the openid scope and the token response includes an ID token: a signed JWT that says who authorized your app. Use it to sign people in to your own product with their Campfire account.
1

Add the identity scopes to your app

Add openid, plus email and/or profile if you want those claims, to the app’s allowed_scopes in its manifest or through the API, then promote the version. They grant no access to Campfire data.
2

Request them with a nonce

Include the scopes in scope and send a random nonce, stored in the session with state:
3

Verify the ID token

Exchange the code as usual. The response now has an id_token alongside the access token. Before trusting it, verify it:
  • The signature, with algorithm RS256 and the key named by the token’s kid header, from https://api.meetcampfire.com/.well-known/jwks.json.
  • iss is https://api.meetcampfire.com.
  • aud is your client ID.
  • exp is in the future.
  • nonce equals the value you stored.

ID token claims

An ID token describes the person, not the workspace. To learn which workspace they chose, call the permissions endpoint with the access token. Refreshing a connection that holds openid returns a fresh ID token too, without a nonce. The client_credentials grant never returns one.

UserInfo endpoint

You can also read the same claims with the access token:
It returns 401 with WWW-Authenticate: Bearer error="invalid_token" for an expired or revoked token, and 403 with error="insufficient_scope" if the connection was not granted openid.

Discovery

OpenID Connect libraries can configure themselves from https://api.meetcampfire.com/.well-known/openid-configuration, which lists the issuer, endpoints, jwks_uri, userinfo_endpoint, and supported algorithms. Campfire signs ID tokens with RS256 and uses public subject identifiers. Cache the JWKS, and re-fetch it when a token names a kid you don’t have.

Part 3: Manage connections

Viewing connected apps

Apps connected to your account are listed under Settings > Connections. On the All Connections tab, an app with a category appears in that category’s section (and on the category’s tab) alongside Campfire’s built-in integrations; an app without one appears in the Apps section. The Active tab lists every connected app under Apps, with the last time each one was used.
The Connections page, Active tab, showing Acme Collections under Apps
Click an app to see its description, the scopes you granted, and its Activity log. The log records every connection, token issue, refresh, revocation, and API request the app makes, including the method, path, and response status.
The Acme Collections connection page with Description, Access, and an Activity table of API requests and token events
People see their own activity. Workspace admins see the activity of everyone in the workspace. If the app has a Manage URL, the page also shows Manage in <App>. If it adds buttons, panels, navigation or event subscriptions, workspace admins can switch each one on or off here.

Disconnecting an app

Click Disconnect on the app’s connection page and confirm. The app’s tokens stop working immediately, and it has to be authorized again to reconnect.
The Disconnect Acme Collections confirmation dialog
After a disconnect, API calls with the old token return 401:
Your app should treat a 401 on a refresh, or on a request made right after a refresh, as a lost connection and prompt the person to reconnect.

When access ends automatically

Besides an explicit disconnect, Campfire revokes a connection’s tokens when: Widening an app’s permissions never changes existing connections. People keep what they originally granted until they authorize again.

Part 4: Manage your app

On Settings > Developer > Apps, click Manage on an app’s card to open its page. The tabs are:
The FakeTax app page on the Details tab, with a v1 Production badge and an Actions menu
The Actions menu has View credentials, Discard draft (when there is a development version), and Delete app.

Versions and approval

An app’s details and permissions are versioned, so you can change them without affecting the people who already use your app. The versioned fields are: name, tagline, category, description, icon, redirect URLs, Connect URL, Manage URL, and permissions.
  • Production is the version people authorize, and it’s what the app uses in every workspace.
  • Development is your draft. There’s at most one. The first time you save a change on the Details or Permissions tab (or in the manifest’s app section), Campfire copies production into a new development version and saves your change there. Later saves update the same draft.
The app’s header and its card on the Apps page show both versions:
The FakeTax app page with v1 Production and v2 Development badges, a Promote v2 button, and the note Editing development version 2. Promote it to go live.
The FakeTax card on the Apps page showing v1 Production and v2 Development badges

Testing a development version

You can authorize the development version before it goes live. Add a redirect URL that only the draft has, for example your staging callback, and start the flow with that redirect_uri. Campfire picks the version from the redirect URL:
  • If production registers the redirect_uri, the person authorizes production. Production always wins when both match.
  • If only the development version registers it, the person authorizes the draft, with the draft’s name, details and permissions. Development authorizations are limited to your own workspace.
  • If neither does, the request is rejected.
Narrowing the draft’s permissions immediately narrows any connections made on the draft. Discarding the draft disconnects them.

Promoting

Click Promote vN to make the draft live.
The Promote version 2 to production dialog explaining what happens to existing connections
  • Private apps are promoted immediately.
  • Published or approved apps are submitted to Campfire for review. The button becomes Submit for approval, and the badge shows vN · Pending approval. You can keep testing the draft while it waits. Saving another change withdraws it from review, so you’ll need to submit again.
  • If Campfire approves it, the draft becomes production.
  • If Campfire requests changes, the badge shows vN · Changes requested, and the app page shows a banner with the reviewer’s message. Edit the draft and submit it again.
When a version is promoted, the previous production version is archived and every connection moves to the new version:
Not versioned: allowed domains, the signing secret, buttons, panels, navigation, event subscriptions, and the Published toggle. These take effect as soon as you save.

Rotating the client secret

Choose Actions > View credentials. After the first time, the secret is hidden. Click Rotate secret to generate a new one, which is shown once.
The App credentials dialog with the secret hidden and a Rotate secret button
Rotating keeps the same client ID, but immediately revokes every access and refresh token issued to the app, across every connection. Everyone who connected will need to authorize again. Deploy the new secret right away.
The client secret is separate from the signing secret on the Security tab, which signs webhooks, events and context tokens. Rotating the signing secret doesn’t revoke any tokens.

Deleting

Actions > Delete app asks for confirmation. The app’s credentials stop working immediately and every connection is removed. This cannot be undone.

Private vs. published apps

Publishing is a two-step process. Turn on Published on the Details tab, then contact your Campfire support team to request a review. Until Campfire approves the app, it behaves like a private app. Turning Published off, or losing approval, disconnects every workspace other than your own.

Scopes reference

Scopes have the form <resource>:<tier>, for example invoices:read or bills:write. Request them space-separated in the scope parameter. A higher tier includes lower tiers (write includes draft and read). approve is separate and only covers itself.
The live catalog, with a human-readable description for every scope, is available from GET https://api.meetcampfire.com/ca/api/v1/oauth-apps/scopes using any access token.
These scopes have no tiers and grant no access to Campfire data. They only control what the ID token and UserInfo endpoint return.

Errors and troubleshooting

Authorize endpoint

If the client_id or redirect_uri is invalid, Campfire can’t safely redirect back to you. It responds with 400 and a JSON detail instead: All other problems redirect back to your redirect_uri with error, error_description, and your state: The consent screen itself can also show Authorization unavailable. This happens if the request expired (the person took more than 10 minutes), was already used, or the person doesn’t belong to the workspace a private app is locked to. Start the flow again from your app.

Token endpoint

Errors follow the OAuth 2.0 format: {"error": "...", "error_description": "..."}.
Reusing an authorization code, like reusing a refresh token, revokes the tokens already issued from it.

API requests

Security checklist

  • Keep the client secret on your server. Never put it in front-end code, mobile apps, or source control.
  • Always send and verify state.
  • Use PKCE (S256) on every authorization.
  • When you use OpenID Connect, send a nonce, verify every ID token before trusting it, and key accounts on sub, not email.
  • Request the fewest scopes you need. Prefer draft over write when a human should review changes.
  • Store tokens encrypted, and save each new refresh token before using the new access token.
  • Handle 401 by refreshing once, then prompting the person to reconnect.
  • Rotate the secret immediately if it may have leaked. This also revokes every existing token.
Need help? Contact your Campfire support team and we’re happy to help you build your integration.