heyreach-cli 0.1.3 → 0.1.5

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/AGENTS.md CHANGED
@@ -13,6 +13,9 @@ export HEYREACH_API_KEY="your-api-key-here"
13
13
 
14
14
  # Verify it works
15
15
  heyreach status
16
+
17
+ # Or save credentials (validates key before saving)
18
+ heyreach login --api-key "your-api-key-here"
16
19
  ```
17
20
 
18
21
  **Requirements:** Node.js 18+
@@ -31,6 +34,13 @@ Or pass it per-command:
31
34
  heyreach campaigns list --api-key "your-api-key-here"
32
35
  ```
33
36
 
37
+ Or save it permanently (validates the key first):
38
+
39
+ ```bash
40
+ heyreach login --api-key "your-api-key-here"
41
+ # → {"success":true,"message":"Credentials saved and verified."}
42
+ ```
43
+
34
44
  API keys are generated from: HeyReach → Settings → Integrations → Public API
35
45
 
36
46
  ### Organization API (admin commands)
@@ -49,6 +59,7 @@ Or per-command: `heyreach org workspaces --org-key "your-org-key"`
49
59
  - API keys never expire but can be deleted/deactivated
50
60
  - Workspace key and Organization key are separate — each has its own 300 req/min rate limit
51
61
  - Base URL is fixed: `https://api.heyreach.io/api/public/`
62
+ - `heyreach login` validates the key against the API before saving — invalid keys are rejected immediately
52
63
 
53
64
  ## Output Format
54
65
 
@@ -74,6 +85,17 @@ heyreach campaigns list --quiet
74
85
  {"error":"No API key found. Run \"heyreach login\" or set HEYREACH_API_KEY.","code":"AUTH_ERROR"}
75
86
  ```
76
87
 
88
+ ### Error codes
89
+
90
+ | Code | Meaning |
91
+ |------|---------|
92
+ | `AUTH_ERROR` | Missing or invalid API key |
93
+ | `NOT_FOUND` | Resource doesn't exist (bad ID, no matching lead, etc.) |
94
+ | `VALIDATION_ERROR` | Missing required fields or invalid input |
95
+ | `RATE_LIMIT` | 300 req/min exceeded (auto-retried with backoff) |
96
+ | `SERVER_ERROR` | HeyReach API error (auto-retried up to 3 times) |
97
+ | `HTTP_ERROR` | Other HTTP error |
98
+
77
99
  ## Discovering Commands
78
100
 
79
101
  ```bash
@@ -87,114 +109,122 @@ heyreach campaigns --help
87
109
  heyreach campaigns list --help
