├── .prettierrc.json ├── src ├── errors │ ├── index.ts │ └── timeoutError.ts ├── utils.ts ├── index.ts ├── contact.ts ├── httpHandler.ts ├── salesInvoice.ts ├── moneybird.ts ├── common.ts └── administration.ts ├── .prettierignore ├── example ├── dummy.pdf ├── .env.example ├── package.scripts.js ├── package.json ├── example.js └── package-lock.json ├── tsconfig.build.json ├── .editorconfig ├── release.config.js ├── .eslintrc.js ├── package.scripts.js ├── .github └── workflows │ └── release.yml ├── tsconfig.json ├── LICENSE ├── .gitattributes ├── README.md ├── package.json ├── .gitignore └── CHANGELOG.md /.prettierrc.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /src/errors/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./timeoutError"; 2 | -------------------------------------------------------------------------------- /src/utils.ts: -------------------------------------------------------------------------------- 1 | //todo make method that goes from object to filter string 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | dist 2 | lib 3 | package-lock.json 4 | CHANGELOG.md 5 | README.md 6 | -------------------------------------------------------------------------------- /example/dummy.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Print-one/moneybird-js/HEAD/example/dummy.pdf -------------------------------------------------------------------------------- /tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "exclude": ["test/**/*.spec.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /example/.env.example: -------------------------------------------------------------------------------- 1 | MONEYBIRD_API_KEY=your_api_key 2 | # Incase you want to see DEBUG messages 3 | DEBUG=moneybird* 4 | -------------------------------------------------------------------------------- /src/errors/timeoutError.ts: -------------------------------------------------------------------------------- 1 | export class TimeoutError extends Error { 2 | constructor(message: string, public readonly retryAfter: Date) { 3 | super(message); 4 | this.name = "TimeoutError"; 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /example/package.scripts.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | scripts: { 3 | start: { 4 | _default: "bsm buildLib start._", 5 | _: "env-cmd -f ./.env node ./example.js", 6 | }, 7 | buildLib: "cd ../ && npm run build", 8 | }, 9 | }; 10 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | 7 | [*.{js,ts}] 8 | charset = utf-8 9 | 10 | [src/**.{js,ts}] 11 | indent_style = space 12 | indent_size = 2 13 | 14 | [package.json] 15 | indent_style = space 16 | indent_size = 2 -------------------------------------------------------------------------------- /release.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | branches: ["main"], 3 | plugins: [ 4 | "@semantic-release/commit-analyzer", 5 | "@semantic-release/release-notes-generator", 6 | "@semantic-release/changelog", 7 | "@semantic-release/npm", 8 | "@semantic-release/github", 9 | "@semantic-release/git", 10 | ], 11 | }; 12 | -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example", 3 | "version": "1.0.0", 4 | "dependencies": { 5 | "@print-one/moneybird-js": "file:../" 6 | }, 7 | "scripts": { 8 | "start": "bsm start" 9 | }, 10 | "devDependencies": { 11 | "@types/node": "^18.15.12", 12 | "@under_koen/bsm": "^0.0.6", 13 | "env-cmd": "^10.1.0", 14 | "lodash": "^4.17.21" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { Moneybird } from "./moneybird"; 2 | 3 | export { Moneybird }; 4 | export { Administration } from "./administration"; 5 | export { Contact } from "./contact"; 6 | export { SalesInvoice } from "./salesInvoice"; 7 | export * from "./common"; 8 | export * from "./errors"; 9 | 10 | export const instance: Moneybird = new Moneybird( 11 | "https://moneybird.com/api/", 12 | "v2" 13 | ); 14 | -------------------------------------------------------------------------------- /example/example.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-var-requires */ 2 | const moneybird = require("@print-one/moneybird-js"); 3 | const fs = require("fs"); 4 | const _ = require("lodash"); 5 | 6 | moneybird.instance.setOptions({ 7 | api_token: process.env.MONEYBIRD_API_KEY, 8 | }); 9 | 10 | (async () => { 11 | while (true) { 12 | const administrations = await moneybird.instance.administrations(); 13 | for (const administration of administrations) { 14 | } 15 | } 16 | })().catch(console.log); 17 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | /*eslint sort-keys-fix/sort-keys-fix: "warn"*/ 2 | 3 | module.exports = { 4 | env: { 5 | node: true, 6 | }, 7 | extends: [ 8 | "eslint:recommended", 9 | "plugin:@typescript-eslint/recommended", 10 | "prettier", 11 | ], 12 | ignorePatterns: ["**/node_modules", "**/lib", "**/package-lock.json"], 13 | parser: "@typescript-eslint/parser", 14 | plugins: [ 15 | "@typescript-eslint", 16 | "simple-import-sort", 17 | "no-relative-import-paths", 18 | "unused-imports", 19 | "sort-keys-fix", 20 | ], 21 | root: true, 22 | }; 23 | -------------------------------------------------------------------------------- /package.scripts.js: -------------------------------------------------------------------------------- 1 | /*eslint sort-keys-fix/sort-keys-fix: "warn"*/ 2 | 3 | module.exports = { 4 | scripts: { 5 | build: ["bsm clean", "tsc --project tsconfig.build.json"], 6 | clean: "rimraf ./lib", 7 | format: { 8 | _default: "bsm ~.*", 9 | eslint: "eslint --fix .", 10 | packageJson: "prettier-package-json --write", 11 | prettier: "prettier --write .", 12 | }, 13 | lint: { 14 | _default: "bsm ~.*", 15 | eslint: "eslint .", 16 | prettier: "prettier -c .", 17 | typescript: "tsc --noEmit", 18 | }, 19 | }, 20 | }; 21 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | on: 3 | push: 4 | branches: 5 | - main 6 | jobs: 7 | release: 8 | name: Release 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Checkout 12 | uses: actions/checkout@v3 13 | with: 14 | fetch-depth: 0 15 | - name: Setup Node.js 16 | uses: actions/setup-node@v3 17 | with: 18 | node-version: "lts/*" 19 | - name: Install dependencies 20 | run: npm ci 21 | - name: Build 22 | run: npm run build 23 | - name: Release 24 | env: 25 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 26 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 27 | run: npx semantic-release 28 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es2017", 5 | 6 | "sourceMap": true, 7 | "declaration": true, 8 | "declarationMap": true, 9 | "preserveSymlinks": true, 10 | 11 | "removeComments": true, 12 | "incremental": true, 13 | "emitDecoratorMetadata": true, 14 | "experimentalDecorators": true, 15 | "allowSyntheticDefaultImports": true, 16 | "skipLibCheck": true, 17 | "esModuleInterop": false, 18 | 19 | "strict": true, 20 | 21 | "resolveJsonModule": true, 22 | 23 | "plugins": [ 24 | { "transform": "typescript-transform-paths" }, 25 | { "transform": "typescript-transform-paths", "afterDeclarations": true } 26 | ], 27 | 28 | "baseUrl": "./", 29 | "outDir": "./lib" 30 | }, 31 | 32 | "include": ["src/**/*.ts", "test/**/*.ts"] 33 | } 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Print.one 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ## This .gitattributes file automatically formats the EOL character in certain filetypes within the repository 2 | 3 | ## Source code 4 | # JavaScript, TypeScript source files 5 | *.js text eol=lf 6 | *.ts text eol=lf 7 | 8 | # Shell scripts 9 | *.sh text eol=lf 10 | *.bash text eol=lf 11 | 12 | # Windows batch and PowerShell scripts 13 | *.bat text eol=crlf 14 | *.cmd text eol=crlf 15 | *.ps1 text eol=crlf 16 | 17 | ##### Other file types ##### 18 | 19 | ## Text files and documentation 20 | *.txt text 21 | *.md text diff=markdown 22 | README* text 23 | RELEASING* text 24 | CHANGELOG* text 25 | CONTRIBUTING* text 26 | INSTALL* text 27 | LICENSE* text 28 | 29 | ## Non-text documentation 30 | *.html text diff=html 31 | *.pdf binary 32 | *.json text eol=lf 33 | *.rtf binary 34 | 35 | ## Git Properties 36 | .gitignore text 37 | .gitmodules text 38 | .gitattributes text -------------------------------------------------------------------------------- /src/contact.ts: -------------------------------------------------------------------------------- 1 | import { IContact, IContactCreate } from "./common"; 2 | import { Moneybird } from "./moneybird"; 3 | import { Administration } from "./administration"; 4 | import { HTTP, HttpHandler } from "./httpHandler"; 5 | 6 | export class Contact { 7 | private readonly moneybird: Moneybird; 8 | private readonly administration: Administration; 9 | private readonly id: string; 10 | public readonly data: IContact; 11 | 12 | constructor( 13 | moneybird: Moneybird, 14 | administration: Administration, 15 | data: IContact 16 | ) { 17 | this.moneybird = moneybird; 18 | this.administration = administration; 19 | this.id = data.id; 20 | this.data = data; 21 | this.HTTP = new HttpHandler( 22 | this.administration.HTTP, 23 | `contacts/${this.id}` 24 | ); 25 | } 26 | 27 | /** 28 | * To perform requests to the Moneybird API in the context of this contact 29 | */ 30 | public readonly HTTP: HTTP; 31 | 32 | /** 33 | * Updates the contact with the given data 34 | * @param data The data to update the contact with 35 | */ 36 | public async update(data: Partial): Promise { 37 | const contact = await this.HTTP.PATCH("", { contact: data }); 38 | return new Contact(this.moneybird, this.administration, contact); 39 | } 40 | 41 | /** 42 | * Deletes the contact from the administration 43 | */ 44 | public async delete(): Promise { 45 | await this.HTTP.DELETE(""); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/httpHandler.ts: -------------------------------------------------------------------------------- 1 | import { AxiosRequestConfig } from "axios"; 2 | 3 | export interface HTTP { 4 | GET(url: string, options?: AxiosRequestConfig): Promise; 5 | POST(url: string, data: unknown, options?: AxiosRequestConfig): Promise; 6 | PATCH( 7 | url: string, 8 | data: unknown, 9 | options?: AxiosRequestConfig 10 | ): Promise; 11 | DELETE(url: string, options?: AxiosRequestConfig): Promise; 12 | } 13 | 14 | export class HttpHandler implements HTTP { 15 | private readonly parent: HTTP; 16 | private readonly url: string; 17 | 18 | constructor(parent: HTTP, url: string) { 19 | this.parent = parent; 20 | this.url = url; 21 | } 22 | 23 | public async GET( 24 | url: string, 25 | options: AxiosRequestConfig = {} 26 | ): Promise { 27 | return await this.parent.GET(`${this.url}/${url}`, options); 28 | } 29 | 30 | public async POST( 31 | url: string, 32 | data: unknown, 33 | options: AxiosRequestConfig = {} 34 | ): Promise { 35 | return await this.parent.POST(`${this.url}/${url}`, data, options); 36 | } 37 | 38 | public async PATCH( 39 | url: string, 40 | data: unknown, 41 | options: AxiosRequestConfig = {} 42 | ): Promise { 43 | return await this.parent.PATCH(`${this.url}/${url}`, data, options); 44 | } 45 | 46 | public async DELETE( 47 | url: string, 48 | options: AxiosRequestConfig = {} 49 | ): Promise { 50 | return await this.parent.DELETE(`${this.url}/${url}`, options); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Moneybird.js 2 | 3 | [![npm package][npm-img]][npm-url] 4 | [![Build Status][build-img]][build-url] 5 | [![Issues][issues-img]][issues-url] 6 | [![Semantic Release][semantic-release-img]][semantic-release-url] 7 | 8 | > A wrapper for the Moneybird API. 9 | 10 | ## Currently supported endpoints 11 | 12 | - Administration 13 | - Contact* 14 | - Sales invoice* 15 | - Tax rates 16 | - Custom Fields 17 | - Ledger accounts* 18 | - Workflows 19 | - Webhooks 20 | 21 | *not all endpoints are yet implemented 22 | 23 | ## Usage 24 | 25 | ```js 26 | const moneybird = require("@print-one/moneybird-js"); 27 | 28 | // Set API token for the Moneybird instance 29 | moneybird.instance.setOptions({ 30 | api_token: 'XXXXX', 31 | }); 32 | 33 | // Alternatively you can create an new instance 34 | const instance = new moneybird.Moneybird( 35 | 'https://moneybird.com/api/', 36 | 'v2', 37 | 'XXXXX' 38 | ); 39 | 40 | // Get all administrations 41 | instance.administrations().then(async (administration) => { 42 | const contacts = await administration.contacts(); 43 | console.log(contacts); 44 | }); 45 | ``` 46 | 47 | [build-img]:https://github.com/Print-one/moneybird-js/actions/workflows/release.yml/badge.svg 48 | 49 | [build-url]:https://github.com/Print-one/moneybird-js/actions/workflows/release.yml 50 | 51 | [npm-img]:https://img.shields.io/npm/v/@print-one/moneybird-js 52 | 53 | [npm-url]:https://www.npmjs.com/package/@print-one/moneybird-js 54 | 55 | [issues-img]:https://img.shields.io/github/issues/Print-one/moneybird-js 56 | 57 | [issues-url]:https://github.com/ryansonshine/Print-one/moneybird-js/issues 58 | 59 | [semantic-release-img]:https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg 60 | 61 | [semantic-release-url]:https://github.com/semantic-release/semantic-release 62 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@print-one/moneybird-js", 3 | "version": "1.10.1", 4 | "description": "A client for Moneybird in javascript", 5 | "license": "MIT", 6 | "author": "Print.one", 7 | "homepage": "https://github.com/Print-one/moneybird-js#readme", 8 | "repository": { 9 | "type": "git", 10 | "url": "git+https://github.com/Print-one/moneybird-js.git" 11 | }, 12 | "bugs": "https://github.com/Print-one/moneybird-js/issues", 13 | "main": "lib/index.js", 14 | "files": [ 15 | "lib/**" 16 | ], 17 | "scripts": { 18 | "build": "bsm build", 19 | "clean": "bsm clean", 20 | "format": "bsm format", 21 | "lint": "bsm lint", 22 | "semantic-release": "semantic-release" 23 | }, 24 | "types": "lib/index.d.ts", 25 | "dependencies": { 26 | "axios": "^1.5.1", 27 | "debug": "^4.3.4" 28 | }, 29 | "devDependencies": { 30 | "@semantic-release/changelog": "^6.0.3", 31 | "@semantic-release/git": "^10.0.1", 32 | "@semantic-release/github": "^8.0.7", 33 | "@types/debug": "^4.1.7", 34 | "@typescript-eslint/eslint-plugin": "^5.57.1", 35 | "@typescript-eslint/parser": "^5.57.1", 36 | "@under_koen/bsm": "^0.0.6", 37 | "eslint": "^8.37.0", 38 | "eslint-config-prettier": "^8.8.0", 39 | "eslint-plugin-no-relative-import-paths": "^1.5.2", 40 | "eslint-plugin-prettier": "^4.2.1", 41 | "eslint-plugin-simple-import-sort": "^10.0.0", 42 | "eslint-plugin-sort-keys-fix": "^1.1.2", 43 | "eslint-plugin-unused-imports": "^2.0.0", 44 | "prettier": "^2.8.7", 45 | "prettier-package-json": "^2.8.0", 46 | "semantic-release": "^21.0.1", 47 | "typescript": "^5.0.3", 48 | "typescript-transform-paths": "^3.4.6" 49 | }, 50 | "keywords": [ 51 | "api", 52 | "bookkeeping", 53 | "moneybird", 54 | "rest" 55 | ] 56 | } 57 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | lib 2 | 3 | ### VisualStudioCode template 4 | .vscode/* 5 | !.vscode/settings.json 6 | !.vscode/tasks.json 7 | !.vscode/launch.json 8 | !.vscode/extensions.json 9 | !.vscode/*.code-snippets 10 | 11 | # Local History for Visual Studio Code 12 | .history/ 13 | 14 | # Built Visual Studio Code Extensions 15 | *.vsix 16 | 17 | ### JetBrains template 18 | .idea 19 | 20 | ### Node template 21 | # Logs 22 | logs 23 | *.log 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | lerna-debug.log* 28 | .pnpm-debug.log* 29 | 30 | # Diagnostic reports (https://nodejs.org/api/report.html) 31 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 32 | 33 | # Runtime data 34 | pids 35 | *.pid 36 | *.seed 37 | *.pid.lock 38 | 39 | # Directory for instrumented libs generated by jscoverage/JSCover 40 | lib-cov 41 | 42 | # Coverage directory used by tools like istanbul 43 | coverage 44 | *.lcov 45 | 46 | # nyc test coverage 47 | .nyc_output 48 | 49 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 50 | .grunt 51 | 52 | # Bower dependency directory (https://bower.io/) 53 | bower_components 54 | 55 | # node-waf configuration 56 | .lock-wscript 57 | 58 | # Compiled binary addons (https://nodejs.org/api/addons.html) 59 | build/Release 60 | 61 | # Dependency directories 62 | node_modules/ 63 | jspm_packages/ 64 | 65 | # Snowpack dependency directory (https://snowpack.dev/) 66 | web_modules/ 67 | 68 | # TypeScript cache 69 | *.tsbuildinfo 70 | 71 | # Optional npm cache directory 72 | .npm 73 | 74 | # Optional eslint cache 75 | .eslintcache 76 | 77 | # Optional stylelint cache 78 | .stylelintcache 79 | 80 | # Microbundle cache 81 | .rpt2_cache/ 82 | .rts2_cache_cjs/ 83 | .rts2_cache_es/ 84 | .rts2_cache_umd/ 85 | 86 | # Optional REPL history 87 | .node_repl_history 88 | 89 | # Output of 'npm pack' 90 | *.tgz 91 | 92 | # Yarn Integrity file 93 | .yarn-integrity 94 | 95 | # dotenv environment variable files 96 | .env 97 | .env.development.local 98 | .env.test.local 99 | .env.production.local 100 | .env.local 101 | 102 | # parcel-bundler cache (https://parceljs.org/) 103 | .cache 104 | .parcel-cache 105 | 106 | # Next.js build output 107 | .next 108 | out 109 | 110 | # Nuxt.js build / generate output 111 | .nuxt 112 | dist 113 | 114 | # Gatsby files 115 | .cache/ 116 | # Comment in the public line in if your project uses Gatsby and not Next.js 117 | # https://nextjs.org/blog/next-9-1#public-directory-support 118 | # public 119 | 120 | # vuepress build output 121 | .vuepress/dist 122 | 123 | # vuepress v2.x temp and cache directory 124 | .temp 125 | 126 | # Docusaurus cache and generated files 127 | .docusaurus 128 | 129 | # Serverless directories 130 | .serverless/ 131 | 132 | # FuseBox cache 133 | .fusebox/ 134 | 135 | # DynamoDB Local files 136 | .dynamodb/ 137 | 138 | # TernJS port file 139 | .tern-port 140 | 141 | # Stores VSCode versions used for testing VSCode extensions 142 | .vscode-test 143 | 144 | # yarn v2 145 | .yarn/cache 146 | .yarn/unplugged 147 | .yarn/build-state.yml 148 | .yarn/install-state.gz 149 | .pnp.* 150 | 151 | ### WebStorm+all template 152 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider 153 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 154 | 155 | # User-specific stuff 156 | 157 | # AWS User-specific 158 | 159 | # Generated files 160 | 161 | # Sensitive or high-churn files 162 | 163 | # Gradle 164 | 165 | # Gradle and Maven with auto-import 166 | # When using Gradle or Maven with auto-import, you should exclude module files, 167 | # since they will be recreated, and may cause churn. Uncomment if using 168 | # auto-import. 169 | # .idea/artifacts 170 | # .idea/compiler.xml 171 | # .idea/jarRepositories.xml 172 | # .idea/modules.xml 173 | # .idea/*.iml 174 | # .idea/modules 175 | # *.iml 176 | # *.ipr 177 | 178 | # CMake 179 | 180 | # Mongo Explorer plugin 181 | 182 | # File-based project format 183 | 184 | # IntelliJ 185 | 186 | # mpeltonen/sbt-idea plugin 187 | 188 | # JIRA plugin 189 | 190 | # Cursive Clojure plugin 191 | 192 | # SonarLint plugin 193 | 194 | # Crashlytics plugin (for Android Studio and IntelliJ) 195 | 196 | # Editor-based Rest Client 197 | 198 | # Android studio 3.1+ serialized cache file 199 | 200 | ### Windows template 201 | # Windows thumbnail cache files 202 | Thumbs.db 203 | Thumbs.db:encryptable 204 | ehthumbs.db 205 | ehthumbs_vista.db 206 | 207 | # Dump file 208 | *.stackdump 209 | 210 | # Folder config file 211 | [Dd]esktop.ini 212 | 213 | # Recycle Bin used on file shares 214 | $RECYCLE.BIN/ 215 | 216 | # Windows Installer files 217 | *.cab 218 | *.msi 219 | *.msix 220 | *.msm 221 | *.msp 222 | 223 | # Windows shortcuts 224 | *.lnk 225 | 226 | ### macOS template 227 | # General 228 | .DS_Store 229 | .AppleDouble 230 | .LSOverride 231 | 232 | # Icon must end with two \r 233 | Icon 234 | 235 | # Thumbnails 236 | ._* 237 | 238 | # Files that might appear in the root of a volume 239 | .DocumentRevisions-V100 240 | .fseventsd 241 | .Spotlight-V100 242 | .TemporaryItems 243 | .Trashes 244 | .VolumeIcon.icns 245 | .com.apple.timemachine.donotpresent 246 | 247 | # Directories potentially created on remote AFP share 248 | .AppleDB 249 | .AppleDesktop 250 | Network Trash Folder 251 | Temporary Items 252 | .apdisk 253 | 254 | -------------------------------------------------------------------------------- /src/salesInvoice.ts: -------------------------------------------------------------------------------- 1 | import { HttpHandler } from "./httpHandler"; 2 | import { Moneybird } from "./moneybird"; 3 | import { Administration } from "./administration"; 4 | import { 5 | IAttachment, 6 | IPayment, 7 | IPaymentCreate, 8 | ISalesInvoice, 9 | ISalesInvoiceSending, 10 | } from "./common"; 11 | 12 | export class SalesInvoice { 13 | private readonly moneybird: Moneybird; 14 | private readonly administration: Administration; 15 | private readonly id: string; 16 | public readonly data: ISalesInvoice; 17 | private readonly HTTP: HttpHandler; 18 | 19 | constructor( 20 | moneybird: Moneybird, 21 | administration: Administration, 22 | data: ISalesInvoice 23 | ) { 24 | this.moneybird = moneybird; 25 | this.administration = administration; 26 | this.id = data.id; 27 | this.data = data; 28 | this.HTTP = new HttpHandler( 29 | this.administration.HTTP, 30 | `sales_invoices/${this.id}` 31 | ); 32 | } 33 | 34 | /** 35 | * Send the sales invoice 36 | * @returns A sales invoice 37 | */ 38 | public async send(data: ISalesInvoiceSending = {}): Promise { 39 | return new SalesInvoice( 40 | this.moneybird, 41 | this.administration, 42 | await this.HTTP.PATCH("send_invoice", { 43 | sales_invoice_sending: data, 44 | }) 45 | ); 46 | } 47 | 48 | /** 49 | * Download the PDF of the sales invoice 50 | * @returns The content of the PDF 51 | */ 52 | public async downloadPDF(): Promise { 53 | return this.HTTP.GET("download_pdf", { 54 | responseType: "arraybuffer", 55 | }); 56 | } 57 | 58 | /** 59 | * Download the UBL of the sales invoice 60 | * @returns The content of the UBL 61 | */ 62 | public async downloadUBL(): Promise { 63 | return this.HTTP.GET("download_ubl", { 64 | responseType: "arraybuffer", 65 | }); 66 | } 67 | 68 | /** 69 | * Download the packing slip of the sales invoice 70 | * @returns The PDF content of the packing slip 71 | */ 72 | public async downloadPackingSlip(): Promise { 73 | return this.HTTP.GET("download_packing_slip_pdf", { 74 | responseType: "arraybuffer", 75 | }); 76 | } 77 | 78 | /** 79 | * Add a payment to the sales invoice 80 | * @param payment The payment to add 81 | */ 82 | public async addPayment(payment: IPaymentCreate): Promise { 83 | return this.HTTP.POST("payments", { 84 | payment: payment, 85 | }); 86 | } 87 | 88 | /** 89 | * Delete a payment from the sales invoice 90 | * @param payment The payment to delete 91 | */ 92 | public async deletePayment(payment: IPayment): Promise; 93 | /** 94 | * Delete a payment from the sales invoice 95 | * @param paymentId The ID of the payment to delete 96 | */ 97 | public async deletePayment(paymentId: string): Promise; 98 | public async deletePayment(payment: IPayment | string): Promise { 99 | const id = typeof payment === "string" ? payment : payment.id; 100 | await this.HTTP.DELETE(`payments/${id}`); 101 | } 102 | 103 | /** 104 | * Add attachment to the sales invoice 105 | */ 106 | public async addAttachment( 107 | content: ArrayBuffer, 108 | file_name?: string 109 | ): Promise { 110 | const formData = new FormData(); 111 | formData.append("file", new Blob([content]), file_name); 112 | 113 | return this.HTTP.POST("attachments", formData, { 114 | headers: { 115 | "Content-Type": "multipart/form-data", 116 | }, 117 | }); 118 | } 119 | 120 | /** 121 | * Delete attachment from the sales invoice 122 | */ 123 | public async deleteAttachment(attachment: IAttachment): Promise; 124 | public async deleteAttachment(attachmentId: string): Promise; 125 | public async deleteAttachment( 126 | attachment: IAttachment | string 127 | ): Promise { 128 | const attachmentId = 129 | typeof attachment === "string" ? attachment : attachment.id; 130 | return this.HTTP.DELETE(`attachments/${attachmentId}`); 131 | } 132 | 133 | /** 134 | * Download attachment from the sales invoice 135 | */ 136 | public async downloadAttachment( 137 | attachment: IAttachment 138 | ): Promise; 139 | public async downloadAttachment(attachmentId: string): Promise; 140 | public async downloadAttachment( 141 | attachment: IAttachment | string 142 | ): Promise { 143 | const attachmentId = 144 | typeof attachment === "string" ? attachment : attachment.id; 145 | return this.HTTP.GET(`attachments/${attachmentId}/download`, { 146 | responseType: "arraybuffer", 147 | }); 148 | } 149 | 150 | /** 151 | * Update the sales invoice 152 | */ 153 | public async update(data: Partial): Promise { 154 | return new SalesInvoice( 155 | this.moneybird, 156 | this.administration, 157 | await this.HTTP.PATCH("", { sales_invoice: data }) 158 | ); 159 | } 160 | 161 | /** 162 | * Delete the sales invoice 163 | */ 164 | public async delete(): Promise { 165 | return this.HTTP.DELETE(""); 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [1.10.1](https://github.com/Print-one/moneybird-js/compare/v1.10.0...v1.10.1) (2025-01-16) 2 | 3 | 4 | ### Bug Fixes 5 | 6 | * create webhook body wrong ([56cb3f3](https://github.com/Print-one/moneybird-js/commit/56cb3f35b15916f050b3c1854218b4eea88ee46c)) 7 | 8 | # [1.10.0](https://github.com/Print-one/moneybird-js/compare/v1.9.1...v1.10.0) (2025-01-15) 9 | 10 | 11 | ### Features 12 | 13 | * support webhooks ([b203921](https://github.com/Print-one/moneybird-js/commit/b203921c44d16cff8942ca45e29f23d18dc043e1)) 14 | 15 | ## [1.9.1](https://github.com/Print-one/moneybird-js/compare/v1.9.0...v1.9.1) (2024-08-20) 16 | 17 | 18 | ### Bug Fixes 19 | 20 | * export TimeoutError ([d1f0e08](https://github.com/Print-one/moneybird-js/commit/d1f0e08b8df5c891259af3b0daebc7794371bdd3)) 21 | 22 | # [1.9.0](https://github.com/Print-one/moneybird-js/compare/v1.8.2...v1.9.0) (2024-08-20) 23 | 24 | 25 | ### Features 26 | 27 | * throw an timeout error for when an timeout is happened ([eea9212](https://github.com/Print-one/moneybird-js/commit/eea9212aaf9038e4f384d694b4db9bad169f602d)) 28 | 29 | ## [1.8.2](https://github.com/Print-one/moneybird-js/compare/v1.8.1...v1.8.2) (2024-01-24) 30 | 31 | 32 | ### Bug Fixes 33 | 34 | * **types:** make amount optional in invoice details_attributes ([8227275](https://github.com/Print-one/moneybird-js/commit/8227275c0c9466f86d5dd467d7fc2e90d76ea15a)) 35 | 36 | ## [1.8.1](https://github.com/Print-one/moneybird-js/compare/v1.8.0...v1.8.1) (2023-10-24) 37 | 38 | 39 | ### Bug Fixes 40 | 41 | * add attachment file name ([87e8a33](https://github.com/Print-one/moneybird-js/commit/87e8a336ee052e308a146b251b7a639681cf448c)) 42 | * debugger show correct ms ([a703512](https://github.com/Print-one/moneybird-js/commit/a703512e723bccbab7ac51bec69429b3e283d6c2)) 43 | 44 | # [1.8.0](https://github.com/Print-one/moneybird-js/compare/v1.7.0...v1.8.0) (2023-10-12) 45 | 46 | 47 | ### Features 48 | 49 | * send invoice endpoint added. Thanks @SimonsThijs ([#2](https://github.com/Print-one/moneybird-js/issues/2)) ([00a3de7](https://github.com/Print-one/moneybird-js/commit/00a3de729b15e880ef71d7b5b8bd3685d1d85151)) 50 | 51 | # [1.7.0](https://github.com/Print-one/moneybird-js/compare/v1.6.1...v1.7.0) (2023-10-12) 52 | 53 | 54 | ### Bug Fixes 55 | 56 | * return ArrayBuffer instead of string ([9b3f39d](https://github.com/Print-one/moneybird-js/commit/9b3f39d9021c5232dbdde747c6e8b39bce36fea9)) 57 | 58 | 59 | ### Features 60 | 61 | * invoice attachments ([9223c39](https://github.com/Print-one/moneybird-js/commit/9223c39ef8f92b89f1964c7fdbe2cb52abed57ce)) 62 | 63 | ## [1.6.1](https://github.com/Print-one/moneybird-js/compare/v1.6.0...v1.6.1) (2023-09-07) 64 | 65 | 66 | ### Bug Fixes 67 | 68 | * export all common types ([65fe2ad](https://github.com/Print-one/moneybird-js/commit/65fe2aded885a0a8e097fff41470183a04d57075)) 69 | 70 | # [1.6.0](https://github.com/Print-one/moneybird-js/compare/v1.5.0...v1.6.0) (2023-09-06) 71 | 72 | 73 | ### Features 74 | 75 | * payments endpoints added ([5e13ef7](https://github.com/Print-one/moneybird-js/commit/5e13ef74c84b2182bbf7b2ef9bcc86f4f1e57985)) 76 | * payments types added ([2ee79a0](https://github.com/Print-one/moneybird-js/commit/2ee79a0c299889276d074bace07aa573ecbcca98)) 77 | 78 | # [1.5.0](https://github.com/Print-one/moneybird-js/compare/v1.4.0...v1.5.0) (2023-06-22) 79 | 80 | 81 | ### Features 82 | 83 | * workflows endpoints added ([e3bf931](https://github.com/Print-one/moneybird-js/commit/e3bf931f9012154b477a6d4ae5c849a6356e6750)) 84 | 85 | # [1.4.0](https://github.com/Print-one/moneybird-js/compare/v1.3.3...v1.4.0) (2023-06-22) 86 | 87 | 88 | ### Features 89 | 90 | * custom fields endpoints ([67bd74f](https://github.com/Print-one/moneybird-js/commit/67bd74f27b962d31f6dee939a8edcdb066077fd0)) 91 | * some ledger account endpoints ([ab162fe](https://github.com/Print-one/moneybird-js/commit/ab162fe634e9da4237ac8f071d24b4989fbb6748)) 92 | * taxes endpoints ([3eee0d2](https://github.com/Print-one/moneybird-js/commit/3eee0d28c744515833ea70025428393d0dcb2339)) 93 | 94 | ## [1.3.3](https://github.com/Print-one/moneybird-js/compare/v1.3.2...v1.3.3) (2023-04-20) 95 | 96 | 97 | ### Bug Fixes 98 | 99 | * POST, PATCH, DELETE logging breaking calls ([e10e5fc](https://github.com/Print-one/moneybird-js/commit/e10e5fce975627c3d950117c827ea4c11f7ad3c7)) 100 | 101 | ## [1.3.2](https://github.com/Print-one/moneybird-js/compare/v1.3.1...v1.3.2) (2023-04-20) 102 | 103 | 104 | ### Bug Fixes 105 | 106 | * hide debug logs ([145b766](https://github.com/Print-one/moneybird-js/commit/145b766333ec44ad507a52f902c4eaf164b15395)) 107 | 108 | ## [1.3.1](https://github.com/Print-one/moneybird-js/compare/v1.3.0...v1.3.1) (2023-04-19) 109 | 110 | 111 | ### Bug Fixes 112 | 113 | * export Adminstration, Contact and SalesInvoice in index ([f15841e](https://github.com/Print-one/moneybird-js/commit/f15841ec5acde11b448efe0354b288bc40457925)) 114 | 115 | # [1.3.0](https://github.com/Print-one/moneybird-js/compare/v1.2.0...v1.3.0) (2023-04-17) 116 | 117 | 118 | ### Features 119 | 120 | * administration api ([70b35f5](https://github.com/Print-one/moneybird-js/commit/70b35f52ae599898ab1c2df93aef77728d3e1feb)) 121 | * contacts api ([14298d8](https://github.com/Print-one/moneybird-js/commit/14298d8af8ef74e29e75abdf769a5e22bb2e7983)) 122 | * sales invoices added ([addcf26](https://github.com/Print-one/moneybird-js/commit/addcf262d4ff37af50d126a08cd8bdbc748c63a0)) 123 | -------------------------------------------------------------------------------- /example/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "example", 9 | "version": "1.0.0", 10 | "dependencies": { 11 | "@print-one/moneybird-js": "file:../" 12 | }, 13 | "devDependencies": { 14 | "@types/node": "^18.15.12", 15 | "@under_koen/bsm": "^0.0.6", 16 | "env-cmd": "^10.1.0", 17 | "lodash": "^4.17.21" 18 | } 19 | }, 20 | "..": { 21 | "name": "@print-one/moneybird-js", 22 | "version": "1.8.1", 23 | "license": "MIT", 24 | "dependencies": { 25 | "axios": "^1.5.1", 26 | "debug": "^4.3.4" 27 | }, 28 | "devDependencies": { 29 | "@semantic-release/changelog": "^6.0.3", 30 | "@semantic-release/git": "^10.0.1", 31 | "@semantic-release/github": "^8.0.7", 32 | "@types/debug": "^4.1.7", 33 | "@typescript-eslint/eslint-plugin": "^5.57.1", 34 | "@typescript-eslint/parser": "^5.57.1", 35 | "@under_koen/bsm": "^0.0.6", 36 | "eslint": "^8.37.0", 37 | "eslint-config-prettier": "^8.8.0", 38 | "eslint-plugin-no-relative-import-paths": "^1.5.2", 39 | "eslint-plugin-prettier": "^4.2.1", 40 | "eslint-plugin-simple-import-sort": "^10.0.0", 41 | "eslint-plugin-sort-keys-fix": "^1.1.2", 42 | "eslint-plugin-unused-imports": "^2.0.0", 43 | "prettier": "^2.8.7", 44 | "prettier-package-json": "^2.8.0", 45 | "semantic-release": "^21.0.1", 46 | "typescript": "^5.0.3", 47 | "typescript-transform-paths": "^3.4.6" 48 | } 49 | }, 50 | "node_modules/@print-one/moneybird-js": { 51 | "resolved": "..", 52 | "link": true 53 | }, 54 | "node_modules/@types/node": { 55 | "version": "18.15.12", 56 | "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.12.tgz", 57 | "integrity": "sha512-Wha1UwsB3CYdqUm2PPzh/1gujGCNtWVUYF0mB00fJFoR4gTyWTDPjSm+zBF787Ahw8vSGgBja90MkgFwvB86Dg==", 58 | "dev": true 59 | }, 60 | "node_modules/@under_koen/bsm": { 61 | "version": "0.0.6", 62 | "resolved": "https://registry.npmjs.org/@under_koen/bsm/-/bsm-0.0.6.tgz", 63 | "integrity": "sha512-cGpHaVomkLlqyUpmkqA4wE8mxzglBvLraqrpU3XInunsQtNSMyoys2JT9jBMNxCBEqDi0qSU0Fi/3lI07P/kgQ==", 64 | "dev": true, 65 | "bin": { 66 | "bsm": "dist/index.js" 67 | } 68 | }, 69 | "node_modules/commander": { 70 | "version": "4.1.1", 71 | "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", 72 | "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", 73 | "dev": true, 74 | "engines": { 75 | "node": ">= 6" 76 | } 77 | }, 78 | "node_modules/cross-spawn": { 79 | "version": "7.0.3", 80 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", 81 | "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", 82 | "dev": true, 83 | "dependencies": { 84 | "path-key": "^3.1.0", 85 | "shebang-command": "^2.0.0", 86 | "which": "^2.0.1" 87 | }, 88 | "engines": { 89 | "node": ">= 8" 90 | } 91 | }, 92 | "node_modules/env-cmd": { 93 | "version": "10.1.0", 94 | "resolved": "https://registry.npmjs.org/env-cmd/-/env-cmd-10.1.0.tgz", 95 | "integrity": "sha512-mMdWTT9XKN7yNth/6N6g2GuKuJTsKMDHlQFUDacb/heQRRWOTIZ42t1rMHnQu4jYxU1ajdTeJM+9eEETlqToMA==", 96 | "dev": true, 97 | "dependencies": { 98 | "commander": "^4.0.0", 99 | "cross-spawn": "^7.0.0" 100 | }, 101 | "bin": { 102 | "env-cmd": "bin/env-cmd.js" 103 | }, 104 | "engines": { 105 | "node": ">=8.0.0" 106 | } 107 | }, 108 | "node_modules/isexe": { 109 | "version": "2.0.0", 110 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 111 | "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", 112 | "dev": true 113 | }, 114 | "node_modules/lodash": { 115 | "version": "4.17.21", 116 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 117 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", 118 | "dev": true 119 | }, 120 | "node_modules/path-key": { 121 | "version": "3.1.1", 122 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", 123 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", 124 | "dev": true, 125 | "engines": { 126 | "node": ">=8" 127 | } 128 | }, 129 | "node_modules/shebang-command": { 130 | "version": "2.0.0", 131 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", 132 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", 133 | "dev": true, 134 | "dependencies": { 135 | "shebang-regex": "^3.0.0" 136 | }, 137 | "engines": { 138 | "node": ">=8" 139 | } 140 | }, 141 | "node_modules/shebang-regex": { 142 | "version": "3.0.0", 143 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", 144 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", 145 | "dev": true, 146 | "engines": { 147 | "node": ">=8" 148 | } 149 | }, 150 | "node_modules/which": { 151 | "version": "2.0.2", 152 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 153 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 154 | "dev": true, 155 | "dependencies": { 156 | "isexe": "^2.0.0" 157 | }, 158 | "bin": { 159 | "node-which": "bin/node-which" 160 | }, 161 | "engines": { 162 | "node": ">= 8" 163 | } 164 | } 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /src/moneybird.ts: -------------------------------------------------------------------------------- 1 | import axios, { Axios, AxiosResponse, AxiosRequestConfig } from "axios"; 2 | import { IAdministration, MoneybirdOptions } from "./common"; 3 | import { Administration } from "./administration"; 4 | import { HTTP } from "./httpHandler"; 5 | import debug from "debug"; 6 | import { TimeoutError } from "./errors/timeoutError"; 7 | 8 | export class Moneybird implements HTTP { 9 | private readonly client: Axios; 10 | private readonly url: string; 11 | private readonly version: string; 12 | private options: MoneybirdOptions = { api_token: "" }; 13 | private debug = debug("moneybird"); 14 | 15 | constructor(url: string, version: string, options?: MoneybirdOptions) { 16 | this.url = url; 17 | this.version = version; 18 | 19 | this.client = axios.create({ 20 | baseURL: new URL(version, url).href + "/", 21 | responseType: "json", 22 | validateStatus: () => true, 23 | }); 24 | 25 | if (options) this.setOptions(options); 26 | } 27 | 28 | /** 29 | * Changes the options of the Moneybird instance 30 | * @param options The new options 31 | */ 32 | public setOptions(options: MoneybirdOptions): void { 33 | this.options = options; 34 | 35 | this.client.defaults.headers.common.Authorization = `Bearer ${options.api_token}`; 36 | this.client.defaults.responseType = "json"; 37 | } 38 | 39 | /** 40 | * Returns a list of all administrations 41 | */ 42 | public async administrations(): Promise { 43 | const data = await this.GET("administrations"); 44 | 45 | return data.map((a) => new Administration(this, a)); 46 | } 47 | 48 | /** 49 | * Returns an administration object without fetching the data from the API 50 | * This is useful when you already have the id of the administration 51 | * @param id The id of the administration 52 | */ 53 | public administration(id: string): Administration { 54 | return new Administration(this, { id } as IAdministration); 55 | } 56 | 57 | /** 58 | * Performs a GET request to the Moneybird API 59 | * @param url The url to perform the request to 60 | * @param options The options for the request 61 | */ 62 | public async GET( 63 | url: string, 64 | options: AxiosRequestConfig = {} 65 | ): Promise { 66 | this.debug(`GET ${url}`); 67 | 68 | const response = await this.client.request({ 69 | method: "GET", 70 | url: url, 71 | ...options, 72 | }); 73 | 74 | this.handleErrors(response); 75 | 76 | return response.data; 77 | } 78 | 79 | /** 80 | * Performs a POST request to the Moneybird API 81 | * @param url The url to perform the request to 82 | * @param data The data to send with the request 83 | * @param options The options for the request 84 | */ 85 | public async POST( 86 | url: string, 87 | data: unknown, 88 | options: AxiosRequestConfig = {} 89 | ): Promise { 90 | this.debug(`POST ${url}`); 91 | 92 | const response = await this.client.request({ 93 | method: "POST", 94 | url: url, 95 | data: data, 96 | ...options, 97 | }); 98 | 99 | this.handleErrors(response); 100 | 101 | return response.data; 102 | } 103 | 104 | /** 105 | * Performs a PATCH request to the Moneybird API 106 | * @param url The url to perform the request to 107 | * @param data The data to send with the request 108 | * @param options The options for the request 109 | */ 110 | public async PATCH( 111 | url: string, 112 | data: unknown, 113 | options: AxiosRequestConfig = {} 114 | ): Promise { 115 | this.debug(`PATCH ${url}`); 116 | 117 | const response = await this.client.request({ 118 | method: "PATCH", 119 | url: url, 120 | data: data, 121 | ...options, 122 | }); 123 | 124 | this.handleErrors(response); 125 | 126 | return response.data; 127 | } 128 | 129 | /** 130 | * Performs a DELETE request to the Moneybird API 131 | * @param url The url to perform the request to 132 | * @param options The options for the request 133 | */ 134 | public async DELETE( 135 | url: string, 136 | options: AxiosRequestConfig = {} 137 | ): Promise { 138 | this.debug(`DELETE ${url}`); 139 | 140 | const response = await this.client.request({ 141 | method: "DELETE", 142 | url: url, 143 | ...options, 144 | }); 145 | 146 | this.handleErrors(response); 147 | 148 | return response.data; 149 | } 150 | 151 | private handleErrors(response: AxiosResponse) { 152 | let error = "Unknown error;"; 153 | switch (response.status) { 154 | case 200: 155 | case 201: 156 | case 204: 157 | return; 158 | case 400: 159 | error = 160 | "Bad request - Parameters for the request are missing or malformed. Body contains the errors."; 161 | break; 162 | case 401: 163 | error = 164 | "Authorization required - No authorization provided or invalid authorization information provided"; 165 | break; 166 | case 402: 167 | error = "Payment Required - Account limit reached"; 168 | break; 169 | case 403: 170 | error = 171 | "Forbidden - IP is blacklisted for API usage, see Throttling information"; 172 | break; 173 | case 404: 174 | error = "Not found - Entity not found"; 175 | break; 176 | case 405: 177 | error = 178 | "Method Not Allowed - The endpoint with this HTTP method is not available in the API"; 179 | break; 180 | case 406: 181 | error = 182 | "Not accepted - The requested content type is not supported by the API"; 183 | break; 184 | case 422: 185 | error = 186 | "Unprocessable entity - Saving the entity in the database failed due to validation errors. Body contains the errors."; 187 | break; 188 | case 429: 189 | error = "Too many requests - See Throttling information"; 190 | 191 | throw new TimeoutError( 192 | error, 193 | new Date(response.headers["retry-after"] * 1000) 194 | ); 195 | case 500: 196 | error = 197 | "Internal server error - Something went wrong while processing the request. This is unexpected behaviour and requires Moneybird to fix the scenario."; 198 | break; 199 | } 200 | 201 | throw { 202 | error: error, 203 | message: response.data.error, 204 | }; 205 | } 206 | } 207 | -------------------------------------------------------------------------------- /src/common.ts: -------------------------------------------------------------------------------- 1 | export interface MoneybirdOptions { 2 | api_token: string; 3 | } 4 | 5 | export interface IAdministration { 6 | id: string; 7 | name: string; 8 | language: string; 9 | currency: string; 10 | country: string; 11 | time_zone: string; 12 | } 13 | 14 | export interface IContact { 15 | id: string; 16 | administration_id: string; 17 | company_name: string; 18 | firstname: string; 19 | lastname: string; 20 | address1: string; 21 | address2: string; 22 | zipcode: string; 23 | city: string; 24 | country: string; 25 | phone: string; 26 | delivery_method: string; 27 | customer_id: string; 28 | tax_number: string; 29 | chamber_of_commerce: string; 30 | bank_account: string; 31 | attention: string; 32 | email: string; 33 | email_ubl: boolean; 34 | send_invoices_to_attention: string; 35 | send_invoices_to_email: string; 36 | send_estimates_to_attention: string; 37 | send_estimates_to_email: string; 38 | sepa_active: boolean; 39 | sepa_iban: string; 40 | sepa_iban_acccount_name: string; 41 | sepa_bic: string; 42 | sepa_mandate_id: string; 43 | sepa_mandate_date?: string; 44 | sepa_sequence_type: string; 45 | credit_card_number: string; 46 | credit_card_reference: string; 47 | credit_card_type?: string; 48 | tax_number_validated_at?: string; 49 | tax_number_valid?: boolean; 50 | incoice_workflow_id?: string; 51 | estimate_workflow_id?: string; 52 | si_indentifier: string; 53 | si_identifier_type?: string; 54 | moneybird_payments_mandate: boolean; 55 | created_at: string; 56 | updated_at: string; 57 | version: number; 58 | salen_invoices_url: string; 59 | notes: never[]; 60 | custom_fields: { 61 | id: string; 62 | name: string; 63 | value: string; 64 | }[]; 65 | contact_people: never[]; 66 | archived: boolean; 67 | events: never[]; 68 | } 69 | 70 | export interface IContactCreate { 71 | company_name: string; 72 | address1: string; 73 | address2: string; 74 | zipcode: string; 75 | city: string; 76 | country: string; 77 | phone: string; 78 | delivery_method: string; 79 | customer_id: string; 80 | tax_number: string; 81 | firstname: string; 82 | lastname: string; 83 | chamber_of_commerce: string; 84 | bank_account: string; 85 | send_invoices_to_attention: string; 86 | send_invoices_to_email: string; 87 | send_estimates_to_attention: string; 88 | send_estimates_to_email: string; 89 | sepa_active: boolean; 90 | sepa_iban: string; 91 | sepa_iban_account_name: string; 92 | sepa_bic: string; 93 | sepa_mandate_id: string; 94 | sepa_mandate_date?: string; 95 | sepa_sequence_type: string; 96 | si_identifier_type?: string; 97 | si_identifier: string; 98 | invoice_workflow_id?: string; 99 | estimate_workflow_id?: string; 100 | email_ubl: boolean; 101 | direct_debit: boolean; 102 | custom_fields_attributes: { 103 | id: string; 104 | value: string; 105 | }[]; 106 | contact_person: { 107 | firstname: string; 108 | lastname: string; 109 | }[]; 110 | create_event: boolean; 111 | type: string; 112 | } 113 | 114 | export interface ISalesInvoice { 115 | id: string; 116 | administration_id: string; 117 | contact_id: string; 118 | contact: IContact; 119 | contact_person_id?: string; 120 | contact_person?: never; 121 | invoice_id: string; 122 | recurring_sales_invoice_id?: string; 123 | workflow_id: string; 124 | document_style_id: string; 125 | identity_id: string; 126 | draft_id?: string; 127 | state: ISalesInvoiceState; 128 | invoice_date: string; 129 | due_date: string; 130 | payment_condition: string; 131 | payment_reference: string; 132 | short_payment_reference: string; 133 | reference: string; 134 | language: string; 135 | currency: string; 136 | discount: number; 137 | original_sales_invoice_id?: string; 138 | paused: boolean; 139 | paid_at?: string; 140 | sent_at?: string; 141 | created_at: string; 142 | updated_at: string; 143 | public_view_code: string; 144 | public_view_code_expires_at: string; 145 | version: number; 146 | details: { 147 | id: string; 148 | administration_id: string; 149 | tax_rate_id: string; 150 | ledger_account_id: string; 151 | project_id?: string; 152 | product_id?: string; 153 | amount: string; 154 | amount_decimal: string; 155 | description: string; 156 | price: string; 157 | period?: string; 158 | row_order: number; 159 | total_price_exl_tax_with_discount: string; 160 | total_price_exl_tax_with_discount_base: string; 161 | tax_report_reference: string[]; 162 | mandatory_tax_text: string; 163 | created_at: string; 164 | updated_at: string; 165 | }[]; 166 | payments: IPayment[]; 167 | total_paid: string; 168 | total_unpaid: string; 169 | total_unpaid_base: string; 170 | prices_are_incl_tax: string; 171 | total_price_excl_tax: string; 172 | total_price_excl_tax_base: string; 173 | total_price_incl_tax: string; 174 | total_price_incl_tax_base: string; 175 | total_discount: string; 176 | marked_dubious_on?: string; 177 | marked_uncollectible_on?: string; 178 | reminder_count: number; 179 | next_reminder: string; 180 | original_estimate_id?: string; 181 | url: string; 182 | payment_url: string; 183 | custom_fields_attributes: { 184 | id: string; 185 | value: string; 186 | }[]; 187 | notes: never[]; 188 | attachments: IAttachment[]; 189 | events: never[]; 190 | tax_totals: { 191 | tax_rate_id: string; 192 | taxable_amount: string; 193 | taxable_amount_base: string; 194 | tax_amount: string; 195 | tax_amount_base: string; 196 | }[]; 197 | } 198 | 199 | export interface IAttachment { 200 | id: string; 201 | administration_id: string; 202 | attachable_id: string; 203 | attachable_type: "SalesInvoice" | string; 204 | file_name: string; 205 | content_type: string; 206 | size: number; 207 | rotation: number; 208 | created_at: string; 209 | updated_at: string; 210 | } 211 | 212 | export type ISalesInvoiceState = 213 | | "draft" 214 | | "open" 215 | | "scheduled" 216 | | "pending_payment" 217 | | "late" 218 | | "reminded" 219 | | "paid" 220 | | "uncollectible"; 221 | 222 | export interface ISalesInvoiceCreate { 223 | contact_id: string; 224 | contact_person_id?: string; 225 | original_estimate_id?: string; 226 | document_style_id: string; 227 | workflow_id: string; 228 | reference: string; 229 | invoice_sequence_id?: string; 230 | invoice_date: string; 231 | first_due_date: string; 232 | currency: string; 233 | prices_are_incl_tax: boolean; 234 | payment_condition: string; 235 | discount: number; 236 | details_attributes: { 237 | id?: string; 238 | description: string; 239 | period?: string; 240 | price: string; 241 | amount?: number | string; 242 | tax_rate_id: string; 243 | ledger_account_id: string; 244 | project_id?: string; 245 | product_id?: string; 246 | time_entry_ids?: string[]; 247 | row_order: number; 248 | _destroy?: boolean; 249 | automated_tax_enabled?: boolean; 250 | }[]; 251 | custom_fields_attributes: { 252 | id: string; 253 | value: string; 254 | }[]; 255 | from_checkout?: boolean; 256 | } 257 | 258 | export interface ISalesInvoiceSending { 259 | delivery_method?: "Email" | "Simplerinvoicing" | "Manual"; 260 | sending_scheduled?: boolean; 261 | deliver_ubl?: boolean; 262 | mergeable?: boolean; 263 | email_address?: string; 264 | email_message?: string; 265 | invoice_date?: string; 266 | } 267 | 268 | export interface IPayment { 269 | id: string; 270 | administration_id: string; 271 | invoice_type: string; 272 | invoice_id: string; 273 | financial_account_id?: string; 274 | user_id: string; 275 | payment_transaction_id?: string; 276 | transaction_identifier?: string; 277 | price: string; 278 | price_base: string; 279 | payment_date: string; 280 | credit_invoice_id?: string; 281 | financial_mutation_id?: string; 282 | ledger_account_id?: string; 283 | linked_payment_id?: string; 284 | manual_payment_action?: IManualPaymentAction; 285 | created_at: string; 286 | updated_at: string; 287 | } 288 | 289 | export interface IPaymentCreate { 290 | payment_date: string; 291 | price: number | string; 292 | price_base?: number; 293 | financial_account_id?: string; 294 | financial_mutation_id?: string; 295 | transaction_identifier?: string; 296 | manual_payment_action?: IManualPaymentAction; 297 | ledger_account_id?: string; 298 | invoice_id?: string; 299 | } 300 | 301 | export type IManualPaymentAction = 302 | | "private_payment" 303 | | "payment_without_proof" 304 | | "cash_payment" 305 | | "rounding_error" 306 | | "bank_transfer" 307 | | "balance_settlement" 308 | | "invoices_settlement"; 309 | 310 | export type ITaxRateType = 311 | | "general_journal_document" 312 | | "purchase_invoice" 313 | | "sales_invoice"; 314 | 315 | export interface ITax { 316 | id: string; 317 | administration_id: string; 318 | name: string; 319 | percentage: string; 320 | tax_rate_type: ITaxRateType; 321 | show_tax: boolean; 322 | active: boolean; 323 | country?: string; 324 | created_at: string; 325 | updated_at: string; 326 | } 327 | 328 | export type ICustomFieldSource = 329 | | "sales_invoice" 330 | | "contact" 331 | | "identity" 332 | | "estimate"; 333 | 334 | export interface ICustomField { 335 | id: string; 336 | administration_id: string; 337 | name: string; 338 | source: ICustomFieldSource; 339 | } 340 | 341 | export type AccountType = 342 | | "non_current_assets" 343 | | "current_assets" 344 | | "equity" 345 | | "provisions" 346 | | "non_current_liabilities" 347 | | "current_liabilities" 348 | | "revenue" 349 | | "direct_costs" 350 | | "expenses" 351 | | "other_income_expenses"; 352 | 353 | export type DocumentType = 354 | | "sales_invoice" 355 | | "purchase_invoice" 356 | | "general_journal_document" 357 | | "financial_mutation" 358 | | "payment"; 359 | 360 | export interface ILedgerAccount { 361 | id: string; 362 | administration_id: string; 363 | name: string; 364 | account_type: AccountType; 365 | account_id?: string; 366 | parent_id?: string; 367 | created_at: string; 368 | updated_at: string; 369 | allowed_document_types: DocumentType[]; 370 | } 371 | 372 | export type WorkflowType = "EstimateWorkflow" | "InvoiceWorkflow"; 373 | 374 | export interface IWorkflow { 375 | id: string; 376 | administration_id: string; 377 | type: string; 378 | name: string; 379 | default: boolean; 380 | currency: string; 381 | language: string; 382 | active: boolean; 383 | prices_are_incl_tax: boolean; 384 | created_at: string; 385 | updated_at: string; 386 | } 387 | 388 | export interface IWebhook { 389 | id: string; 390 | administration_id: string; 391 | url: string; 392 | enabled_events: string[]; 393 | last_http_status: number | null; 394 | last_http_response: unknown | null; 395 | token: string; 396 | } 397 | 398 | export interface IWebhookCreate { 399 | url: string; 400 | /** 401 | * For available events, see https://developer.moneybird.com/webhooks/#events 402 | */ 403 | enabled_events?: string[]; 404 | } 405 | -------------------------------------------------------------------------------- /src/administration.ts: -------------------------------------------------------------------------------- 1 | import { Moneybird } from "./moneybird"; 2 | import { 3 | IAdministration, 4 | IContact, 5 | IContactCreate, 6 | ICustomField, 7 | ILedgerAccount, 8 | ISalesInvoice, 9 | ISalesInvoiceCreate, 10 | ISalesInvoiceState, 11 | ITax, 12 | ITaxRateType, 13 | IWebhook, 14 | IWebhookCreate, 15 | IWorkflow, 16 | } from "./common"; 17 | import { Contact } from "./contact"; 18 | import { HTTP, HttpHandler } from "./httpHandler"; 19 | import { SalesInvoice } from "./salesInvoice"; 20 | 21 | type PaginatedOptions = Partial<{ 22 | // The page to return 23 | page: number; 24 | // The amount of contacts to return per page 25 | per_page: number; 26 | // Whether to include archived contacts 27 | include_archived: boolean; 28 | }>; 29 | 30 | export class Administration { 31 | private readonly moneybird: Moneybird; 32 | private readonly id: string; 33 | public readonly data: IAdministration; 34 | 35 | constructor(moneybird: Moneybird, data: IAdministration) { 36 | this.moneybird = moneybird; 37 | this.id = data.id; 38 | this.data = data; 39 | this.HTTP = new HttpHandler(this.moneybird, `${this.id}`); 40 | } 41 | 42 | ////////////////////////// CONTACTS ////////////////////////// 43 | //region Contacts 44 | 45 | /** 46 | * To perform requests to the Moneybird API in the context of this administration 47 | */ 48 | public readonly HTTP: HTTP; 49 | 50 | /** 51 | * Returns a list of all contacts in the administration 52 | * @param params The parameters for the request 53 | */ 54 | public async contacts( 55 | params?: Partial< 56 | PaginatedOptions & { 57 | // The query to search for in the following fields: 58 | // company_name, attention, firstname, lastname, address1, address2, zipcode, city, country, email, phone, customer_id, tax_number, chamber_of_commerce, bank_account 59 | query: string; 60 | } 61 | > 62 | ): Promise { 63 | const contacts = await this.HTTP.GET("contacts", { 64 | params, 65 | }); 66 | 67 | return contacts.map((c) => new Contact(this.moneybird, this, c)); 68 | } 69 | 70 | /** 71 | * Returns a filtered list of all contacts in the administration 72 | * @param filter The filter to apply to the contacts 73 | * @param pagination The pagination options 74 | */ 75 | public async filterContacts( 76 | filter: Partial<{ 77 | // The first name of the contact case-insensitive 78 | first_name: string; 79 | // The last name of the contact case-insensitive 80 | last_name: string; 81 | // The date the contact was created 82 | created_after: string; 83 | // The date the contact was last updated 84 | updated_after: string; 85 | }>, 86 | pagination: PaginatedOptions = {} 87 | ): Promise { 88 | const filterString = Object.entries(filter) 89 | .map(([key, value]) => `${key}:${value}`) 90 | .join(","); 91 | 92 | const contacts = await this.HTTP.GET(`contacts/filter`, { 93 | params: { 94 | filter: filterString, 95 | ...pagination, 96 | }, 97 | }); 98 | 99 | return contacts.map((c) => new Contact(this.moneybird, this, c)); 100 | } 101 | 102 | // TODO endpoint for /contacts/synchronization 103 | 104 | /** 105 | * Returns a contact object with the given id 106 | * @param id The id of the contact 107 | */ 108 | public async getContact(id: string): Promise { 109 | const contact = await this.HTTP.GET(`contacts/${id}`); 110 | 111 | return new Contact(this.moneybird, this, contact); 112 | } 113 | 114 | /** 115 | * Returns a contact object with the given customer id 116 | * @param id The customer id of the contact 117 | */ 118 | public async getCustomer(id: string): Promise { 119 | const contact = await this.HTTP.GET(`contacts/customer_id/${id}`); 120 | 121 | return new Contact(this.moneybird, this, contact); 122 | } 123 | 124 | /** 125 | * Returns a contact object without fetching the data from the API 126 | * This is useful when you already have the contact id and want to perform actions on it 127 | * @param id The id of the contact 128 | */ 129 | public contact(id: string): Contact { 130 | return new Contact(this.moneybird, this, { id } as IContact); 131 | } 132 | 133 | /** 134 | * Creates a new contact in the administration 135 | * @param contact The contact to create 136 | */ 137 | public async createContact( 138 | contact: Partial 139 | ): Promise { 140 | if (!(contact.company_name || (contact.firstname && contact.lastname))) { 141 | throw new Error( 142 | "Either company_name or first_name and last_name must be set" 143 | ); 144 | } 145 | 146 | const data = await this.HTTP.POST("contacts", { contact }); 147 | 148 | return new Contact(this.moneybird, this, data); 149 | } 150 | 151 | //endregion Contacts 152 | 153 | ////////////////////////// INVOICES ////////////////////////// 154 | //region Invoices 155 | 156 | /** 157 | * Returns a list of all sales invoices in the administration 158 | */ 159 | public async salesInvoices( 160 | params?: PaginatedOptions 161 | ): Promise { 162 | const invoices = await this.HTTP.GET("sales_invoices", { 163 | params, 164 | }); 165 | 166 | return invoices.map((i) => new SalesInvoice(this.moneybird, this, i)); 167 | } 168 | 169 | /** 170 | * Returns a list of all sales invoices in the administration that match the given filter 171 | * @param filter The filter to apply to the invoices 172 | * @param pagination The pagination options 173 | */ 174 | public async filterSalesInvoices( 175 | filter: Partial<{ 176 | // The state of the invoice 177 | state: "all" | ISalesInvoiceState | ISalesInvoiceState[]; 178 | // The period of the invoice, can also be in format YYMMDD..YYMMDD; 179 | // e.g. 150101..150131 means 1 january 2015 until 31 january 2015 180 | period: 181 | | "this_month" 182 | | "prev_month" 183 | | "next_month" 184 | | "this_quarter" 185 | | "prev_quarter" 186 | | "next_quarter" 187 | | "this_year" 188 | | "prev_year" 189 | | "next_year" 190 | | string; 191 | // Select invoices with a certain reference 192 | reference: string; 193 | // Select invoices belonging to a certain contact 194 | contact_id: string; 195 | // Select invoices created by a certain recurring invoice 196 | recurring_sales_invoice_id: string; 197 | // Select invoices that use a certain workflow 198 | workflow_id: string; 199 | // Select invoices created after the given time (exclusive). ISO 8601 formatted string. The time to compare with is in UTC timezone 200 | created_after: string; 201 | // Select invoices updated after the given time (exclusive). ISO 8601 formatted string. The time to compare with is in UTC timezone 202 | updated_after: string; 203 | }>, 204 | pagination: PaginatedOptions = {} 205 | ): Promise { 206 | let filterParam = ""; 207 | 208 | if (filter) { 209 | filterParam = Object.entries(filter) 210 | // @ts-expect-error TS doesn't know that the value is an array 211 | .map(([key, value]) => `${key}:${value.join ? value.join("|") : value}`) 212 | .join(","); 213 | } 214 | 215 | const invoices = await this.HTTP.GET("sales_invoices", { 216 | params: { 217 | filter: filterParam, 218 | ...pagination, 219 | }, 220 | }); 221 | 222 | return invoices.map((i) => new SalesInvoice(this.moneybird, this, i)); 223 | } 224 | 225 | /** 226 | * Returns a sales invoice object with the given id 227 | * @param id The id of the sales invoice 228 | */ 229 | public async getSalesInvoice(id: string): Promise { 230 | const invoice = await this.HTTP.GET(`sales_invoices/${id}`); 231 | 232 | return new SalesInvoice(this.moneybird, this, invoice); 233 | } 234 | 235 | /** 236 | * Returns a sales invoice object without fetching the data from the API 237 | * This is useful when you already have the invoice id and want to perform actions on it 238 | * @param id The id of the sales invoice 239 | */ 240 | public salesInvoice(id: string): SalesInvoice { 241 | return new SalesInvoice(this.moneybird, this, { id } as ISalesInvoice); 242 | } 243 | 244 | /** 245 | * Creates a new sales invoice in the administration 246 | * @param invoice The invoice to create 247 | */ 248 | public async createSalesInvoice( 249 | invoice: Partial 250 | ): Promise { 251 | const data = await this.HTTP.POST("sales_invoices", { 252 | sales_invoice: invoice, 253 | }); 254 | 255 | return new SalesInvoice(this.moneybird, this, data); 256 | } 257 | 258 | //endregion Invoices 259 | 260 | ////////////////////////// TAXES ///////////////////////////// 261 | //region Taxes 262 | 263 | /** 264 | * Returns a list of all taxes in the administration 265 | */ 266 | public async taxes(params?: PaginatedOptions): Promise { 267 | return await this.HTTP.GET("tax_rates", { params }); 268 | } 269 | 270 | /** 271 | * Returns a list of all taxes in the administration that match the given filter 272 | * @param filter The filter to apply to the taxes 273 | * @param pagination The pagination options 274 | */ 275 | public async filterTaxes( 276 | filter: Partial<{ 277 | // Select taxes with a certain name 278 | name: string; 279 | // Select taxes with a partial name 280 | partial_name: string; 281 | // Select taxes with a certain percentage 282 | percentage: number; 283 | // Select taxes with a certain type 284 | tax_rate_type: "all" | ITaxRateType | ITaxRateType[]; 285 | // Select taxes within a certain country 286 | country: string; 287 | // Select taxes that are visible on the invoice 288 | show_tax: boolean; 289 | // Select taxes that are active 290 | active: boolean; 291 | // Select taxes created after the given time (exclusive). ISO 8601 formatted string. The time to compare with is in UTC timezone 292 | created_after: string; 293 | // Select taxes updated after the given time (exclusive). ISO 8601 formatted string. The time to compare with is in UTC timezone 294 | updated_after: string; 295 | }>, 296 | pagination: PaginatedOptions = {} 297 | ): Promise { 298 | let filterParam = ""; 299 | 300 | if (filter) { 301 | filterParam = Object.entries(filter) 302 | // @ts-expect-error TS doesn't know that the value is an array 303 | .map(([key, value]) => `${key}:${value.join ? value.join("|") : value}`) 304 | .join(","); 305 | } 306 | 307 | return await this.HTTP.GET("tax_rates", { 308 | params: { 309 | filter: filterParam, 310 | ...pagination, 311 | }, 312 | }); 313 | } 314 | //endregion Taxes 315 | 316 | ////////////////////////// CUSTOM FIELDS ///////////////////// 317 | //region Custom Fields 318 | 319 | /** 320 | * Returns a list of all custom fields in the administration 321 | */ 322 | public async customFields( 323 | params?: PaginatedOptions 324 | ): Promise { 325 | return await this.HTTP.GET("custom_fields", { params }); 326 | } 327 | //endregion Custom Fields 328 | 329 | ////////////////////////// LEDGER ACCOUNTS /////////////////// 330 | //region Ledger Accounts 331 | 332 | /** 333 | * Returns a list of all ledger accounts in the administration 334 | */ 335 | public async ledgerAccounts( 336 | params?: PaginatedOptions 337 | ): Promise { 338 | return await this.HTTP.GET("ledger_accounts", { params }); 339 | } 340 | 341 | //endregion Ledger Accounts 342 | 343 | ////////////////////////// WORKFLOWS ///////////////////////// 344 | //region Workflows 345 | 346 | /** 347 | * Returns a list of all workflows in the administration 348 | */ 349 | public async workflows(params?: PaginatedOptions): Promise { 350 | return await this.HTTP.GET("workflows", { params }); 351 | } 352 | 353 | //endregion Workflows 354 | 355 | ////////////////////////// WEBHOOKS ///////////////////////// 356 | //region Webhooks 357 | 358 | public async webhooks(params?: PaginatedOptions): Promise { 359 | return await this.HTTP.GET("webhooks", { params }); 360 | } 361 | 362 | public async createWebhook(webhook: IWebhookCreate): Promise { 363 | return await this.HTTP.POST("webhooks", webhook); 364 | } 365 | 366 | public async deleteWebhook(webhook: string | IWebhook): Promise { 367 | const id = typeof webhook === "string" ? webhook : webhook.id; 368 | await this.HTTP.DELETE(`webhooks/${id}`); 369 | } 370 | 371 | //endregion Webhooks 372 | } 373 | --------------------------------------------------------------------------------