OAuth Clients

OAuth clients represent third-party applications that access the Snapbooks API on behalf of users. Before an application can use OAuth2 flows (authorization code, client credentials, or refresh token), it must be registered as a client.

There are two ways to register a client:

  • Authenticated registration — Create a client tied to your user account via the authenticated API.
  • Dynamic registration — Self-register a client via the public endpoint without prior authentication (RFC 7591).

For details on how to use OAuth clients in authentication flows, see OAuth2 Authentication.

Endpoints

Method Endpoint Description
POST /oauth/register Dynamic client registration (public)
POST /oauth/clients Create an OAuth client
GET /oauth/clients List your OAuth clients
DELETE /oauth/clients/{client_id} Delete an OAuth client

Dynamic Client Registration

POST /public/v2/oauth/register

Public endpoint for dynamic client registration per RFC 7591. No authentication is required. Rate limited to 10 requests per hour.

Dynamically registered clients are owned by the system user and cannot be listed or managed via the authenticated client endpoints.

Request Body

Field Type Required Description
client_name string Yes Display name for the client application
redirect_uris array Yes Non-empty array of redirect URIs. Each must use HTTPS or be localhost
grant_types array No Allowed grant types. Default: ["authorization_code", "refresh_token"]
response_types array No Allowed response types. Default: ["code"]. Only code is supported
scope string No Requested scope
token_endpoint_auth_method string No Authentication method. Default: client_secret_post. Allowed: client_secret_post, client_secret_basic

Allowed Grant Types

Value Description
authorization_code For user-facing applications
client_credentials For server-to-server access
refresh_token For obtaining new access tokens

Example Request

{
  "client_name": "My Integration",
  "redirect_uris": ["https://myapp.example.com/callback"],
  "grant_types": ["authorization_code", "refresh_token"],
  "scope": "read:accounts"
}

Response

{
  "client_id": "AbCdEfGhIjKlMnOpQrStUv",
  "client_secret": "AbCdEfGhIjKlMnOpQrStUvWxYz0123456789AbCdEfGhIjKl",
  "client_name": "My Integration",
  "redirect_uris": ["https://myapp.example.com/callback"],
  "grant_types": ["authorization_code", "refresh_token"],
  "response_types": ["code"],
  "token_endpoint_auth_method": "client_secret_post",
  "client_id_issued_at": 1712764800
}

Important: Store the client_secret securely — it will not be retrievable later.

Error Responses

Status Description
400 Missing or invalid client_name
400 redirect_uris is missing, not an array, or empty
400 Redirect URI does not use HTTPS and is not localhost
400 Unsupported grant_types or response_types
400 Invalid token_endpoint_auth_method
429 Rate limit exceeded (10 per hour)

Create an OAuth Client

POST /api/v2/oauth/clients

Creates a new OAuth client tied to the authenticated user.

Request Body

Field Type Required Description
client_name string Yes Display name for the client application
redirect_uris string Conditional Space-separated redirect URIs. Required when grant_types includes authorization_code
grant_types string No Space-separated grant types. Default: authorization_code refresh_token
scope string No Requested scope

Example Request

{
  "client_name": "My Accounting App",
  "redirect_uris": "https://myapp.example.com/callback",
  "grant_types": "authorization_code refresh_token",
  "scope": "read:accounts write:transactions"
}

Response

{
  "client_id": "AbCdEfGhIjKlMnOpQrStUv",
  "client_secret": "AbCdEfGhIjKlMnOpQrStUvWxYz0123456789AbCdEfGhIjKl",
  "client_name": "My Accounting App",
  "redirect_uris": "https://myapp.example.com/callback",
  "grant_types": "authorization_code refresh_token",
  "scope": "read:accounts write:transactions"
}

Important: Store the client_secret securely — it will not be retrievable later.

Error Responses

Status Description
400 Missing client_name
400 Missing redirect_uris when using authorization code grant

List OAuth Clients

GET /api/v2/oauth/clients

Returns all OAuth clients owned by the authenticated user. The client_secret is not included in the response.

Response

{
  "clients": [
    {
      "client_id": "AbCdEfGhIjKlMnOpQrStUv",
      "client_name": "My Accounting App",
      "redirect_uris": "https://myapp.example.com/callback",
      "grant_types": "authorization_code refresh_token",
      "scope": "read:accounts write:transactions",
      "created_at": "2026-03-15T10:00:00.000000"
    }
  ]
}

Delete an OAuth Client

DELETE /api/v2/oauth/clients/{client_id}

Deletes an OAuth client and revokes all associated refresh tokens. The client must be owned by the authenticated user.

Path Parameters

Parameter Type Description
client_id string The OAuth client ID

Response

{
  "status": "success",
  "message": "Client deleted"
}

Error Responses

Status Description
400 Client not found or not owned by the authenticated user

Attributes

OAuth Client

Attribute Type Description
client_id string Unique client identifier (read-only)
client_secret string Client secret. Only returned on creation
client_name string Display name for the client application
redirect_uris string or array Allowed redirect URIs. String (space-separated) for authenticated registration, array for dynamic registration
grant_types string or array Allowed OAuth grant types
scope string Token scope
created_at datetime Creation timestamp (read-only, only in list response)

Notes

  • The authenticated endpoints (/api/v2/oauth/clients) use space-separated strings for redirect_uris and grant_types.
  • The dynamic registration endpoint (/public/v2/oauth/register) uses arrays for redirect_uris and grant_types, per RFC 7591.
  • Deleting a client automatically revokes all associated refresh tokens. Access tokens (JWT) remain valid until they expire.
  • Only code is supported as a response_type.