PocketSmith TypeScript Client
A fully-typed TypeScript client library for the PocketSmith API, automatically generated from their official OpenAPI specification.
Features
- ✅ Fully typed - Complete TypeScript definitions for all API endpoints
- ✅ Auto-generated - Built directly from PocketSmith's official OpenAPI spec
- ✅ Zero boilerplate - Minimal configuration required
- ✅ Modern - Built with
openapi-fetch for excellent performance
- ✅ Authentication - Supports both API keys and OAuth2
Installation
npm install pocketsmith-ts
Quick Start
Using API Key (Developer Key)
import { createPocketSmithClient } from 'pocketsmith-ts';
const client = createPocketSmithClient({
apiKey: 'your-api-key-here'
});
const { data: user } = await client.GET('/me');
console.log(user);
const { data: accounts } = await client.GET('/users/{id}/accounts', {
params: { path: { id: user.id } }
});
Using OAuth2
const client = createPocketSmithClient({
accessToken: 'your-oauth-token-here'
});
const { data: user } = await client.GET('/me');
Configuration
const client = createPocketSmithClient({
baseUrl: 'https://api.pocketsmith.com/v2',
apiKey: 'your-developer-key',
accessToken: 'your-oauth-token',
});
Understanding Accounts vs Transaction Accounts
PocketSmith has two types of account endpoints that serve different purposes:
Accounts (/accounts/{id})
High-level account groupings that represent conceptual account containers. These are used for organizing and categorizing your financial structure.
const { data: accounts } = await client.GET('/users/{id}/accounts', {
params: { path: { id: userId } }
});
const { data: account } = await client.GET('/accounts/{id}', {
params: { path: { id: accountId } }
});
Transaction Accounts (/transaction_accounts/{id})
Individual accounts where transactions are actually posted. These represent the actual bank accounts, credit cards, etc. where money moves in and out.
const { data: transactionAccounts } = await client.GET('/accounts/{id}/transaction_accounts', {
params: { path: { id: accountId } }
});
const { data: transactions } = await client.GET('/transaction_accounts/{id}/transactions', {
params: {
path: { id: transactionAccountId },
query: {
start_date: '2024-01-01',
end_date: '2024-12-31'
}
}
});
const { data: transaction } = await client.POST('/transaction_accounts/{id}/transactions', {
params: { path: { id: transactionAccountId } },
body: {
payee: 'Coffee Shop',
amount: -4.50,
date: '2024-01-15'
}
});
Examples
Fetching Transactions
Using Standard API Endpoints
const { data: transactions } = await client.GET('/users/{id}/transactions', {
params: {
path: { id: userId },
query: {
start_date: '2024-01-01',
end_date: '2024-12-31',
search: 'coffee',
type: 'debit'
}
}
});
Using Convenience Methods
const { data: accountTransactions } = await client.transactions.getByAccount(123, {
start_date: '2024-01-01',
end_date: '2024-12-31',
search: 'coffee'
});
const { data: transactionAccountTransactions } = await client.transactions.getByTransactionAccount(456, {
start_date: '2024-01-01',
end_date: '2024-12-31',
type: 'debit'
});
Creating a Transaction
const { data: transaction } = await client.POST('/transaction_accounts/{id}/transactions', {
params: {
path: { id: transactionAccountId }
},
body: {
payee: 'Coffee Shop',
amount: -4.50,
date: '2024-01-15',
category_id: categoryId,
note: 'Morning coffee'
}
});
Managing Categories
const { data: category } = await client.POST('/users/{id}/categories', {
params: { path: { id: userId } },
body: {
title: 'Coffee & Drinks',
colour: '#8B4513',
is_bill: false
}
});
const { data: updated } = await client.PUT('/categories/{id}', {
params: { path: { id: category.id } },
body: {
title: 'Coffee & Beverages',
colour: '#654321'
}
});
Error Handling
The client returns a { data, error } object for each request. For better error debugging, use the serializeError utility:
import { createPocketSmithClient, serializeError } from 'pocketsmith-ts';
const client = createPocketSmithClient({ apiKey: 'your-key' });
const { data, error } = await client.GET('/me');
if (error) {
console.error('API Error:', serializeError(error));
console.error('Full error object:', error);
return;
}
console.log(data.name);
Type Safety
All API responses and request bodies are fully typed:
const { data: user } = await client.GET('/me');
console.log(user.id, user.name, user.email);
await client.POST('/users/{id}/categories', {
params: { path: { id: userId } },
body: {
title: 'Required field',
colour: '#FF0000',
}
});
Testing
Running Tests
npm test
npm run test:integration
npm test -- --coverage
Integration Tests
Integration tests require a valid PocketSmith API key. Set it as an environment variable:
export POCKETSMITH_API_KEY=your_api_key_here
npm run test:integration
Or create a .env file (copy from .env.example):
cp .env.example .env
Note: Integration tests make real API calls to PocketSmith and may count against your API rate limits.
Development
Updating the OpenAPI Spec
The client is automatically generated from PocketSmith's official OpenAPI specification. To update:
npm run generate
This will:
- Download the latest OpenAPI spec from PocketSmith's GitHub repo
- Generate TypeScript types and interfaces
- Update the client accordingly
Building
npm run build
Development Mode
npm run dev
Authentication
Developer Keys
For personal use or simple integrations, you can generate a developer key:
- Log into PocketSmith
- Go to Settings → Security & Integrations
- Create a new developer key
- Use it with the
apiKey option
OAuth2
For applications that other users will use:
- Contact PocketSmith at api@pocketsmith.com to register your app
- Implement the OAuth2 flow to get access tokens
- Use tokens with the
accessToken option
See PocketSmith's OAuth documentation for details.
License
MIT
Contributing
- Fork the repository
- Create your feature branch
- Make your changes
- Add tests if applicable
- Submit a pull request
Author
John Barton - @joho
Links