88
110
  ```
89
111
 
90
- ## All Command Groups
112
+ ## Complete Command Reference
91
113
 
92
114
  ### campaigns (8 commands)
93
- Manage LinkedIn outreach campaigns — list, get, pause, resume, add leads, stop leads, pull lead analytics.
94
-
95
- ```
96
- list List campaigns (paginated, filterable by keyword/status/account)
97
- get Get a campaign by ID
98
- resume Resume a paused campaign
99
- pause Pause a running campaign
100
- add-leads Add leads to a campaign (V2returns added/updated/failed counts)
101
- stop-lead Stop a lead's progression in a campaign
102
- get-leads Get leads from a campaign with status breakdowns
103
- get-for-lead Find which campaigns a lead is enrolled in
104
- ```
115
+ Manage LinkedIn outreach campaigns.
116
+
117
+ | Command | Required flags | Optional flags | Description |
118
+ |---------|---------------|----------------|-------------|
119
+ | `list` | | `--offset` `--limit` `--keyword` `--statuses` `--account-ids` | List campaigns (paginated) |
120
+ | `get` | `--campaign-id` | — | Get campaign by ID |
121
+ | `resume` | `--campaign-id` | — | Resume a paused campaign |
122
+ | `pause` | `--campaign-id` || Pause a running campaign |
123
+ | `add-leads` | `--campaign-id` `--leads-json` | `--resume-finished` `--resume-paused` | Add leads (V2, returns counts) |
124
+ | `stop-lead` | `--campaign-id` | `--lead-member-id` `--lead-url` | Stop lead progression |
125
+ | `get-leads` | `--campaign-id` | `--offset` `--limit` `--time-from` `--time-to` `--time-filter` | Get leads with analytics |
126
+ | `get-for-lead` | at least one of: `--email` `--linkedin-id` `--profile-url` | `--offset` `--limit` | Find campaigns for a lead |
105
127
 
106
128
  ### inbox (4 commands)
107
- Read and respond to LinkedIn conversations across all connected accounts.
129
+ Read and respond to LinkedIn conversations.
108
130
 
109
- ```
110
- list List conversations (filter by account, campaign, tags, seen status, search)
111
- get Get a conversation with all messages by account ID + conversation ID
112
- send Send a message to a LinkedIn conversation
113
- set-seen Mark a conversation as seen or unseen
114
- ```
131
+ | Command | Required flags | Optional flags | Description |
132
+ |---------|---------------|----------------|-------------|
133
+ | `list` | | `--offset` `--limit` `--account-ids` `--campaign-ids` `--search` `--lead-linkedin-id` `--lead-profile-url` `--tags` `--seen` | List conversations |
134
+ | `get` | `--account-id` `--conversation-id` | — | Get conversation with messages |
135
+ | `send` | `--message` `--conversation-id` `--account-id` | `--subject` | Send a message |
136
+ | `set-seen` | `--conversation-id` `--account-id` `--seen` | — | Mark seen/unseen |
115
137
 
116
138
  ### accounts (2 commands)
117
139
  Manage connected LinkedIn accounts.
118
140
 
119
- ```
120
- list List all LinkedIn accounts (paginated, searchable)
121
- get Get a LinkedIn account by ID
122
- ```
141
+ | Command | Required flags | Optional flags | Description |
142
+ |---------|---------------|----------------|-------------|
143
+ | `list` | — | `--offset` `--limit` `--keyword` | List LinkedIn accounts |
144
+ | `get` | `--account-id` | — | Get account by ID |
123
145
 
124
146
  ### lists (9 commands)
125
147
  Manage lead and company lists.
126
148
 
127
- ```
128
- list List all lists (filter by type, keyword, campaign)
129
- get Get a list by ID
130
- create Create an empty lead or company list
131
- get-leads Get leads from a list (up to 1000 per request)
132
- add-leads Add leads to a list (V2 returns detailed counts)
133
- delete-leads Delete leads from a list by LinkedIn member IDs
134
- delete-leads-by-url Delete leads from a list by LinkedIn profile URLs
135
- get-companies Get companies from a company list
136
- get-for-lead Find which lists a lead belongs to
137
- ```
149
+ | Command | Required flags | Optional flags | Description |
150
+ |---------|---------------|----------------|-------------|
151
+ | `list` | — | `--offset` `--limit` `--keyword` `--list-type` `--campaign-ids` | List all lists |
152
+ | `get` | `--list-id` | | Get list by ID |
153
+ | `create` | `--name` | `--type` | Create empty list |
154
+ | `get-leads` | `--list-id` | `--offset` `--limit` (max 1000) `--keyword` `--profile-url` `--linkedin-id` `--created-from` `--created-to` | Get leads from list |
155
+ | `add-leads` | `--list-id` `--leads-json` | | Add leads (V2, returns counts) |
156
+ | `delete-leads` | `--list-id` `--member-ids` | | Delete by member IDs |
157
+ | `delete-leads-by-url` | `--list-id` `--urls` | — | Delete by profile URLs |
158
+ | `get-companies` | `--list-id` | `--offset` `--limit` (max 1000) `--keyword` | Get companies from list |
159
+ | `get-for-lead` | at least one of: `--email` `--linkedin-id` `--profile-url` | `--offset` `--limit` | Find lists for a lead |
138
160
 
139
161
  ### stats (1 command)
140
162
  Pull campaign analytics with day-by-day breakdown.
141
163
 
142
- ```
143
- overview Overall stats for date range (profile views, messages, connections, reply rates)
144
- ```
164
+ | Command | Required flags | Optional flags | Description |
165
+ |---------|---------------|----------------|-------------|
166
+ | `overview` | — | `--start-date` `--end-date` `--account-ids` `--campaign-ids` | Stats for date range |
167
+
168
+ **Note:** `--start-date` and `--end-date` default to the last 30 days if omitted. Just run `heyreach stats overview` for a quick summary.
145
169
 
146
170
  ### leads (4 commands)
147
171
  Look up and tag individual leads.
148
172
 
149
- ```
150
- get Get lead details by LinkedIn profile URL
151
- add-tags Add tags to a lead (existing tags unchanged)
152
- get-tags Get tags for a lead (alphabetically sorted)
153
- replace-tags Remove all existing tags and replace with new tags
154
- ```
173
+ | Command | Required flags | Optional flags | Description |
174
+ |---------|---------------|----------------|-------------|
175
+ | `get` | `--profile-url` | | Get lead details |
176
+ | `add-tags` | `--tags` | `--profile-url` `--linkedin-id` `--create-if-missing` | Add tags to a lead |
177
+ | `get-tags` | `--profile-url` | | Get tags (alphabetical) |
178
+ | `replace-tags` | `--tags` | `--profile-url` `--linkedin-id` `--create-if-missing` | Replace all tags |
179
+
180
+ **Note:** For `add-tags` and `replace-tags`, provide at least one of `--profile-url` or `--linkedin-id`. The `--create-if-missing` flag (default: true) auto-creates tags that don't exist yet.
155
181
 
156
182
  ### lead-tags (1 command)
157
183
  Create workspace-level tags.
158
184
 
159
- ```
160
- create Create one or multiple tags with display name and color
161
- ```
185
+ | Command | Required flags | Optional flags | Description |
186
+ |---------|---------------|----------------|-------------|
187
+ | `create` | `--tags-json` | — | Create tags with name + color |
188
+
189
+ Example: `heyreach lead-tags create --tags-json '[{"displayName":"Hot Lead","color":"Red"}]'`
162
190
 
163
191
  ### webhooks (5 commands)
164
192
  Subscribe to real-time LinkedIn events.
165
193
 
166
- ```
167
- create Create a webhook for a specific event type
168
- get Get a webhook by ID
169
- list List all webhooks (paginated)
170
- update Update webhook configuration (name, URL, event type, active status)
171
- delete Delete a webhook
172
- ```
194
+ | Command | Required flags | Optional flags | Description |
195
+ |---------|---------------|----------------|-------------|
196
+ | `create` | `--name` `--url` `--event-type` | `--campaign-ids` | Create webhook |
197
+ | `get` | `--webhook-id` | — | Get webhook by ID |
198
+ | `list` | | `--offset` `--limit` | List all webhooks |
199
+ | `update` | `--webhook-id` | `--name` `--url` `--event-type` `--campaign-ids` `--active` | Update webhook |
200
+ | `delete` | `--webhook-id` | — | Delete webhook |
173
201
 
174
202
  ### network (2 commands)
175
203
  Query LinkedIn network connections.
176
204
 
177
- ```
178
- list Get network connections for a LinkedIn sender (uses pageNumber/pageSize pagination)
179
- check Check if a lead is connected to a specific sender
180
- ```
205
+ | Command | Required flags | Optional flags | Description |
206
+ |---------|---------------|----------------|-------------|
207
+ | `list` | `--sender-id` | `--page` `--page-size` | List connections (pageNumber pagination) |
208
+ | `check` | `--sender-id` + one of: `--profile-url` or `--linkedin-id` | — | Check if connected |
181
209
 
182
- ### org (11 commands)
183
- Organization management — requires Organization API key.
210
+ **Note:** Network commands use `--page`/`--page-size` instead of `--offset`/`--limit`.
184
211
 
185
- ```
186
- workspaces List all workspaces
187
- create-workspace Create a new workspace
188
- update-workspace Update workspace name or seat limit
189
- api-keys Get API/integration keys for a workspace
190
- create-api-key Generate a new API key (PUBLIC, N8N, MAKE, ZAPIER, MCP)
191
- users List all org users (filter by role, invitation status)
192
- get-user Get user details by ID
193
- workspace-users List users in a specific workspace
194
- invite-admins Invite users as organization admins
195
- invite-members Invite users with specific workspace permissions
196
- invite-managers Invite external managers with workspace access
197
- ```
212
+ ### org (11 commands)
213
+ Organization management — requires Organization API key (`--org-key` or `HEYREACH_ORG_API_KEY`).
214
+
215
+ | Command | Required flags | Optional flags | Description |
216
+ |---------|---------------|----------------|-------------|
217
+ | `workspaces` | | `--offset` `--limit` | List all workspaces |
218
+ | `create-workspace` | `--name` | `--seats-limit` | Create workspace |
219
+ | `update-workspace` | `--workspace-id` | `--name` `--seats-limit` | Update workspace |
220
+ | `api-keys` | `--workspace-id` | | Get API keys for workspace |
221
+ | `create-api-key` | `--workspace-id` `--type` | — | Generate new API key |
222
+ | `users` | | `--offset` `--limit` `--role` `--invitation-status` | List all org users |
223
+ | `get-user` | `--user-id` | | Get user details |
224
+ | `workspace-users` | `--workspace-id` | `--offset` `--limit` `--role` `--invitation-status` | List workspace users |
225
+ | `invite-admins` | `--inviter-email` `--emails` | — | Invite org admins |
226
+ | `invite-members` | `--inviter-email` `--emails` `--workspace-ids` `--permissions-json` | — | Invite with permissions |
227
+ | `invite-managers` | `--inviter-email` `--emails` `--workspace-ids` | — | Invite external managers |
198
228
 
199
229
  ## Common Workflows
200
230
 
@@ -266,12 +296,14 @@ heyreach webhooks create --name "Connections" \
266
296
  ### Pull analytics
267
297
 
268
298
  ```bash
