├── .gitignore ├── .prettierrc ├── README.md ├── config.js ├── example.js ├── index.js ├── package-lock.json └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .env 3 | node_modules -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true 3 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Real Time & Query API for Financial News 2 | 3 | - Covers more than 10,000 news sources (Reuters, Bloomberg, The Wall 4 | Street Journal, Seeking Alpha, SEC, and many more). [See the full list of 5 | sources here.](https://newsfilter.io) 6 | - Real-time financial news stream using websockets. The API returns a new article 7 | as soon as it is published on one of the supported news platforms. 8 | - Query API to search the [newsfilter.io](https://newsfilter.io) article database 9 | - JSON formatted 10 | - Articles mapped to company ticker 11 | - Supports Python, C++, JavaScript (Node.js, React, jQuery, Angular, Vue), Java 12 | and Excel plugins using websocket or socket.io clients 13 | 14 | ![https://i.imgur.com/Rd7x9Mi.png](https://i.imgur.com/Rd7x9Mi.png) 15 | 16 | # Real Time Streaming API 17 | 18 | You can use the streaming API in your command line, or develop your own application 19 | using the API as imported package. Both options are explained below. 20 | 21 | **Before you start**: 22 | 23 | - Install Node.js if you haven't already. On Mac in the command line type `brew install node`. 24 | 25 | ## Command Line 26 | 27 | Type in your command line: 28 | 29 | 1. `npm install realtime-newsapi -g` to install the package 30 | 2. `realtime-newsapi` to connect to the stream 31 | 3. Done! You will see new articles printed in your command line 32 | as soon as they are published on one of the supported news platforms. 33 | 34 | ## Node.js 35 | 36 | Type in your command line: 37 | 38 | 1. `mkdir my-project && cd my-project` to create a new folder for your project. 39 | 2. `npm init -y` to set up Node.js boilerplate. 40 | 3. `npm install realtime-newsapi` to install the package. 41 | 4. `touch index.js` to create a new file. Copy/paste the example code below 42 | into the file index.js. 43 | 44 | ```js 45 | const api = require('realtime-newsapi')(); 46 | 47 | api.on('articles', (articles) => { 48 | console.log(articles); 49 | }); 50 | ``` 51 | 52 | 5. `node index.js` to start listening for new articles. New filings are 53 | printed in your console as soon as they are published on one of the supported news platforms. 54 | 55 | ## Live Demo 56 | 57 | [https://codesandbox.io/s/k5q6nwqkrr](https://codesandbox.io/s/k5q6nwqkrr) 58 | 59 | # Query API 60 | 61 | Use `curl` or Postman to send requests to the query API. Articles that match your filter criteria are returned in JSON 62 | format. 63 | 64 | - API endpoint: `https://api.newsfilter.io/public/actions` 65 | - Supported HTTP Method: `POST` 66 | - Supported content type: `JSON` 67 | 68 | ## Example - FDA Approvals 69 | 70 | Return all articles with "FDA Approval" in the title or description of the article. 71 | 72 | Demo: [https://reqbin.com/bf9gon0l](https://reqbin.com/bf9gon0l) 73 | 74 | ```json 75 | { 76 | "type": "filterArticles", 77 | "queryString": "title:\"FDA Approval\" OR description:\"FDA Approval\"" 78 | } 79 | ``` 80 | 81 | ## Example - AAPL 82 | 83 | Return all articles with mentioning `AAPL`. 84 | 85 | Demo: [https://reqbin.com/b6qkjsyl](https://reqbin.com/b6qkjsyl) 86 | 87 | ```json 88 | { 89 | "type": "filterArticles", 90 | "queryString": "title:AAPL OR description:AAPL OR symbols:AAPL" 91 | } 92 | ``` 93 | 94 | # Response Format 95 | 96 | - `id` (string) - unique ID of the article 97 | - `title` (string) - title of the article 98 | - `description` (string) - description of the article 99 | - `symbols` (array) - array of ticker symbols mentioned in the article, e.g. AAPL 100 | - `url` (string) - URL to original article 101 | - `publishedAt` (string) - ISO 8601 formatted date of publication time 102 | - `source` (object) 103 | - `id` (string) - unique ID of news source 104 | - `name` (string) - human readable name of news source 105 | - `author` (string) - name of the author 106 | 107 | ## Example 108 | 109 | ``` 110 | [ 111 | { 112 | source: { 113 | id: 'seekingAlpha', 114 | name: 'Seeking Alpha' 115 | }, 116 | symbols: ['EWH'], 117 | title: 'Hang Seng soars despite massive rally', 118 | description: 'Hong Kong is gearing up for more protests this week after hundreds of thousands of anti-government demonstrators braved heavy rain to rally peacefully on Sunday, marking a change to what have often been violent clashes.The scenes showed that the movement is far from fizzling out, triggering fears about retail, tourism and business confidence, as well as worries over the city\'s stock and property markets.The Hang Seng index still rose 2.2% overnight following a healthy lead from Wall Street and key interest rate reforms from the People\'s Bank of China.ETFs: EWH, FHK, FLHK', 119 | url: 'https://seekingalpha.com/news/3492784-hang-seng-soars-despite-massive-rally', 120 | publishedAt: '2019-08-19T03:23:00-04:00', 121 | id: 'c7007ef5eae6cf50225cc4f19d368fe5' 122 | }, 123 | { 124 | source: { 125 | id: 'businesswire', 126 | name: 'BusinessWire' 127 | }, 128 | symbols: ['CELG'], 129 | title: 'U.S. FDA Approves INREBIC® (Fedratinib) as First New Treatment in Nearly a Decade for Patients With Myelofibrosis', 130 | description: 'SUMMIT, N.J.--(BUSINESS WIRE)--Celgene Corporation (NASDAQ: CELG) today announced the U.S. Food and Drug Administration (FDA) has approved INREBIC® (fedratinib) for the treatment of adult patients with intermediate-2 or high-risk primary or secondary (post-polycythemia vera or post-essential thrombocythemia) myelofibrosis.1', 131 | url: 'https://www.businesswire.com/news/home/20190816005292/en/U.S.-FDA-Approves-INREBIC%C2%AE-Fedratinib-New-Treatment', 132 | publishedAt: '2019-08-16T14:30:00+00:00', 133 | id: '129bd08d615d573fed8e12dbb917436e' 134 | } 135 | ]; 136 | ``` 137 | 138 | # Consulting 139 | 140 | This service is already used around the world by startups, top news organizations, graduate school researchers, 141 | and, of course, hackers like you :) 142 | If you or your company are interested in more advanced features feel free to email & contact me for consulting. 143 | -------------------------------------------------------------------------------- /config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | io: { 3 | filterId: 'all', 4 | server: 'https://api.newsfilter.io' 5 | } 6 | }; 7 | -------------------------------------------------------------------------------- /example.js: -------------------------------------------------------------------------------- 1 | const api = require('./index')(); 2 | 3 | api.on('articles', articles => console.log(articles)); 4 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const io = require('socket.io-client'); 4 | const config = require('./config'); 5 | const events = require('events'); 6 | const store = {}; 7 | 8 | const subscribe = () => { 9 | store.socket.emit('action', { 10 | type: 'subscribe', 11 | filterId: config.io.filterId 12 | }); 13 | }; 14 | 15 | const initSocket = () => { 16 | const uri = config.io.server; 17 | store.socket = io(uri); 18 | store.socket.on('connect', subscribe); 19 | store.socket.on('articles', handleNewArticles); 20 | }; 21 | 22 | const handleNewArticles = ({ articles = [] }) => { 23 | if (articles.length > 0) { 24 | store.eventEmitter.emit('articles', articles); 25 | } 26 | }; 27 | 28 | module.exports.close = () => { 29 | if (store.socket.close) { 30 | store.socket.close(); 31 | } 32 | }; 33 | 34 | module.exports = () => { 35 | initSocket(); 36 | store.eventEmitter = new events.EventEmitter(); 37 | return store.eventEmitter; 38 | }; 39 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "realtime-newsapi", 3 | "version": "1.1.2", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "after": { 8 | "version": "0.8.2", 9 | "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", 10 | "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=" 11 | }, 12 | "arraybuffer.slice": { 13 | "version": "0.0.7", 14 | "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", 15 | "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==" 16 | }, 17 | "backo2": { 18 | "version": "1.0.2", 19 | "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", 20 | "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=" 21 | }, 22 | "base64-arraybuffer": { 23 | "version": "0.1.4", 24 | "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz", 25 | "integrity": "sha1-mBjHngWbE1X5fgQooBfIOOkLqBI=" 26 | }, 27 | "blob": { 28 | "version": "0.0.5", 29 | "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", 30 | "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==" 31 | }, 32 | "component-bind": { 33 | "version": "1.0.0", 34 | "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", 35 | "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=" 36 | }, 37 | "component-emitter": { 38 | "version": "1.3.0", 39 | "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", 40 | "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" 41 | }, 42 | "component-inherit": { 43 | "version": "0.0.3", 44 | "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", 45 | "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=" 46 | }, 47 | "debug": { 48 | "version": "3.1.0", 49 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", 50 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", 51 | "requires": { 52 | "ms": "2.0.0" 53 | } 54 | }, 55 | "engine.io-client": { 56 | "version": "3.5.2", 57 | "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.5.2.tgz", 58 | "integrity": "sha512-QEqIp+gJ/kMHeUun7f5Vv3bteRHppHH/FMBQX/esFj/fuYfjyUKWGMo3VCvIP/V8bE9KcjHmRZrhIz2Z9oNsDA==", 59 | "requires": { 60 | "component-emitter": "~1.3.0", 61 | "component-inherit": "0.0.3", 62 | "debug": "~3.1.0", 63 | "engine.io-parser": "~2.2.0", 64 | "has-cors": "1.1.0", 65 | "indexof": "0.0.1", 66 | "parseqs": "0.0.6", 67 | "parseuri": "0.0.6", 68 | "ws": "~7.4.2", 69 | "xmlhttprequest-ssl": "~1.6.2", 70 | "yeast": "0.1.2" 71 | } 72 | }, 73 | "engine.io-parser": { 74 | "version": "2.2.1", 75 | "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.2.1.tgz", 76 | "integrity": "sha512-x+dN/fBH8Ro8TFwJ+rkB2AmuVw9Yu2mockR/p3W8f8YtExwFgDvBDi0GWyb4ZLkpahtDGZgtr3zLovanJghPqg==", 77 | "requires": { 78 | "after": "0.8.2", 79 | "arraybuffer.slice": "~0.0.7", 80 | "base64-arraybuffer": "0.1.4", 81 | "blob": "0.0.5", 82 | "has-binary2": "~1.0.2" 83 | } 84 | }, 85 | "has-binary2": { 86 | "version": "1.0.3", 87 | "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", 88 | "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", 89 | "requires": { 90 | "isarray": "2.0.1" 91 | } 92 | }, 93 | "has-cors": { 94 | "version": "1.1.0", 95 | "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", 96 | "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=" 97 | }, 98 | "indexof": { 99 | "version": "0.0.1", 100 | "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", 101 | "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=" 102 | }, 103 | "isarray": { 104 | "version": "2.0.1", 105 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", 106 | "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" 107 | }, 108 | "ms": { 109 | "version": "2.0.0", 110 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 111 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 112 | }, 113 | "parseqs": { 114 | "version": "0.0.6", 115 | "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.6.tgz", 116 | "integrity": "sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w==" 117 | }, 118 | "parseuri": { 119 | "version": "0.0.6", 120 | "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.6.tgz", 121 | "integrity": "sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow==" 122 | }, 123 | "socket.io-client": { 124 | "version": "2.4.0", 125 | "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.4.0.tgz", 126 | "integrity": "sha512-M6xhnKQHuuZd4Ba9vltCLT9oa+YvTsP8j9NcEiLElfIg8KeYPyhWOes6x4t+LTAC8enQbE/995AdTem2uNyKKQ==", 127 | "requires": { 128 | "backo2": "1.0.2", 129 | "component-bind": "1.0.0", 130 | "component-emitter": "~1.3.0", 131 | "debug": "~3.1.0", 132 | "engine.io-client": "~3.5.0", 133 | "has-binary2": "~1.0.2", 134 | "indexof": "0.0.1", 135 | "parseqs": "0.0.6", 136 | "parseuri": "0.0.6", 137 | "socket.io-parser": "~3.3.0", 138 | "to-array": "0.1.4" 139 | } 140 | }, 141 | "socket.io-parser": { 142 | "version": "3.3.2", 143 | "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.2.tgz", 144 | "integrity": "sha512-FJvDBuOALxdCI9qwRrO/Rfp9yfndRtc1jSgVgV8FDraihmSP/MLGD5PEuJrNfjALvcQ+vMDM/33AWOYP/JSjDg==", 145 | "requires": { 146 | "component-emitter": "~1.3.0", 147 | "debug": "~3.1.0", 148 | "isarray": "2.0.1" 149 | } 150 | }, 151 | "to-array": { 152 | "version": "0.1.4", 153 | "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", 154 | "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=" 155 | }, 156 | "ws": { 157 | "version": "7.4.6", 158 | "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", 159 | "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==" 160 | }, 161 | "xmlhttprequest-ssl": { 162 | "version": "1.6.3", 163 | "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.6.3.tgz", 164 | "integrity": "sha512-3XfeQE/wNkvrIktn2Kf0869fC0BN6UpydVasGIeSm2B1Llihf7/0UfZM+eCkOw3P7bP4+qPgqhm7ZoxuJtFU0Q==" 165 | }, 166 | "yeast": { 167 | "version": "0.1.2", 168 | "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", 169 | "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=" 170 | } 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "realtime-newsapi", 3 | "version": "1.1.2", 4 | "description": "Realtime News API", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node index.js", 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/janlukasschroeder/realtime-newsapi.git" 13 | }, 14 | "keywords": [ 15 | "Realtime", 16 | "News", 17 | "API", 18 | "Financial news", 19 | "News API", 20 | "News stream", 21 | "SEC filings", 22 | "Reuters", 23 | "Bloomberg", 24 | "JSON news", 25 | "Analyst ratings", 26 | "The Wall Street Journal", 27 | "Seeking Alpha", 28 | "News aggregator" 29 | ], 30 | "author": "Jan Schroeder", 31 | "license": "MIT", 32 | "bugs": { 33 | "url": "https://github.com/janlukasschroeder/realtime-newsapi/issues" 34 | }, 35 | "homepage": "https://github.com/janlukasschroeder/realtime-newsapi#readme", 36 | "dependencies": { 37 | "socket.io-client": "^2.4.0" 38 | }, 39 | "bin": { 40 | "realtime-newsapi": "./index.js" 41 | } 42 | } 43 | --------------------------------------------------------------------------------