pocketsmith-ts
v1.1.0
Published
TypeScript client library for PocketSmith API
Maintainers
Readme
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-fetchfor excellent performance - ✅ Authentication - Supports both API keys and OAuth2
Installation
npm install pocketsmith-tsQuick Start
Using API Key (Developer Key)
import { createPocketSmithClient } from 'pocketsmith-ts';
const client = createPocketSmithClient({
apiKey: 'your-api-key-here'
});
// Get current user
const { data: user } = await client.GET('/me');
console.log(user);
// Get user's accounts
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({
// API base URL (optional, defaults to https://api.pocketsmith.com/v2)
baseUrl: 'https://api.pocketsmith.com/v2',
// For personal use - get from https://my.pocketsmith.com/api_keys
apiKey: 'your-developer-key',
// For OAuth apps - obtained through OAuth flow
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.
// Fetch all accounts for a user
const { data: accounts } = await client.GET('/users/{id}/accounts', {
params: { path: { id: userId } }
});
// Get specific account details
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.
// Fetch transaction accounts for an account
const { data: transactionAccounts } = await client.GET('/accounts/{id}/transaction_accounts', {
params: { path: { id: accountId } }
});
// Get transactions for a specific transaction account
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'
}
}
});
// Create a transaction in a specific transaction account
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
// Get transactions for a high-level account grouping
const { data: accountTransactions } = await client.transactions.getByAccount(123, {
start_date: '2024-01-01',
end_date: '2024-12-31',
search: 'coffee'
});
// Get transactions for a specific transaction account (where transactions are posted)
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
// Create a category
const { data: category } = await client.POST('/users/{id}/categories', {
params: { path: { id: userId } },
body: {
title: 'Coffee & Drinks',
colour: '#8B4513',
is_bill: false
}
});
// Update a category
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) {
// Use serializeError to properly format errors (no more [object Object])
console.error('API Error:', serializeError(error));
console.error('Full error object:', error);
// Handle error case
return;
}
// Use data safely here
console.log(data.name);Type Safety
All API responses and request bodies are fully typed:
// user is typed as components["schemas"]["User"]
const { data: user } = await client.GET('/me');
// TypeScript knows about all user properties
console.log(user.id, user.name, user.email);
// Request body is also typed
await client.POST('/users/{id}/categories', {
params: { path: { id: userId } },
body: {
title: 'Required field',
colour: '#FF0000', // Optional but typed
// TypeScript will error if you use invalid properties
}
});Testing
Running Tests
# Run all tests
npm test
# Run only integration tests (requires API key)
npm run test:integration
# Run with coverage
npm test -- --coverageIntegration 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:integrationOr create a .env file (copy from .env.example):
cp .env.example .env
# Edit .env with your API keyNote: 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 generateThis will:
- Download the latest OpenAPI spec from PocketSmith's GitHub repo
- Generate TypeScript types and interfaces
- Update the client accordingly
Building
npm run buildDevelopment Mode
npm run devAuthentication
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
apiKeyoption
OAuth2
For applications that other users will use:
- Contact PocketSmith at [email protected] to register your app
- Implement the OAuth2 flow to get access tokens
- Use tokens with the
accessTokenoption
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