269
- # Last 30 days overall stats
299
+ # Last 30 days overall stats (dates default automatically)
300
+ heyreach stats overview --pretty
301
+
302
+ # Custom date range
270
303
  heyreach stats overview \
271
304
  --start-date "2025-01-01T00:00:00Z" \
272
305
  --end-date "2025-01-31T23:59:59Z" \
273
306
  --pretty
274
- # → { byDayStats: {...}, overallStats: { messagesSent, totalMessageReplies, ... } }
275
307
  ```
276
308
 
277
309
  ### Manage lists
@@ -324,10 +356,35 @@ heyreach campaigns list --offset 100 --limit 100
324
356
 
325
357
  Response: `{ "totalCount": 250, "items": [...] }`
326
358
 
327
- **Max items per request:** 100 (1000 for lead/company list queries)
359
+ **Max items per request:** 100 (1000 for `lists get-leads` and `lists get-companies`)
328
360
 
329
361
  **Exception:** Network commands use `--page` and `--page-size` instead of offset/limit.
330
362
 
363
+ ## Input Patterns
364
+
365
+ ### Comma-separated lists
366
+ Arrays are passed as comma-separated strings:
367
+ ```bash
368
+ --statuses "IN_PROGRESS,PAUSED"
369
+ --tags "hot,priority"
370
+ --campaign-ids "123,456,789"
371
+ --emails "a@co.com,b@co.com"
372
+ --urls "https://linkedin.com/in/one,https://linkedin.com/in/two"
373
+ ```
374
+
375
+ ### JSON inputs
376
+ Complex nested data uses `--xxx-json` flags:
377
+ ```bash
378
+ # Lead data for campaigns/lists
379
+ --leads-json '[{"lead":{"firstName":"Jane","profileUrl":"..."}}]'
380
+
381
+ # Tag creation
382
+ --tags-json '[{"displayName":"Hot","color":"Red"}]'
383
+
384
+ # Workspace permissions
385
+ --permissions-json '{"viewCampaigns":true,"editManageCampaigns":true}'
386
+ ```
387
+
331
388
  ## Key Enums
332
389
 
333
390
  **Campaign statuses:** DRAFT, IN_PROGRESS, PAUSED, FINISHED, CANCELED, FAILED, STARTING, SCHEDULED
@@ -383,3 +440,5 @@ MCP config for your AI assistant:
383
440
  12. **Org commands need a separate key** — set `HEYREACH_ORG_API_KEY` for `heyreach org ...` commands
384
441
  13. **Lead lookup is by profile URL** — use `--profile-url` to identify leads across most endpoints
385
442
  14. **V2 endpoints are used by default** — `add-leads` returns `{addedLeadsCount, updatedLeadsCount, failedLeadsCount}` instead of just a number
443
+ 15. **Error messages are parsed** — nested API validation errors are extracted into clean, readable messages
444
+ 16. **Login validates keys** — `heyreach login` checks the key against the API before saving, so a successful login means the key works
package/dist/index.js CHANGED
@@ -84,6 +84,7 @@ function extractMessage(raw) {
84
84
  }
85
85
  if (parts.length > 0) return parts.join(". ");
86
86
  }
87
+ if (nested?.errorMessage) return String(nested.errorMessage);
87
88
  return raw;
88
89
  }
89
90
  function safeParse(text) {
@@ -2646,7 +2647,7 @@ import { Command } from "commander";
2646
2647
  var program = new Command();
2647
2648
  program.name("heyreach").description(
2648
2649
  "HeyReach CLI \u2014 manage LinkedIn campaigns, leads, lists, inbox, webhooks, and more from your terminal."
2649
- ).version("0.1.3").option("--pretty", "Pretty-print JSON output").option("--quiet", "Suppress output, exit codes only").option("--fields <fields>", "Comma-separated fields to include in output").option("--api-key <key>", "HeyReach workspace API key").option("--org-key <key>", "HeyReach Organization API key");
2650
+ ).version("0.1.5").option("--pretty", "Pretty-print JSON output").option("--quiet", "Suppress output, exit codes only").option("--fields <fields>", "Comma-separated fields to include in output").option("--api-key <key>", "HeyReach workspace API key").option("--org-key <key>", "HeyReach Organization API key");
2650
2651
  registerAllCommands(program);
2651
2652
  program.parse();
2652
2653
  //# sourceMappingURL=index.js.map