Legacy flow (deprecated)
The original Vacation Tracker OAuth2 hostname at api.app.vacationtracker.io. Kept as a permanent compatibility mapping for existing integrations. New integrations should use auth.vacationtracker.io.
Deprecated hostname. This page documents api.app.vacationtracker.io/oauth/*, the original host. It's kept as a permanent compatibility mapping so existing integrations (notably Zapier) keep working without changes. New integrations should use the modern flow at auth.vacationtracker.io. It's the same API surface, supports both public and confidential clients, and adds PKCE, Dynamic Client Registration, and metadata discovery. Nothing about new integrations requires this hostname.
Overview
- Grant type: Authorization Code (confidential clients only)
- Token format: JWT (issued by AWS Cognito)
- Token lifetime: access tokens expire after 60 minutes, refresh tokens after 365 days
- Authorization codes: single-use, expire after 10 minutes
- PKCE: not supported. Security relies on client secrets, the
stateparameter, and redirect URI validation.
Base URL
All legacy endpoints are served under the /oauth path on the original API host:
https://api.app.vacationtracker.io/oauthThis host is kept alive indefinitely as a compatibility mapping onto the same underlying API. It serves the same routes as the modern base URL (https://auth.vacationtracker.io), so your existing Zapier and confidential-client integrations do not need to migrate.
Flow diagram
Step 1: Redirect to authorization endpoint
Redirect the user's browser to the authorization endpoint with the required parameters:
GET https://api.app.vacationtracker.io/oauth/authorize
?client_id=your-client-id
&redirect_uri=https://yourapp.com/callback
&state=random-csrf-token
&scope=openid email profile
&response_type=code| Parameter | Required | Description |
|---|---|---|
client_id | Yes | Your registered OAuth client ID |
redirect_uri | Yes | Must exactly match a registered redirect URI for your client |
state | Yes | Random string for CSRF protection. You must verify this value when the user returns |
scope | No | Space-separated list of scopes. Defaults to openid |
response_type | No | Must be code. Defaults to code |
Step 2: User authenticates
The authorization endpoint validates your parameters and redirects the user to Vacation Tracker's login page. The user can authenticate via:
- Microsoft account
- Google account
- Slack account
- Email and password
Step 3: User grants permission
After authentication, the user sees a consent screen showing your application's name and the requested scopes. They can approve or deny the request.
Step 4: Receive authorization code
If the user approves, Vacation Tracker redirects back to your redirect_uri with an authorization code and your state value:
https://yourapp.com/callback?code=a1b2c3d4-e5f6-7890-abcd-ef1234567890&state=random-csrf-tokenImportant:
- Verify that the
stateparameter matches what you sent in Step 1 - The authorization code is single-use and expires after 10 minutes
Step 5: Exchange code for tokens
Make a server-side POST request to exchange the authorization code for tokens:
curl -X POST https://api.app.vacationtracker.io/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code" \
-d "code=a1b2c3d4-..." \
-d "redirect_uri=https://yourapp.com/callback" \
-d "client_id=your-client-id" \
-d "client_secret=your-client-secret"Or using HTTP Basic authentication:
curl -X POST https://api.app.vacationtracker.io/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-u "your-client-id:your-client-secret" \
-d "grant_type=authorization_code" \
-d "code=a1b2c3d4-..." \
-d "redirect_uri=https://yourapp.com/callback"Step 6: Receive tokens
On success, you receive a JSON response with your tokens:
{
"access_token": "eyJ...",
"id_token": "eyJ...",
"refresh_token": "eyJ...",
"token_type": "Bearer",
"expires_in": 3600
}access_token: use this to authenticate API requests. Expires in 60 minutes.id_token: contains user identity claims. Expires in 60 minutes.refresh_token: use this to get new access tokens. Valid for 365 days.
Step 7: Use the access token
Include the access token in the Authorization header when calling protected endpoints:
curl https://api.app.vacationtracker.io/oauth/me \
-H "Authorization: Bearer eyJ..."Refreshing tokens
When the access token expires, use the refresh token to get a new one:
curl -X POST https://api.app.vacationtracker.io/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=refresh_token" \
-d "refresh_token=eyJ..." \
-d "client_id=your-client-id" \
-d "client_secret=your-client-secret"Response:
{
"access_token": "eyJ...",
"refresh_token": "eyJ...",
"token_type": "Bearer",
"expires_in": 3600
}The same refresh token is returned. Vacation Tracker does not rotate refresh tokens.
Error handling
If something goes wrong, the authorization endpoint returns an error as a JSON response:
{
"error": "invalid_client",
"error_description": "Unknown client_id"
}See Endpoints for the complete list of error codes per endpoint.