n8n-nodes-datahyena 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,25 @@
1
+ # n8n-nodes-datahyena
2
+
3
+ n8n community node for [Datahyena](https://datahyena.com): B2B growth signals as one API. Pull funding rounds, acquisitions (M&A), executive moves, company data, and investor data, deduped and matched to a single company.
4
+
5
+ ## Installation
6
+
7
+ In n8n: Settings, Community Nodes, Install, enter `n8n-nodes-datahyena`.
8
+
9
+ ## Credentials
10
+
11
+ Create a **Datahyena API** credential with your API key. Free key (50 credits, no card) at https://app.datahyena.com/register. The node adds the `X-API-Key` header for you, so you only paste the key.
12
+
13
+ ## Resources
14
+
15
+ - **Funding Event**: company, amount, round, date, investors
16
+ - **Acquisition**: acquirer, target, deal value, payment type, date
17
+ - **Executive Move**: person, company, role, seniority, move type
18
+ - **Company**: domain, LinkedIn, HQ, industry, employee count, founded year
19
+ - **Investor**: name, type, HQ, domain
20
+
21
+ Each supports **Get Many** with filters (date, country, round, amount, move type, seniority, investor type, and more) and returns all results via cursor pagination.
22
+
23
+ ## Links
24
+
25
+ [datahyena.com](https://datahyena.com) · [Docs](https://datahyena.com/docs) · [API reference](https://datahyena.com/docs)
@@ -0,0 +1,9 @@
1
+ import type { IAuthenticateGeneric, ICredentialTestRequest, ICredentialType, INodeProperties } from 'n8n-workflow';
2
+ export declare class DatahyenaApi implements ICredentialType {
3
+ name: string;
4
+ displayName: string;
5
+ documentationUrl: string;
6
+ properties: INodeProperties[];
7
+ authenticate: IAuthenticateGeneric;
8
+ test: ICredentialTestRequest;
9
+ }
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DatahyenaApi = void 0;
4
+ class DatahyenaApi {
5
+ constructor() {
6
+ this.name = 'datahyenaApi';
7
+ this.displayName = 'Datahyena API';
8
+ this.documentationUrl = 'https://datahyena.com/docs';
9
+ this.properties = [
10
+ {
11
+ displayName: 'API Key',
12
+ name: 'apiKey',
13
+ type: 'string',
14
+ typeOptions: { password: true },
15
+ default: '',
16
+ required: true,
17
+ description: 'Your Datahyena API key. Free (50 credits, no card) at https://app.datahyena.com/register',
18
+ },
19
+ ];
20
+ this.authenticate = {
21
+ type: 'generic',
22
+ properties: {
23
+ headers: {
24
+ 'X-API-Key': '={{ $credentials.apiKey }}',
25
+ },
26
+ },
27
+ };
28
+ this.test = {
29
+ request: {
30
+ baseURL: 'https://api.datahyena.com/v1',
31
+ url: '/funding-events',
32
+ qs: { limit: 1 },
33
+ },
34
+ };
35
+ }
36
+ }
37
+ exports.DatahyenaApi = DatahyenaApi;
@@ -0,0 +1,5 @@
1
+ import type { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription } from 'n8n-workflow';
2
+ export declare class Datahyena implements INodeType {
3
+ description: INodeTypeDescription;
4
+ execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
5
+ }
@@ -0,0 +1,149 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Datahyena = void 0;
4
+ const ROUTES = {
5
+ fundingEvent: 'funding-events',
6
+ acquisition: 'acquisitions',
7
+ execMove: 'exec-moves',
8
+ company: 'companies',
9
+ investor: 'investors',
10
+ };
11
+ // Which filter params each resource accepts (matches the API DTOs).
12
+ const ALLOWED = {
13
+ fundingEvent: ['since', 'round', 'minAmountUsd', 'maxAmountUsd', 'country'],
14
+ acquisition: ['since', 'minAmountUsd', 'maxAmountUsd', 'paymentType', 'isMerger'],
15
+ execMove: ['since', 'until', 'moveType', 'roleSeniority'],
16
+ company: ['since', 'search', 'country', 'industryGroup', 'employeeCountBucket'],
17
+ investor: ['since', 'search', 'country', 'type'],
18
+ };
19
+ const COUNTRIES = [
20
+ ['AE', 'United Arab Emirates'], ['AR', 'Argentina'], ['AT', 'Austria'], ['AU', 'Australia'],
21
+ ['BD', 'Bangladesh'], ['BE', 'Belgium'], ['BR', 'Brazil'], ['BS', 'Bahamas'], ['CA', 'Canada'],
22
+ ['CH', 'Switzerland'], ['CL', 'Chile'], ['CN', 'China'], ['CO', 'Colombia'], ['CY', 'Cyprus'],
23
+ ['CZ', 'Czechia'], ['DE', 'Germany'], ['DK', 'Denmark'], ['EE', 'Estonia'], ['EG', 'Egypt'],
24
+ ['ES', 'Spain'], ['FI', 'Finland'], ['FR', 'France'], ['GB', 'United Kingdom'], ['GR', 'Greece'],
25
+ ['HK', 'Hong Kong'], ['HU', 'Hungary'], ['ID', 'Indonesia'], ['IE', 'Ireland'], ['IL', 'Israel'],
26
+ ['IN', 'India'], ['IT', 'Italy'], ['JP', 'Japan'], ['KE', 'Kenya'], ['KR', 'South Korea'],
27
+ ['LT', 'Lithuania'], ['LU', 'Luxembourg'], ['LV', 'Latvia'], ['MX', 'Mexico'], ['MY', 'Malaysia'],
28
+ ['NG', 'Nigeria'], ['NL', 'Netherlands'], ['NO', 'Norway'], ['NZ', 'New Zealand'],
29
+ ['PH', 'Philippines'], ['PK', 'Pakistan'], ['PL', 'Poland'], ['PT', 'Portugal'], ['RO', 'Romania'],
30
+ ['RU', 'Russia'], ['SA', 'Saudi Arabia'], ['SE', 'Sweden'], ['SG', 'Singapore'], ['TH', 'Thailand'],
31
+ ['TR', 'Turkey'], ['TW', 'Taiwan'], ['UA', 'Ukraine'], ['US', 'United States'], ['VN', 'Vietnam'],
32
+ ['ZA', 'South Africa'],
33
+ ].map(([value, name]) => ({ name, value }));
34
+ const FUNDING_ROUNDS = ['pre-seed', 'seed', 'angel', 'series-a', 'series-b', 'series-c', 'series-d', 'series-e', 'series-f', 'growth', 'extension', 'bridge', 'convertible', 'safe', 'debt', 'grant', 'pre-ipo', 'secondary', 'pipe', 'other'].map((v) => ({ name: v, value: v }));
35
+ const show = (resources) => ({ displayOptions: { show: { resource: resources } } });
36
+ class Datahyena {
37
+ constructor() {
38
+ this.description = {
39
+ displayName: 'Datahyena',
40
+ name: 'datahyena',
41
+ icon: 'fa:chart-line',
42
+ group: ['transform'],
43
+ version: 1,
44
+ subtitle: '={{ $parameter["resource"] }}',
45
+ description: 'B2B growth signals: funding rounds, acquisitions, exec moves, companies, investors',
46
+ defaults: { name: 'Datahyena' },
47
+ inputs: ['main'],
48
+ outputs: ['main'],
49
+ credentials: [{ name: 'datahyenaApi', required: true }],
50
+ properties: [
51
+ {
52
+ displayName: 'Resource',
53
+ name: 'resource',
54
+ type: 'options',
55
+ noDataExpression: true,
56
+ options: [
57
+ { name: 'Funding Event', value: 'fundingEvent' },
58
+ { name: 'Acquisition', value: 'acquisition' },
59
+ { name: 'Executive Move', value: 'execMove' },
60
+ { name: 'Company', value: 'company' },
61
+ { name: 'Investor', value: 'investor' },
62
+ ],
63
+ default: 'fundingEvent',
64
+ },
65
+ {
66
+ displayName: 'Operation',
67
+ name: 'operation',
68
+ type: 'options',
69
+ noDataExpression: true,
70
+ options: [{ name: 'Get Many', value: 'getMany', action: 'Get many records' }],
71
+ default: 'getMany',
72
+ },
73
+ {
74
+ displayName: 'Return All',
75
+ name: 'returnAll',
76
+ type: 'boolean',
77
+ default: false,
78
+ description: 'Whether to return all results or only up to a limit',
79
+ },
80
+ {
81
+ displayName: 'Limit',
82
+ name: 'limit',
83
+ type: 'number',
84
+ typeOptions: { minValue: 1 },
85
+ default: 50,
86
+ description: 'Max number of results to return',
87
+ displayOptions: { show: { returnAll: [false] } },
88
+ },
89
+ // Filters
90
+ { displayName: 'Since (ISO-8601)', name: 'since', type: 'string', default: '', placeholder: '2026-01-01T00:00:00.000Z', description: 'Only records after this timestamp' },
91
+ { displayName: 'Until (ISO-8601)', name: 'until', type: 'string', default: '', ...show(['execMove']) },
92
+ { displayName: 'HQ Country', name: 'country', type: 'options', default: '', options: [{ name: 'Any', value: '' }, ...COUNTRIES], ...show(['fundingEvent', 'company', 'investor']) },
93
+ { displayName: 'Search', name: 'search', type: 'string', default: '', description: 'Keyword search by name or domain', ...show(['company', 'investor']) },
94
+ { displayName: 'Industry Group', name: 'industryGroup', type: 'string', default: '', ...show(['company']) },
95
+ { displayName: 'Employee Count', name: 'employeeCountBucket', type: 'options', default: '', options: [{ name: 'Any', value: '' }, ...['1-10', '11-50', '51-200', '201-500', '501-1000', '1001-5000', '5001-10000', '10001+'].map((v) => ({ name: v, value: v }))], ...show(['company']) },
96
+ { displayName: 'Funding Rounds', name: 'round', type: 'multiOptions', default: [], options: FUNDING_ROUNDS, ...show(['fundingEvent']) },
97
+ { displayName: 'Min Amount (USD)', name: 'minAmountUsd', type: 'number', default: 0, ...show(['fundingEvent', 'acquisition']) },
98
+ { displayName: 'Max Amount (USD)', name: 'maxAmountUsd', type: 'number', default: 0, ...show(['fundingEvent', 'acquisition']) },
99
+ { displayName: 'Payment Type', name: 'paymentType', type: 'options', default: '', options: [{ name: 'Any', value: '' }, ...['cash', 'stock', 'mixed', 'undisclosed'].map((v) => ({ name: v, value: v }))], ...show(['acquisition']) },
100
+ { displayName: 'Only Mergers', name: 'isMerger', type: 'boolean', default: false, ...show(['acquisition']) },
101
+ { displayName: 'Move Type', name: 'moveType', type: 'options', default: '', options: [{ name: 'Any', value: '' }, ...['appointment', 'promotion', 'departure', 'transition'].map((v) => ({ name: v, value: v }))], ...show(['execMove']) },
102
+ { displayName: 'Role Seniority', name: 'roleSeniority', type: 'multiOptions', default: [], options: [{ name: 'C-Level', value: 'c_level' }, { name: 'VP-Level', value: 'vp_level' }, { name: 'Founder', value: 'founder' }], ...show(['execMove']) },
103
+ { displayName: 'Investor Type', name: 'type', type: 'options', default: '', options: [{ name: 'Any', value: '' }, ...[['vc', 'VC'], ['angel', 'Angel'], ['cvc', 'Corporate VC'], ['pe', 'Private Equity'], ['growth', 'Growth'], ['accelerator', 'Accelerator'], ['family_office', 'Family Office'], ['syndicate', 'Syndicate'], ['unknown', 'Unknown']].map(([value, name]) => ({ name, value }))], ...show(['investor']) },
104
+ ],
105
+ };
106
+ }
107
+ async execute() {
108
+ const resource = this.getNodeParameter('resource', 0);
109
+ const returnAll = this.getNodeParameter('returnAll', 0);
110
+ const limit = returnAll ? Number.POSITIVE_INFINITY : this.getNodeParameter('limit', 0);
111
+ const route = ROUTES[resource];
112
+ const allowed = ALLOWED[resource] ?? [];
113
+ const filters = {};
114
+ for (const key of allowed) {
115
+ const value = this.getNodeParameter(key, 0, undefined);
116
+ if (value === undefined || value === null || value === '' || value === 0)
117
+ continue;
118
+ if (Array.isArray(value) && value.length === 0)
119
+ continue;
120
+ filters[key] = value;
121
+ }
122
+ const out = [];
123
+ let cursor;
124
+ let fetched = 0;
125
+ do {
126
+ const pageLimit = Math.min(100, returnAll ? 100 : limit - fetched);
127
+ const qs = { ...filters, limit: pageLimit };
128
+ if (cursor)
129
+ qs.cursor = cursor;
130
+ const response = (await this.helpers.httpRequestWithAuthentication.call(this, 'datahyenaApi', {
131
+ method: 'GET',
132
+ baseURL: 'https://api.datahyena.com/v1',
133
+ url: `/${route}`,
134
+ qs,
135
+ json: true,
136
+ }));
137
+ const data = Array.isArray(response.data) ? response.data : [];
138
+ for (const item of data) {
139
+ out.push({ json: item });
140
+ fetched += 1;
141
+ if (fetched >= limit)
142
+ break;
143
+ }
144
+ cursor = response.pagination?.hasMore ? response.pagination?.nextCursor : undefined;
145
+ } while (cursor && fetched < limit);
146
+ return [out];
147
+ }
148
+ }
149
+ exports.Datahyena = Datahyena;
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "n8n-nodes-datahyena",
3
+ "version": "0.1.0",
4
+ "description": "n8n community node for the Datahyena B2B growth-signals API: funding rounds, acquisitions, executive moves, companies, and investors.",
5
+ "keywords": [
6
+ "n8n-community-node-package",
7
+ "datahyena",
8
+ "funding",
9
+ "signals",
10
+ "b2b",
11
+ "intent",
12
+ "sales"
13
+ ],
14
+ "license": "MIT",
15
+ "homepage": "https://datahyena.com",
16
+ "author": {
17
+ "name": "Datahyena",
18
+ "email": "team@datahyena.com"
19
+ },
20
+ "main": "index.js",
21
+ "scripts": {
22
+ "build": "tsc",
23
+ "dev": "tsc --watch",
24
+ "prepublishOnly": "tsc"
25
+ },
26
+ "files": [
27
+ "dist"
28
+ ],
29
+ "n8n": {
30
+ "n8nNodesApiVersion": 1,
31
+ "credentials": [
32
+ "dist/credentials/DatahyenaApi.credentials.js"
33
+ ],
34
+ "nodes": [
35
+ "dist/nodes/Datahyena/Datahyena.node.js"
36
+ ]
37
+ },
38
+ "devDependencies": {
39
+ "@types/node": "^20.0.0",
40
+ "n8n-workflow": "*",
41
+ "typescript": "^5.5.0"
42
+ },
43
+ "peerDependencies": {
44
+ "n8n-workflow": "*"
45
+ }
46
+ }