WundertreOS

Token

Exchange an authorization code for tokens, or refresh an expired access token.

POST/oauth-token

These endpoints are used by third-party OAuth integrations (such as Zapier). If you are building a direct server integration, use an API key instead.

Try it
POST

Create an API key in your workspace under Settings → Integrations & API.

Used in two situations:

  1. Exchange an authorization code for an access_token + refresh_token
  2. Refresh an expired access token using a refresh_token

Accepts either application/x-www-form-urlencoded or application/json.

Exchange authorization code

Body
NameTypeDescription
grant_typerequiredstringMust be `authorization_code`.
coderequiredstringThe code received on the redirect.
redirect_urirequiredstringMust match the redirect_uri used in /oauth-authorize.
client_idrequiredstringYour OAuth client ID.
client_secretrequiredstringYour OAuth client secret.
code_verifierstringRequired if a PKCE `code_challenge` was sent on /oauth-authorize. Verified using SHA‑256 (S256).
bash
curl -X POST 'https://api.wundertreos.com/functions/v1/oauth-token' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'grant_type=authorization_code' \
  -d 'code=8f3c2a1d9e7b4f6a5c2d1e0f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b' \
  -d 'redirect_uri=https://your-app.com/callback' \
  -d 'client_id=your_client' \
  -d 'client_secret=your_secret'

Refresh an access token

Each refresh rotates the refresh token — the old one is revoked and a new one is returned alongside the new access token.

Body
NameTypeDescription
grant_typerequiredstringMust be `refresh_token`.
refresh_tokenrequiredstringThe refresh token from a prior exchange.
client_idrequiredstringYour OAuth client ID.
client_secretrequiredstringYour OAuth client secret.

Response

json
{
  "access_token": "8f3c2a1d9e7b4f6a5c2d1e0f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "1d3e5c7f9a1d3e5c7f9a1d3e5c7f9a1d3e5c7f9a1d3e5c7f9a1d3e5c7f9a1d3e",
  "scope": "contacts:read contacts:write webhooks:write"
}

expires_in is always 3600 (1 hour).

Errors

StatuserrorWhen
400invalid_requestMissing grant_type, code, redirect_uri, or refresh_token.
400invalid_grantCode or refresh token is unknown, expired, already used, or was issued to a different client. PKCE verifier mismatch.
400unsupported_grant_typegrant_type is neither authorization_code nor refresh_token.
401invalid_clientMissing or wrong client_id / client_secret.