5.8 KiB
title
| title |
|---|
| Using the API |
import { Method, MethodBox } from './types';
The API gives you full programmatic access to your data. If you are a developer, you can use this to import transactions from a custom source, export data to another app like Excel, or write anything you want on top of Actual.
One thing to keep in mind: Actual is not like most other apps. While your data is stored on a server, the server does not have the functionality for analyzing details of or modifying your budget. As a result, the API client contains all the code necessary to query your data and will work on a local copy. Right now, the primary use case is custom importers and exporters.
Getting started
We provide an official node.js client in the @actual-app/api package. Other languages are not supported at this point.
The client is open-source on GitHub along with the rest of Actual if you want to see the code.
Install it with either npm or yarn:
npm install --save @actual-app/api
yarn add @actual-app/api
Next, you’ll need to point the API at your budget data. There are two ways to do this.
Connecting to the server files directly
If you’re able to run the @actual-app/api package on the same computer that has the Actual server running, you can connect directly to the server files. This is the easiest way to get started.
let api = require('@actual-app/api');
await api.init({
// This is the UUID from Settings → Show advanced settings → Budget ID
budgetId: 'abcdef',
config: {
// This is the path to the `user-files` folder created by actual-server
dataDir: '/path/to/user-files',
},
});
let budget = await api.getBudgetMonth('2019-10');
console.log(budget);
await api.shutdown();
This code will load the budget file and print out the result of getBudgetMonth. Read the reference docs to see all the methods available.
You can find your budget id in the "Advanced" section of the settings page.
If you want, you can use some low-level methods (see below) to manage the connection yourself, but this is not recommended.
Writing data importers
If you are using another app, like YNAB or Mint, you might want to migrate your data. Right now only officially support importing YNAB4 data (and it works very well). But if you want to import all of your data into Actual, you can write a custom importer.
Note that this is not about importing transactions. If all you want to do is add transactions from a custom source (like your banks API), use importTransactions. In this context, a custom importer is something takes all of your data (budgets, transactions, payees, etc) and dumps them all into a new file in Actual.
The API has a special mode for bulk importing data. In this mode, a new file is always created (you can't bulk import into an existing file), and it will run much faster than if you did it normally.
To write a custom importer, use runImport instead of runWithBudget. runImport takes the name of the file you want to create and runs a function. Here is an example importer:
let api = require('@actual-app/api');
let data = require('my-data.json');
async function run() {
for (let account of data.accounts) {
let acctId = await api.createAccount(convertAccount(account));
await api.addTransactions(
acctId,
data.transactions
.filter((t) => t.acctId === acctId)
.map(convertTransaction)
);
}
}
api.runImport('My-Budget', run);
This is very simple, but it takes some data in my-data.json and creates all the accounts and transactions from it. Functions to convert the items (like convertAccount) are not included here. Use the reference docs to learn the shape of objects that Actual expects.
Note: it's important that addTransactions is used here. You want to use it instead of importTransactions when dumping raw data into Actual. The former will not run the reconciliation process (which dedupes transactions), and won't create the other side of transfer transactions, and more. If you use importTransactions it may adjust your data in ways that don't match the data you’re importing.
Check out the YNAB4 and YNAB5 importers to see how a real importer works.
Methods
These are the public methods that you can use. The API also exports low-level functions like init, send, disconnect, and loadBudget if you want to manually manage the connection. You can read the source to learn about those methods (search for export const lib).
init
<Method name="init" argsObject={true} args={[{ name: 'options', properties: [{ name: 'budgetId', type: 'string'}, { name: 'config', properties: [{ name: 'dataDir', type: 'string' }, { name: 'serverURL', type: 'string' }]}] }]} returns="Promise" />
After connecting to the budget budgetId, run the function. This function can assume all API methods are ready to use.
You can find your budget id in the "Advanced" section of the settings page.
runImport
<Method name="runImport" args={[{ name: 'budgetName', type: 'string'}, { name: 'func', type: 'function' }]} returns="Promise" />
Create the budget budgetName, connect to it, and run the function. This puts the API in a special "import mode" that does some maintenance work to create a new budget, and bulk importing data runs much faster.