Authentication

Secure access, simplified — authenticate with OAuth 2 and start building with confidence

Ballpark uses OAuth 2.0 to authorise API requests on behalf of users.
Depending on your use case, you may either generate a personal access token (suitable for local development and internal scripts) or implement the full OAuth 2.0 flow to obtain tokens on behalf of other users.

Personal Access Tokens

For local development or internal tooling, you can generate a personal access token and bypass the full OAuth flow.

Important: Personal access tokens do not expire. Treat them as highly sensitive credentials. If a token is compromised, revoke it immediately from your account settings.

OAuth 2.0 Overview

Ballpark supports OAuth 2.0 as well as the PKCE extension for native and client-side applications.

Before you can request tokens, you must register an application at:
ballparkhq.com/oauth/applications/

Choosing a Client Type

The client type is determined by your application architecture:

  • Public client — for applications where secrets cannot be safely stored, such as single-page web applications, mobile apps, or desktop clients.

  • Confidential client — for applications with a backend server under your control, where secrets can be securely kept.

Supported Grant Types

Ballpark supports the following OAuth 2.0 grant types:

  • Authorisation Code — Recommended for confidential clients. Supports token refresh and offers greater security.

  • Implicit — Designed for public clients without a server component. Simpler to implement but less secure, and does not support refresh tokens.

Guidelines:

  • Confidential clients must use the authorisation_code flow.

  • Public clients may use the implicit flow, but if refresh tokens are required (e.g. in native apps), you must implement the authorisation_code + PKCE flow.

Implementing the Authorisation Flow

The exact implementation depends on your chosen grant type.

Authorisation Code Flow (without PKCE)

1. Redirect the user to Ballpark

Direct the user to Ballpark’s authorisation endpoint:

https://ballparkhq.com/oauth/authorize?
    state=<random_string>&
    client_id=<client_id>&
    response_type=code&
    redirect_uri=<redirect_uri>&
    scope=<space-separated_scopes>

Parameters:

  • client_id — Your registered application’s client ID

  • redirect_uri — A registered redirect URI

  • scope — A space-separated list of scopes

  • state — A randomly generated string used to mitigate CSRF

The user will be asked to grant or deny access.

2. Handle the Redirect

  • If access is denied, the user will be redirected to your redirect_uri with:

error=access_denied

If access is granted, the user will be redirected with:

code=<authorisation_code>&state=<state>

Verify that the state matches the value you initially supplied.

3. Exchange the Code for a Token

Make a POST request to the token endpoint:

https://ballparkhq.com/oauth/token/

Request body (application/x-www-form-urlencoded):

Name

Value

client_id

<client_id>

client_secret

<client_secret>

code

<code>

grant_type

authorization_code

redirect_uri

<redirect_uri>

Successful response:

{
  "access_token": "<access_token>",
  "expires_in": 36000,
  "refresh_token": "<refresh_token>",
  "scope": "<scope>",
  "token_type": "Bearer"
}

Error Responses

  • 401 invalid_grant — The provided authorisation code or refresh token is invalid, expired, revoked, does not match the registered redirection URI, or was issued to another client.

Authenticating Requests

Once you have obtained an access token, include it in the Authorization header of your API requests:

Authorization: Bearer <access_token

If the token is invalid or expired, the API will return a 401 response. In this case, you must either refresh the token or re-authorise the user.

Refreshing Access Tokens

Access tokens expire after 7 days. To refresh an access token, send a request to:

https://ballparkhq.com/oauth/token/

Request body (application/x-www-form-urlencoded):

Name

Value

client_id

<client_id>

client_secret

<client_secret>

refresh_token

<refresh_token>

grant_typegrant_type

refresh_token

scope

<scopes>

Response:

{
  "access_token": "<new_access_token>",
  "expires_in": 36000,
  "refresh_token": "<new_refresh_token>",
  "scope": "<scope>",
  "token_type": "Bearer"
}

Available Scopes

Follow the principle of least privilege and request only the scopes your application requires.

  • user:read — Read user profile data, including email address

  • projects:read — Read project data and collaborators

  • projects:write — Create and modify projects and collaborators

  • projects:delete — Delete user projects

  • projects.comments:write — Add, edit, and delete project comments

  • company:read — Read company and member data

  • company.projects:read — Read company projects

  • company.teams:write — Create and manage company teams

  • teams:read — Read team and member data