{"id":18313747,"url":"https://github.com/timaschew/comdirect","last_synced_at":"2025-10-24T23:11:23.067Z","repository":{"id":40934383,"uuid":"243330588","full_name":"timaschew/comdirect","owner":"timaschew","description":"Un-official comdirect REST API client for Node.js","archived":false,"fork":false,"pushed_at":"2023-02-23T20:46:01.000Z","size":62,"stargazers_count":12,"open_issues_count":7,"forks_count":5,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-08-28T04:44:22.730Z","etag":null,"topics":["banking-api","comdirect","fintech","fints","online-banking"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/timaschew.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-02-26T18:04:08.000Z","updated_at":"2024-03-08T22:00:34.000Z","dependencies_parsed_at":"2024-11-05T16:49:15.751Z","dependency_job_id":null,"html_url":"https://github.com/timaschew/comdirect","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/timaschew/comdirect","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timaschew%2Fcomdirect","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timaschew%2Fcomdirect/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timaschew%2Fcomdirect/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timaschew%2Fcomdirect/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/timaschew","download_url":"https://codeload.github.com/timaschew/comdirect/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timaschew%2Fcomdirect/sbom","scorecard":{"id":885558,"data":{"date":"2025-08-11","repo":{"name":"github.com/timaschew/comdirect","commit":"016e80861f117c7efd9f5f9a6d6008461f1fefff"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.2,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":0,"reason":"Found 0/21 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":0,"reason":"license file not detected","details":["Warn: project does not have a license file"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":7,"reason":"3 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-pfrx-2q88-qq97","Warn: Project is vulnerable to: GHSA-rc47-6667-2j5j","Warn: Project is vulnerable to: GHSA-px4h-xg32-q955"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-24T09:53:41.954Z","repository_id":40934383,"created_at":"2025-08-24T09:53:41.955Z","updated_at":"2025-08-24T09:53:41.955Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273886640,"owners_count":25185509,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-06T02:00:13.247Z","response_time":2576,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["banking-api","comdirect","fintech","fints","online-banking"],"created_at":"2024-11-05T16:28:40.565Z","updated_at":"2025-10-04T04:50:49.180Z","avatar_url":"https://github.com/timaschew.png","language":"JavaScript","readme":"# comdirect\n\nUn-official node.js module for the [comdirect REST API](https://www.comdirect.de/cms/kontakt-zugaenge-api.html)\n\n## NOTE:\n\nThis module works only with the **photoTAN** method!\n\nUse it at your own risk!  \nIf you enter a wrong TAN 3 times your account will be blocked (to unlock you need to do a phone call).\n\nYou can reset the error counter by enter a valid TAN via the \n[official website](https://kunde.comdirect.de/lp/wt/login) by retreiving your [inbox (PostBox)](https://kunde.comdirect.de/itx/posteingangsuche).\n\nEnable the and handle your [REST API credentials](https://kunde.comdirect.de/itx/oauth/privatkunden).\n\n## Motivation\n\nThe REST API requires 5 HTTP requests (authentication) before you can fetch your bank account information.  \nTo fetch account transactions you need 7 HTTP requests in total.\n\nThe authentication works with an access token which is valid for 10 minutes and a refresh token which is valid for 20 minutes.\nFor each new HTTP request both tokens are changing its value and extending the expiration.\nIf the refresh token is expired you need to authenticate again which means to need to enter a new TAN again.\n\nThis module helps you to make it easys as possible by:\n\n- automate much as possible of the authentication flow\n  - if there is no valid refresh token you need to open a browser and do the TAN challenge (scan picture and and enter a TAN)\n  - if access token is expired but refresh token is valid a new access token is created\n- load the account id automatically in order to allow you to fetch account transactions\n- auto refresh (update the refresh token automatically every 19 minutes, before it will expire)\n- automatically save new access token, refresh token, request id and session id and automatically inject them\n- mask sensitive output in the optional logs (client secret, pin/password, acces token, refresh token)\n- reformat `remittanceInfo` in the transactions (remove `01`, `02`, etc. and split into an array of chunks)\n- persist data (refresh token, account id, etc.) optionally to run your script again without doing the TAN challenge after it has terminated\n\n**Reformated remittanceInfo:**\n\nOriginal:\n\n```\n\"remittanceInfo\": \"01Auszahlung                         \\n02Commerzbank 00102434/Eisenbahnstraß\\n032019-09-23T12:56:40 KFN 1  VJ 1315 \",\n```\n\nReformated:\n\n```\nremittanceInfo: [\n  'Auszahlung                         ',\n  'Commerzbank 00102434/Eisenbahnstraß',\n  '2020-03-02T11:26:15 KFN 1  VJ 1315 '\n],\n```\n\n## Usage\n\n### Install \nEither clone this repository and run `npm install` or install it with `npm install comdirect`.\n\n## Environment variables\n\n```sh\nexport CLIENT_ID=User_A1234B567D901012E0XXXXXXXXXXXXXX\nexport CLIENT_SECRET=ABDBASDBASB12361741623ABACBD\nexport PERSISTENCE=1 # optionally save refresh token, etc. to file, otherwise everything is only in the memory\nexport CREDENTIALS_FILE_PATH='.credentials' # defaults to '$PWD/.credentials', only usefull when PERSISTENCE=1\nexport DEBUG=1 # print all HTTP requests (url, status code, body)\n```\n\n### API\n\n```js\n{start, createServer} = require('comdirect')\nhighLevel = require('comdirect/high-level')\nlowLevel = require('comdirect/low-level')\n```\n\n##### `comdirect.start(config = {autoRefresh: false, webhook: false, port: 8090})`\nFunction with an optional config object.  \n\n`autoRefresh`: update the refresh token every 19 minutes  \n`webhook`:  if true the authorization starts when you open the URL and do login via a browser.  \n`port`: is required to open a URL for the TAN challenge in the browser and the webhook method.  \n\nReturns a promise with the this object:\n```json\n{\n  \"access_token\": \"AAA\",\n  \"refresh_token\": \"BBB\",\n  \"sessionUUID\": \"CCC\",\n  \"sessionId\": \"DDD\",\n  \"requestId\": \"EEE\",\n  \"accountId\": [\"FFF\", \"GGG\"]\n}\n```\n\n##### `comdirect.createServer(config = {autoRefresh: false, webhook: false}, callback)`\n\nLike `comdirect.start` but without starting the server. Instead the function returns a HTTP server\non which you can attach your custom route handlers. You need to start the server manually via `server.listen`\nand handle non matching URLs. The callback is called when the authentication is done.  \nSee the example below for more details. \n\n##### `lowLevel.getAccountBalances()`\n\nShow balances of all your accounts.\n\n##### `lowLevel.getTransactions(accountId, offset, minDate, maxDate)`\n\nOnly 20 transactions are shown in one response. Set `offset` to `20` to see the next entries.  \nDate format example: `2020-02-02`.\n\n##### `lowLevel.refreshTokenFlow()`\n\nUpdates the refresh token.\n\n##### `highLevel.refreshTokenFlowIfNeeded()`\n\nUpdates the access token if needed.\n\n##### Other APIs\n\nPlease check the source code.\n\n\n### Example (interactive CLI)\n\nExample with interactive CLI. Follow instructions in the output.  \nTo scan the TAN challenge you need to use a browser.\n\n```js\nconst comdirect = require('comdirect')\nconst {getTransactions} = require('comdirect/low-level')\nconst {refreshTokenFlowIfNeeded} = require('comdirect/high-level')\n\n;(async function() {\n\tconst result = await comdirect.start({autoRefresh: true, webhook: false})\n\tconst {accountId} = result\n\tlet transactions = await getTransactions(accountId)\n\tconsole.log(transactions.values[0]) // show latest transaction\n\n\t// wait 30 minutes\n\tawait new Promise((resolve, reject) =\u003e setTimeout(resolve, 1000 * 60 * 30))\n\t// ensure a valid access token\n\tawait refreshTokenFlowIfNeeded()\n\ttransactions = await getTransactions(accountId)\n\tconsole.log(transactions.values[0]) // show latest transaction\n})()\n```\n\n### Example (webhook)\n\nSame as above, but just pass `webhook: true` instead.  \n\nThis is esefull when your deployment (and server start) is automated.  \nThe login and TAN challenge is done via any browser.\n\n\n### Example (custom server)\n\nYou can attach other route handler to the server:\n\n```js\nconst comdirect = require('comdirect')\nconst {getTransactions} = require('comdirect/low-level')\nconst {refreshTokenFlowIfNeeded} = require('comdirect/high-level')\n\nlet accountId = null\n\nasync function transactionHandler(req, res) {\n  if (req.url === '/transactions') {\n    try {\n      await refreshTokenFlowIfNeeded()\n      const transactions = await getTransactions(accountId)\n      res.writeHead(200, {'Content-Type': 'application/json'})\n      res.end(JSON.stringify({payload: transactions}))\n    } catch (error) {\n      console.error(error)\n      res.writeHead(400, {'Content-Type': 'application/json'})\n      res.end('check server logs')\n    }\n  }\n}\n\nconst PORT = process.env.port || 8088\n\n;(async function() {\n  const result = await new Promise((resolve, reject) =\u003e {\n    const server = comdirect.createServer({autoRefresh: true, webhook: true}, (error, data) =\u003e {\n      if (error) {\n        return reject(error)\n      }\n      resolve(data)\n    })\n    server.on('request', transactionHandler)\n    server.listen(PORT)\n    console.log('listen on', PORT)\n  })\n  accountId = result.accountId\n})()\n```\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftimaschew%2Fcomdirect","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftimaschew%2Fcomdirect","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftimaschew%2Fcomdirect/lists"}