Authenticating with the API
How to get an access token with OAuth 2.0, which scopes exist, and what the legacy API keys are.
Last updated 15 August 2026
Every API request carries a bearer token:
Authorization: Bearer <token>
Two kinds of token work. OAuth 2.0 access tokens are the recommended kind; legacy API keys exist for older clients.
Scopes
| Scope | Grants |
|---|---|
temponia:read |
Every GET endpoint |
temponia:write |
Creating, updating and deleting time entries and expenses |
A request without the scope it needs gets 403 with
{"error":"insufficient_scope"}. A missing, expired or revoked token gets
401.
The OAuth 2.0 flow
Temponia implements the standard authorization code flow, and PKCE is required. First register a custom OAuth application to get a client id and secret.
1. Send the user to authorize
Generate a random code_verifier, derive the S256 code_challenge from it,
and open:
https://app.temponia.com/oauth/authorize
?client_id=YOUR_CLIENT_ID
&redirect_uri=YOUR_REDIRECT_URI
&response_type=code
&scope=temponia:read temponia:write
&state=RANDOM_STATE
&code_challenge=YOUR_CODE_CHALLENGE
&code_challenge_method=S256
The user signs in to Temponia if needed, sees what your app is asking for, and
authorises it. We then redirect to your redirect_uri with ?code=... and
your state.
2. Exchange the code for tokens
curl -X POST https://app.temponia.com/oauth/token \
-d grant_type=authorization_code \
-d code=THE_CODE \
-d redirect_uri=YOUR_REDIRECT_URI \
-d client_id=YOUR_CLIENT_ID \
-d client_secret=YOUR_CLIENT_SECRET \
-d code_verifier=YOUR_CODE_VERIFIER
The response holds an access_token, a refresh_token, and expires_in.
Access tokens last 2 hours.
3. Call the API
curl https://app.temponia.com/api/v1/projects \
-H "Authorization: Bearer THE_ACCESS_TOKEN"
4. Refresh when it expires
curl -X POST https://app.temponia.com/oauth/token \
-d grant_type=refresh_token \
-d refresh_token=THE_REFRESH_TOKEN \
-d client_id=YOUR_CLIENT_ID \
-d client_secret=YOUR_CLIENT_SECRET
Legacy API keys
Older clients exchange an email and password for a permanent key:
curl -X POST https://app.temponia.com/api/v1/authenticate \
-d [email protected] \
-d password=... \
-d application=my-script
The key in the response works as a bearer token with full access, and it does not expire. It also stops working the moment the user is deactivated. Prefer OAuth applications for anything new: they are scoped, revocable one by one, and never see the user's password. Note that users who sign in with Google, Microsoft or Xero have no password to use here, so OAuth is also the only option that works for everyone.