Authentication
Every request carries a bearer token. There are two ways to get one, and the API cannot tell them apart once it has one — both resolve to a workspace and a scope set, and every downstream query is scoped to that workspace.
Which credential to use
- API keys — for your own scripts, back-office jobs and internal integrations, where there is no user to send through a browser.
- OAuth 2.0 — for anything a third party distributes. The user clicks a button, signs in to Chirply, approves, and never handles a credential.
Scopes are read and write. A token never exceeds the permissions of the workspace member behind it: if a screen is manager-only, so is its operation.
API keys
Create one in the app under Developers. A key looks like chp_live_<32 hex> and is displayed exactly once, at creation time — Chirply stores only its SHA-256 hash for lookup, plus a short display prefix so you can tell keys apart in the UI. A key acts with owner-level access for its workspace: treat it like a password, keep it server-side, and rotate it from the same screen whenever you want (revocation is immediate).
curl https://app.chirply.io/api/v1 \
-H "Authorization: Bearer chp_live_…"That endpoint is the whoami read: it returns the workspace the credential acts for and the scopes it holds. It is the cheapest way to verify a connection — the quickstart starts there.
OAuth 2.0
Standard authorization-code grant, with PKCE and refresh-token rotation. Register your client (name, logo, redirect URIs, scopes) with Chirply first; redirect URIs are matched exactly — no prefixes and no wildcards.
Authorize GET https://app.chirply.io/oauth/authorize
?client_id=…&redirect_uri=…&response_type=code
&scope=read%20write&state=…
&code_challenge=…&code_challenge_method=S256 (PKCE)
Token POST https://app.chirply.io/api/v1/oauth/token
grant_type=authorization_code
&code=…&redirect_uri=…&client_id=…&client_secret=…
&code_verifier=… (PKCE)
Refresh POST https://app.chirply.io/api/v1/oauth/token
grant_type=refresh_token&refresh_token=…The consent screen
The user signs in to Chirply, sees who is asking and what they get, and picks one workspace per connection — the way Stripe and Slack do it. Only workspaces the user can administer are offered, because connecting an integration is a workspace-level decision. The redirect back to you carries the authorization code (short-lived, single-use) and your state.
The token endpoint
POST https://app.chirply.io/api/v1/oauth/token accepts form-encoded or JSON bodies, and client credentials either in the body or as HTTP Basic (RFC 6749 §2.3.1) — use whichever your OAuth library prefers. A successful exchange answers:
{
"access_token": "chp_at_…",
"refresh_token": "chp_rt_…",
"token_type": "bearer",
"expires_in": 28800,
"scope": "read write"
}| Property | Behavior |
|---|---|
| access_token | A bearer credential (chp_at_…) valid for 8 hours (expires_in: 28800). Send it exactly like an API key: Authorization: Bearer chp_at_…. |
| refresh_token | Rotates on every refresh: the token you sent is retired and a new one (chp_rt_…) comes back in the same response. Store the new one every time. |
| PKCE | S256 is the supported challenge method. Public clients (mobile, CLI, single-page) use PKCE in place of a client secret; confidential clients are welcome to send both. |
| redirect_uri | Must byte-for-byte match one you registered, on the authorize request and again on the code exchange. |
| errors | This endpoint speaks RFC 6749: a flat { "error", "error_description" } object your OAuth library already understands — see Errors. |
Connections and revocation
Each connection is one workspace. Users list and revoke their connections in the app under Developers; revoking a connection retires its tokens immediately. Access tokens hold the same authority as an API key for their scopes — and the same rule applies: they never exceed what the approving user can do.
Token hygiene
Token responses are served with Cache-Control: no-store — keep them out of caches and logs on your side too. Authorization codes are single-use; refresh tokens are single-use by rotation. If a refresh ever fails with invalid_grant, send the user back through the authorize step.

Chirply