autotouch-cli 0.2.72__tar.gz → 0.2.74__tar.gz

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.
Files changed (53) hide show
  1. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/PKG-INFO +4 -1
  2. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/README.md +3 -0
  3. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/autotouch_cli/cli.py +6 -0
  4. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/autotouch_cli/commands/linkedin.py +252 -1
  5. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/autotouch_cli/data/CLI_REFERENCE.md +165 -5
  6. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/autotouch_cli/data/cli-manifest.json +977 -3
  7. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/autotouch_cli/parser.py +3 -0
  8. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/autotouch_cli.egg-info/PKG-INFO +4 -1
  9. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/autotouch_shared/linkedin_contract.py +68 -1
  10. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/autotouch_shared/linkedin_filters.py +151 -3
  11. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/pyproject.toml +1 -1
  12. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/MANIFEST.in +0 -0
  13. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/autotouch_cli/__init__.py +0 -0
  14. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/autotouch_cli/cli_contracts.py +0 -0
  15. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/autotouch_cli/commands/__init__.py +0 -0
  16. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/autotouch_cli/commands/agents.py +0 -0
  17. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/autotouch_cli/commands/auth.py +0 -0
  18. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/autotouch_cli/commands/cells.py +0 -0
  19. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/autotouch_cli/commands/columns.py +0 -0
  20. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/autotouch_cli/commands/jobs.py +0 -0
  21. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/autotouch_cli/commands/leads.py +0 -0
  22. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/autotouch_cli/commands/prompts.py +0 -0
  23. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/autotouch_cli/commands/rows.py +0 -0
  24. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/autotouch_cli/commands/search.py +0 -0
  25. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/autotouch_cli/commands/sequences.py +0 -0
  26. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/autotouch_cli/commands/tables.py +0 -0
  27. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/autotouch_cli/commands/tasks.py +0 -0
  28. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/autotouch_cli/commands/webhooks.py +0 -0
  29. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/autotouch_cli/commands/workspace_secrets.py +0 -0
  30. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/autotouch_cli/core/__init__.py +0 -0
  31. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/autotouch_cli/core/auth.py +0 -0
  32. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/autotouch_cli/core/config.py +0 -0
  33. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/autotouch_cli/core/csv_import.py +0 -0
  34. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/autotouch_cli/core/http.py +0 -0
  35. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/autotouch_cli/core/io.py +0 -0
  36. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/autotouch_cli/core/output.py +0 -0
  37. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/autotouch_cli/core/polling.py +0 -0
  38. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/autotouch_cli/core/run.py +0 -0
  39. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/autotouch_cli/core/validation.py +0 -0
  40. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/autotouch_cli/exceptions.py +0 -0
  41. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/autotouch_cli/mongo_status.py +0 -0
  42. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/autotouch_cli/parser_groups.py +0 -0
  43. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/autotouch_cli/sequence_support.py +0 -0
  44. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/autotouch_cli/templates.py +0 -0
  45. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/autotouch_cli.egg-info/SOURCES.txt +0 -0
  46. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/autotouch_cli.egg-info/dependency_links.txt +0 -0
  47. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/autotouch_cli.egg-info/entry_points.txt +0 -0
  48. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/autotouch_cli.egg-info/requires.txt +0 -0
  49. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/autotouch_cli.egg-info/top_level.txt +0 -0
  50. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/autotouch_shared/__init__.py +0 -0
  51. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/autotouch_shared/provider_registry.py +0 -0
  52. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/autotouch_shared/search_contract.py +0 -0
  53. {autotouch_cli-0.2.72 → autotouch_cli-0.2.74}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: autotouch-cli
3
- Version: 0.2.72
3
+ Version: 0.2.74
4
4
  Summary: Autotouch Smart Table CLI
5
5
  Project-URL: Homepage, https://app.autotouch.ai
6
6
  Project-URL: Documentation, https://github.com/nicolonic/autotouch_main/tree/main/docs/research-table/reference
@@ -134,6 +134,7 @@ autotouch rows get --table-id "$TABLE_ID" --row-id "$ROW_ID" --output json
134
134
  - Create a workflow column: `autotouch columns recipe`, `autotouch columns create`
135
135
  - Run provider-hidden search: `autotouch search companies`, `autotouch search people`
136
136
  - Inspect LinkedIn/Sales Nav filters: `autotouch linkedin filters --api sales_navigator --category people`
137
+ - Build a paced LinkedIn people list on Smart Table workers: `autotouch linkedin list-build create --company-query 'SaaS startups' --headcount 1-10 --people-query 'Account Executive OR SDR' --num-results 250 --wait`
137
138
  - Run one LinkedIn search page/debug replay: `autotouch linkedin search`
138
139
  - Run controlled slices: `autotouch columns run-next`
139
140
  - Poll authoritative state: `autotouch jobs get`
@@ -148,6 +149,8 @@ For automation or agent-driven setup, use:
148
149
  - `autotouch cli-reference` for the shipped parser-generated reference
149
150
  - `autotouch capabilities --output json` for provider/workflow contracts
150
151
  - `autotouch linkedin filters --output json` for LinkedIn/Sales Navigator filter tokens such as headcount, industry, location, role, function, and seniority
152
+ - `autotouch linkedin list-build create` for durable LinkedIn/Sales Navigator list building with Smart Table-owned paced provider requests, visible progress, and cooldown status
153
+ - `autotouch linkedin search` for one-page LinkedIn/Sales Navigator replay/debug searches; it is not the recommended path for large lists
151
154
  - `autotouch rows list` / `autotouch rows get` / `autotouch cells get` for read-back and audit
152
155
  - `autotouch sequences ...` and `autotouch tasks ...` for sequence/task workflows
153
156
  - `pip install 'autotouch-cli[mongo]'` if you need the Mongo-backed `status` / `watch` commands
@@ -109,6 +109,7 @@ autotouch rows get --table-id "$TABLE_ID" --row-id "$ROW_ID" --output json
109
109
  - Create a workflow column: `autotouch columns recipe`, `autotouch columns create`
110
110
  - Run provider-hidden search: `autotouch search companies`, `autotouch search people`
111
111
  - Inspect LinkedIn/Sales Nav filters: `autotouch linkedin filters --api sales_navigator --category people`
112
+ - Build a paced LinkedIn people list on Smart Table workers: `autotouch linkedin list-build create --company-query 'SaaS startups' --headcount 1-10 --people-query 'Account Executive OR SDR' --num-results 250 --wait`
112
113
  - Run one LinkedIn search page/debug replay: `autotouch linkedin search`
113
114
  - Run controlled slices: `autotouch columns run-next`
114
115
  - Poll authoritative state: `autotouch jobs get`
@@ -123,6 +124,8 @@ For automation or agent-driven setup, use:
123
124
  - `autotouch cli-reference` for the shipped parser-generated reference
124
125
  - `autotouch capabilities --output json` for provider/workflow contracts
125
126
  - `autotouch linkedin filters --output json` for LinkedIn/Sales Navigator filter tokens such as headcount, industry, location, role, function, and seniority
127
+ - `autotouch linkedin list-build create` for durable LinkedIn/Sales Navigator list building with Smart Table-owned paced provider requests, visible progress, and cooldown status
128
+ - `autotouch linkedin search` for one-page LinkedIn/Sales Navigator replay/debug searches; it is not the recommended path for large lists
126
129
  - `autotouch rows list` / `autotouch rows get` / `autotouch cells get` for read-back and audit
127
130
  - `autotouch sequences ...` and `autotouch tasks ...` for sequence/task workflows
128
131
  - `pip install 'autotouch-cli[mongo]'` if you need the Mongo-backed `status` / `watch` commands
@@ -95,6 +95,9 @@ from autotouch_cli.commands.linkedin import (
95
95
  cmd_linkedin_comments as cmd_linkedin_comments_impl,
96
96
  cmd_linkedin_filters as cmd_linkedin_filters_impl,
97
97
  cmd_linkedin_limits as cmd_linkedin_limits_impl,
98
+ cmd_linkedin_list_build_create as cmd_linkedin_list_build_create_impl,
99
+ cmd_linkedin_list_build_results as cmd_linkedin_list_build_results_impl,
100
+ cmd_linkedin_list_build_status as cmd_linkedin_list_build_status_impl,
98
101
  cmd_linkedin_post as cmd_linkedin_post_impl,
99
102
  cmd_linkedin_posts as cmd_linkedin_posts_impl,
100
103
  cmd_linkedin_reactions as cmd_linkedin_reactions_impl,
@@ -1546,6 +1549,9 @@ _register("linkedin_limits", cmd_linkedin_limits_impl, _linkedin_command_runtime
1546
1549
  _register("linkedin_search", cmd_linkedin_search_impl, _linkedin_command_runtime)
1547
1550
  _register("linkedin_search_params", cmd_linkedin_search_params_impl, _linkedin_command_runtime)
1548
1551
  _register("linkedin_filters", cmd_linkedin_filters_impl, _linkedin_command_runtime)
1552
+ _register("linkedin_list_build_create", cmd_linkedin_list_build_create_impl, _linkedin_command_runtime)
1553
+ _register("linkedin_list_build_status", cmd_linkedin_list_build_status_impl, _linkedin_command_runtime)
1554
+ _register("linkedin_list_build_results", cmd_linkedin_list_build_results_impl, _linkedin_command_runtime)
1549
1555
  _register("linkedin_posts", cmd_linkedin_posts_impl, _linkedin_command_runtime)
1550
1556
  _register("linkedin_post", cmd_linkedin_post_impl, _linkedin_command_runtime)
1551
1557
  _register("linkedin_comments", cmd_linkedin_comments_impl, _linkedin_command_runtime)
@@ -2,8 +2,9 @@ from __future__ import annotations
2
2
 
3
3
  import argparse
4
4
  import json
5
+ import time
5
6
  from dataclasses import dataclass
6
- from typing import Any, Callable, Dict, Optional, Sequence
7
+ from typing import Any, Callable, Dict, List, Optional, Sequence
7
8
 
8
9
  from autotouch_shared.linkedin_filters import linkedin_filter_catalog
9
10
  from autotouch_cli.exceptions import AutotouchInputError
@@ -118,6 +119,208 @@ def cmd_linkedin_search_params(args: argparse.Namespace, *, runtime: LinkedInCom
118
119
  runtime.print_json(data, args.compact)
119
120
 
120
121
 
122
+ def _load_optional_json_object(raw: Optional[str], *, context: str) -> Optional[Dict[str, Any]]:
123
+ if not raw:
124
+ return None
125
+ try:
126
+ parsed = json.loads(raw)
127
+ except Exception as exc:
128
+ raise AutotouchInputError(f"invalid JSON for {context}: {exc}") from exc
129
+ if not isinstance(parsed, dict):
130
+ raise AutotouchInputError(f"{context} must be a JSON object")
131
+ return parsed
132
+
133
+
134
+ def _split_repeated_values(values: Optional[List[str]]) -> List[str]:
135
+ output: List[str] = []
136
+ for raw in values or []:
137
+ for part in str(raw).replace("\n", ",").split(","):
138
+ value = part.strip()
139
+ if value:
140
+ output.append(value)
141
+ return output
142
+
143
+
144
+ def _coerce_filter_arg_value(raw: str) -> Any:
145
+ value = str(raw or "").strip()
146
+ if not value:
147
+ return ""
148
+ if value[0] in "[{\"" or value.lower() in {"true", "false", "null"}:
149
+ try:
150
+ return json.loads(value)
151
+ except Exception:
152
+ pass
153
+ if "," in value:
154
+ return [part.strip() for part in value.split(",") if part.strip()]
155
+ return value
156
+
157
+
158
+ def _parse_filter_pairs(values: Optional[List[str]], *, context: str) -> Dict[str, Any]:
159
+ filters: Dict[str, Any] = {}
160
+ for raw in values or []:
161
+ item = str(raw or "").strip()
162
+ if not item:
163
+ continue
164
+ if "=" not in item:
165
+ raise AutotouchInputError(f"{context} filters must use FIELD=VALUE")
166
+ field, value = item.split("=", 1)
167
+ field = field.strip()
168
+ if not field:
169
+ raise AutotouchInputError(f"{context} filter field is empty")
170
+ filters[field] = _coerce_filter_arg_value(value)
171
+ return filters
172
+
173
+
174
+ def _add_repeated_filter(filters: Dict[str, Any], field: str, values: Optional[List[str]]) -> None:
175
+ parsed = _split_repeated_values(values)
176
+ if parsed:
177
+ filters[field] = parsed
178
+
179
+
180
+ def _normalize_linkedin_list_build_payload(args: argparse.Namespace, *, runtime: LinkedInCommandRuntime) -> Dict[str, Any]:
181
+ explicit = runtime.load_json_input(
182
+ inline_json=getattr(args, "data_json", None),
183
+ file_path=getattr(args, "data_file", None),
184
+ context="data",
185
+ default=None,
186
+ )
187
+ if explicit is not None:
188
+ if not isinstance(explicit, dict):
189
+ raise AutotouchInputError("linkedin list-build payload must be a JSON object")
190
+ return explicit
191
+
192
+ company_query = str(getattr(args, "company_query", "") or "").strip()
193
+ if not company_query:
194
+ raise AutotouchInputError("linkedin list-build create requires --company-query or --data-file")
195
+
196
+ payload: Dict[str, Any] = {
197
+ "mode": str(getattr(args, "mode", "company-first-people") or "company-first-people").strip(),
198
+ "company_query": company_query,
199
+ "headcount": str(getattr(args, "headcount", "1-10") or "1-10").strip(),
200
+ "num_results": max(1, min(int(getattr(args, "num_results", 100) or 100), 1000)),
201
+ }
202
+ people_query = str(getattr(args, "people_query", "") or "").strip()
203
+ if people_query:
204
+ payload["people_query"] = people_query
205
+ linkedin_api = str(getattr(args, "linkedin_api", "auto") or "auto").strip()
206
+ if linkedin_api and linkedin_api != "auto":
207
+ payload["linkedin_api"] = linkedin_api
208
+ excluded_titles = _split_repeated_values(getattr(args, "excluded_title", None))
209
+ if excluded_titles:
210
+ payload["excluded_titles"] = excluded_titles
211
+ company_filters = _parse_filter_pairs(getattr(args, "company_filter", None), context="company")
212
+ people_filters = _parse_filter_pairs(getattr(args, "people_filter", None), context="people")
213
+ _add_repeated_filter(company_filters, "location", getattr(args, "company_location_id", None) or getattr(args, "location_id", None))
214
+ _add_repeated_filter(people_filters, "location", getattr(args, "people_location_id", None) or getattr(args, "location_id", None))
215
+ _add_repeated_filter(company_filters, "industry", getattr(args, "company_industry_id", None))
216
+ _add_repeated_filter(people_filters, "industry", getattr(args, "people_industry_id", None))
217
+ _add_repeated_filter(people_filters, "role", getattr(args, "role_id", None))
218
+ _add_repeated_filter(people_filters, "function", getattr(args, "function_id", None))
219
+ _add_repeated_filter(people_filters, "seniority", getattr(args, "seniority", None))
220
+ _add_repeated_filter(people_filters, "profile_language", getattr(args, "profile_language", None))
221
+ _add_repeated_filter(company_filters, "technologies", getattr(args, "technology_id", None))
222
+ if getattr(args, "has_job_offers", False):
223
+ company_filters["has_job_offers"] = True
224
+ if company_filters:
225
+ payload["company_filters"] = company_filters
226
+ if people_filters:
227
+ payload["people_filters"] = people_filters
228
+ for arg_name, payload_key, context in (
229
+ ("extra_params_json", "extra_params", "extra-params"),
230
+ ("company_extra_params_json", "company_extra_params", "company-extra-params"),
231
+ ("people_extra_params_json", "people_extra_params", "people-extra-params"),
232
+ ):
233
+ parsed = _load_optional_json_object(getattr(args, arg_name, None), context=context)
234
+ if parsed is not None:
235
+ payload[payload_key] = parsed
236
+ return payload
237
+
238
+
239
+ def _wait_for_linkedin_list_build(
240
+ job_id: str,
241
+ args: argparse.Namespace,
242
+ *,
243
+ runtime: LinkedInCommandRuntime,
244
+ token: Optional[str],
245
+ ) -> Dict[str, Any]:
246
+ started = time.time()
247
+ interval = max(1, int(getattr(args, "poll_interval", 5) or 5))
248
+ timeout = max(0, int(getattr(args, "wait_timeout", 0) or 0))
249
+ terminal = {"completed", "error", "cancelled"}
250
+ latest: Dict[str, Any] = {}
251
+
252
+ while True:
253
+ latest = runtime.request_api(
254
+ "GET",
255
+ f"/api/integrations/linkedin/list-builds/{job_id}",
256
+ base_url=args.base_url,
257
+ token=token,
258
+ use_x_api_key=args.use_x_api_key,
259
+ timeout=args.timeout,
260
+ verbose=args.verbose,
261
+ )
262
+ status = str(latest.get("status") or "").strip().lower() if isinstance(latest, dict) else ""
263
+ if status in terminal:
264
+ return latest
265
+ if timeout and (time.time() - started) >= timeout:
266
+ return latest
267
+ time.sleep(interval)
268
+
269
+
270
+ def cmd_linkedin_list_build_create(args: argparse.Namespace, *, runtime: LinkedInCommandRuntime) -> None:
271
+ token = runtime.resolve_token(args.token, required=True)
272
+ payload = _normalize_linkedin_list_build_payload(args, runtime=runtime)
273
+ data = runtime.request_api(
274
+ "POST",
275
+ "/api/integrations/linkedin/list-builds",
276
+ base_url=args.base_url,
277
+ token=token,
278
+ use_x_api_key=args.use_x_api_key,
279
+ payload=payload,
280
+ timeout=args.timeout,
281
+ verbose=args.verbose,
282
+ )
283
+ if getattr(args, "wait", False) and isinstance(data, dict) and data.get("job_id"):
284
+ data = _wait_for_linkedin_list_build(str(data["job_id"]), args, runtime=runtime, token=token)
285
+ runtime.print_json(data, args.compact)
286
+
287
+
288
+ def cmd_linkedin_list_build_status(args: argparse.Namespace, *, runtime: LinkedInCommandRuntime) -> None:
289
+ token = runtime.resolve_token(args.token, required=True)
290
+ job_id = str(args.job_id).strip()
291
+ data = runtime.request_api(
292
+ "GET",
293
+ f"/api/integrations/linkedin/list-builds/{job_id}",
294
+ base_url=args.base_url,
295
+ token=token,
296
+ use_x_api_key=args.use_x_api_key,
297
+ timeout=args.timeout,
298
+ verbose=args.verbose,
299
+ )
300
+ runtime.print_json(data, args.compact)
301
+
302
+
303
+ def cmd_linkedin_list_build_results(args: argparse.Namespace, *, runtime: LinkedInCommandRuntime) -> None:
304
+ token = runtime.resolve_token(args.token, required=True)
305
+ job_id = str(args.job_id).strip()
306
+ params: Dict[str, Any] = {
307
+ "type": str(getattr(args, "type", "people") or "people"),
308
+ "page": max(1, int(getattr(args, "page", 1) or 1)),
309
+ "page_size": max(1, min(int(getattr(args, "page_size", 50) or 50), 500)),
310
+ }
311
+ data = runtime.request_api(
312
+ "GET",
313
+ f"/api/integrations/linkedin/list-builds/{job_id}/results",
314
+ base_url=args.base_url,
315
+ token=token,
316
+ use_x_api_key=args.use_x_api_key,
317
+ params=params,
318
+ timeout=args.timeout,
319
+ verbose=args.verbose,
320
+ )
321
+ runtime.print_json(data, args.compact)
322
+
323
+
121
324
  def cmd_linkedin_filters(args: argparse.Namespace, *, runtime: LinkedInCommandRuntime) -> None:
122
325
  output = linkedin_filter_catalog(
123
326
  api_mode=getattr(args, "api", None),
@@ -293,6 +496,54 @@ def register_linkedin_subcommands(
293
496
  add_api_common_arguments(filters_parser)
294
497
  filters_parser.set_defaults(func=handlers["filters"])
295
498
 
499
+ list_build_parser = linkedin_sub.add_parser("list-build", help="Create and inspect paced LinkedIn list-build jobs")
500
+ list_build_sub = list_build_parser.add_subparsers(dest="linkedin_list_build_cmd", required=True)
501
+
502
+ list_build_create = list_build_sub.add_parser("create", help="Create a paced background LinkedIn list-build job")
503
+ list_build_create.add_argument("--data-json", help="Explicit list-build payload JSON (overrides individual flags)")
504
+ list_build_create.add_argument("--data-file", help="Path to list-build payload JSON file")
505
+ list_build_create.add_argument("--mode", choices=["company-first-people"], default="company-first-people", help="List build mode")
506
+ list_build_create.add_argument("--linkedin-api", choices=["auto", "classic", "sales_navigator"], default="auto", help="API mode (default: auto; uses connected account mode)")
507
+ list_build_create.add_argument("--company-query", help="Company-search query used to build the seed account set")
508
+ list_build_create.add_argument("--people-query", help="People-search query/title terms")
509
+ list_build_create.add_argument("--headcount", default="1-10", help="Company headcount range, e.g. 1-10 or 11-50")
510
+ list_build_create.add_argument("--num-results", type=int, default=100, help="Target number of people results, 1-1000")
511
+ list_build_create.add_argument("--excluded-title", action="append", help="Title to exclude after results return; repeat or comma-separate")
512
+ list_build_create.add_argument("--location-id", action="append", help="LinkedIn location/region ID applied to company and people search")
513
+ list_build_create.add_argument("--company-location-id", action="append", help="LinkedIn location/region ID applied only to company search")
514
+ list_build_create.add_argument("--people-location-id", action="append", help="LinkedIn location/region ID applied only to people search")
515
+ list_build_create.add_argument("--company-industry-id", action="append", help="LinkedIn industry ID applied to company search")
516
+ list_build_create.add_argument("--people-industry-id", action="append", help="LinkedIn industry ID applied to people search")
517
+ list_build_create.add_argument("--role-id", action="append", help="Resolved LinkedIn job-title ID for people search; repeat or comma-separate")
518
+ list_build_create.add_argument("--function-id", action="append", help="Resolved LinkedIn department/function ID for Sales Nav people search")
519
+ list_build_create.add_argument("--seniority", action="append", help="Sales Nav seniority filter value; repeat or comma-separate")
520
+ list_build_create.add_argument("--profile-language", action="append", help="Profile language code, e.g. en")
521
+ list_build_create.add_argument("--technology-id", action="append", help="Sales Nav technology ID applied to company search")
522
+ list_build_create.add_argument("--has-job-offers", action="store_true", help="Filter companies currently hiring on LinkedIn")
523
+ list_build_create.add_argument("--company-filter", action="append", help="Catalog company filter as FIELD=VALUE; repeat for multiple filters")
524
+ list_build_create.add_argument("--people-filter", action="append", help="Catalog people filter as FIELD=VALUE; repeat for multiple filters")
525
+ list_build_create.add_argument("--extra-params-json", help="JSON object applied to both company and people searches")
526
+ list_build_create.add_argument("--company-extra-params-json", help="JSON object applied only to company search")
527
+ list_build_create.add_argument("--people-extra-params-json", help="JSON object applied only to people search")
528
+ list_build_create.add_argument("--wait", action="store_true", help="Poll until the job reaches completed, error, or cancelled")
529
+ list_build_create.add_argument("--poll-interval", type=int, default=5, help="Polling interval seconds for --wait")
530
+ list_build_create.add_argument("--wait-timeout", type=int, default=0, help="Max seconds to wait (0 = no timeout)")
531
+ add_api_common_arguments(list_build_create)
532
+ list_build_create.set_defaults(func=handlers["list_build_create"])
533
+
534
+ list_build_status = list_build_sub.add_parser("status", help="Get LinkedIn list-build job status")
535
+ list_build_status.add_argument("--job-id", required=True, help="LinkedIn list-build job id")
536
+ add_api_common_arguments(list_build_status)
537
+ list_build_status.set_defaults(func=handlers["list_build_status"])
538
+
539
+ list_build_results = list_build_sub.add_parser("results", help="Get LinkedIn list-build results")
540
+ list_build_results.add_argument("--job-id", required=True, help="LinkedIn list-build job id")
541
+ list_build_results.add_argument("--type", choices=["people", "companies", "all"], default="people", help="Result type")
542
+ list_build_results.add_argument("--page", type=int, default=1, help="Results page")
543
+ list_build_results.add_argument("--page-size", type=int, default=50, help="Results per page, 1-500")
544
+ add_api_common_arguments(list_build_results)
545
+ list_build_results.set_defaults(func=handlers["list_build_results"])
546
+
296
547
  posts_parser = linkedin_sub.add_parser("posts", help="List LinkedIn posts for a user")
297
548
  posts_parser.add_argument("--identifier", required=True, help="LinkedIn profile URL, public ID, or URN")
298
549
  posts_parser.add_argument("--cursor", help="Pagination cursor from previous response")
@@ -1,6 +1,6 @@
1
1
  # Autotouch CLI Reference
2
2
 
3
- Generated from the installed parser for `autotouch-cli` `0.2.72`.
3
+ Generated from the installed parser for `autotouch-cli` `0.2.74`.
4
4
  Manifest schema version: `2`.
5
5
 
6
6
  ## Output Modes
@@ -2243,10 +2243,10 @@ LinkedIn list-building operations
2243
2243
  - Auth: `varies_by_subcommand`
2244
2244
  - Stability: `stable`
2245
2245
  - Destructive: `no`
2246
- - Subcommands: `recipe, status, limits, search, search-params, filters, posts, post, comments, reactions`
2246
+ - Subcommands: `recipe, status, limits, search, search-params, filters, list-build, posts, post, comments, reactions`
2247
2247
  - Example:
2248
2248
  - `autotouch linkedin [-h]
2249
- {recipe,status,limits,search,search-params,filters,posts,post,comments,reactions} ...`
2249
+ {recipe,status,limits,search,search-params,filters,list-build,posts,post,comments,reactions} ...`
2250
2250
 
2251
2251
  #### `autotouch linkedin comments`
2252
2252
 
@@ -2336,6 +2336,166 @@ View LinkedIn send limits and usage
2336
2336
  - `--json-pointer` (kind=string): Extract a JSON pointer from the final result (for example: /id)
2337
2337
  - `--verbose` (kind=boolean; when omitted=False; when present=True): Print request metadata to stderr
2338
2338
 
2339
+ #### `autotouch linkedin list-build`
2340
+
2341
+ Create and inspect paced LinkedIn list-build jobs
2342
+
2343
+ - Auth: `varies_by_subcommand`
2344
+ - Stability: `stable`
2345
+ - Destructive: `no`
2346
+ - Subcommands: `create, status, results`
2347
+ - Example:
2348
+ - `autotouch linkedin list-build [-h] {create,status,results} ...`
2349
+
2350
+ #### `autotouch linkedin list-build create`
2351
+
2352
+ Create a paced background LinkedIn list-build job
2353
+
2354
+ - Auth: `developer_key_or_user_session`
2355
+ - Stability: `stable`
2356
+ - Destructive: `no`
2357
+ - Output modes: `json, ndjson, human`
2358
+ - Example:
2359
+ - `autotouch linkedin list-build create [-h] [--data-json DATA_JSON]
2360
+ [--data-file DATA_FILE]
2361
+ [--mode {company-first-people}]
2362
+ [--linkedin-api {auto,classic,sales_navigator}]
2363
+ [--company-query COMPANY_QUERY]
2364
+ [--people-query PEOPLE_QUERY]
2365
+ [--headcount HEADCOUNT]
2366
+ [--num-results NUM_RESULTS]
2367
+ [--excluded-title EXCLUDED_TITLE]
2368
+ [--location-id LOCATION_ID]
2369
+ [--company-location-id COMPANY_LOCATION_ID]
2370
+ [--people-location-id PEOPLE_LOCATION_ID]
2371
+ [--company-industry-id COMPANY_INDUSTRY_ID]
2372
+ [--people-industry-id PEOPLE_INDUSTRY_ID]
2373
+ [--role-id ROLE_ID]
2374
+ [--function-id FUNCTION_ID]
2375
+ [--seniority SENIORITY]
2376
+ [--profile-language PROFILE_LANGUAGE]
2377
+ [--technology-id TECHNOLOGY_ID]
2378
+ [--has-job-offers]
2379
+ [--company-filter COMPANY_FILTER]
2380
+ [--people-filter PEOPLE_FILTER]
2381
+ [--extra-params-json EXTRA_PARAMS_JSON]
2382
+ [--company-extra-params-json COMPANY_EXTRA_PARAMS_JSON]
2383
+ [--people-extra-params-json PEOPLE_EXTRA_PARAMS_JSON]
2384
+ [--wait]
2385
+ [--poll-interval POLL_INTERVAL]
2386
+ [--wait-timeout WAIT_TIMEOUT]
2387
+ [--base-url BASE_URL]
2388
+ [--token TOKEN] [--use-x-api-key]
2389
+ [--timeout TIMEOUT]
2390
+ [--output {json,ndjson,human}]
2391
+ [--compact] [--select SELECT |
2392
+ --json-pointer JSON_POINTER]
2393
+ [--verbose]`
2394
+ - Options:
2395
+ - `--data-json` (kind=json; input=json): Explicit list-build payload JSON (overrides individual flags)
2396
+ - `--data-file` (kind=file; input=file): Path to list-build payload JSON file
2397
+ - `--mode` (kind=string; choices=company-first-people; default=company-first-people): List build mode
2398
+ - `--linkedin-api` (kind=string; choices=auto,classic,sales_navigator; default=auto): API mode (default: auto; uses connected account mode)
2399
+ - `--company-query` (kind=string): Company-search query used to build the seed account set
2400
+ - `--people-query` (kind=string): People-search query/title terms
2401
+ - `--headcount` (kind=string; default=1-10): Company headcount range, e.g. 1-10 or 11-50
2402
+ - `--num-results` (kind=integer; default=100): Target number of people results, 1-1000
2403
+ - `--excluded-title` (kind=string; repeatable): Title to exclude after results return; repeat or comma-separate
2404
+ - `--location-id` (kind=string; repeatable): LinkedIn location/region ID applied to company and people search
2405
+ - `--company-location-id` (kind=string; repeatable): LinkedIn location/region ID applied only to company search
2406
+ - `--people-location-id` (kind=string; repeatable): LinkedIn location/region ID applied only to people search
2407
+ - `--company-industry-id` (kind=string; repeatable): LinkedIn industry ID applied to company search
2408
+ - `--people-industry-id` (kind=string; repeatable): LinkedIn industry ID applied to people search
2409
+ - `--role-id` (kind=string; repeatable): Resolved LinkedIn job-title ID for people search; repeat or comma-separate
2410
+ - `--function-id` (kind=string; repeatable): Resolved LinkedIn department/function ID for Sales Nav people search
2411
+ - `--seniority` (kind=string; repeatable): Sales Nav seniority filter value; repeat or comma-separate
2412
+ - `--profile-language` (kind=string; repeatable): Profile language code, e.g. en
2413
+ - `--technology-id` (kind=string; repeatable): Sales Nav technology ID applied to company search
2414
+ - `--has-job-offers` (kind=boolean; when omitted=False; when present=True): Filter companies currently hiring on LinkedIn
2415
+ - `--company-filter` (kind=string; repeatable): Catalog company filter as FIELD=VALUE; repeat for multiple filters
2416
+ - `--people-filter` (kind=string; repeatable): Catalog people filter as FIELD=VALUE; repeat for multiple filters
2417
+ - `--extra-params-json` (kind=json; input=json): JSON object applied to both company and people searches
2418
+ - `--company-extra-params-json` (kind=json; input=json): JSON object applied only to company search
2419
+ - `--people-extra-params-json` (kind=json; input=json): JSON object applied only to people search
2420
+ - `--wait` (kind=boolean; when omitted=False; when present=True): Poll until the job reaches completed, error, or cancelled
2421
+ - `--poll-interval` (kind=integer; default=5): Polling interval seconds for --wait
2422
+ - `--wait-timeout` (kind=integer; default=0): Max seconds to wait (0 = no timeout)
2423
+ - `--base-url` (kind=string; default=https://app.autotouch.ai): API base URL (default: https://app.autotouch.ai)
2424
+ - `--token` (kind=string; sensitive): Developer API key / JWT token
2425
+ - `--use-x-api-key` (kind=boolean; when omitted=False; when present=True): Send token via X-API-Key header
2426
+ - `--timeout` (kind=integer; default=30): HTTP timeout in seconds
2427
+ - `--output` (kind=string; choices=json,ndjson,human; default=json): Output mode
2428
+ - `--compact` (kind=boolean; when omitted=False; when present=True): Print compact JSON
2429
+ - `--select` (kind=string): Extract a dotted field path from the final result (for example: id or items.0.id)
2430
+ - `--json-pointer` (kind=string): Extract a JSON pointer from the final result (for example: /id)
2431
+ - `--verbose` (kind=boolean; when omitted=False; when present=True): Print request metadata to stderr
2432
+
2433
+ #### `autotouch linkedin list-build results`
2434
+
2435
+ Get LinkedIn list-build results
2436
+
2437
+ - Auth: `developer_key_or_user_session`
2438
+ - Stability: `stable`
2439
+ - Destructive: `no`
2440
+ - Required flags: `--job-id`
2441
+ - Output modes: `json, ndjson, human`
2442
+ - Example:
2443
+ - `autotouch linkedin list-build results [-h] --job-id JOB_ID
2444
+ [--type {people,companies,all}]
2445
+ [--page PAGE]
2446
+ [--page-size PAGE_SIZE]
2447
+ [--base-url BASE_URL]
2448
+ [--token TOKEN] [--use-x-api-key]
2449
+ [--timeout TIMEOUT]
2450
+ [--output {json,ndjson,human}]
2451
+ [--compact] [--select SELECT |
2452
+ --json-pointer JSON_POINTER]
2453
+ [--verbose]`
2454
+ - Options:
2455
+ - `--job-id` (required; kind=string): LinkedIn list-build job id
2456
+ - `--type` (kind=string; choices=people,companies,all; default=people): Result type
2457
+ - `--page` (kind=integer; default=1): Results page
2458
+ - `--page-size` (kind=integer; default=50): Results per page, 1-500
2459
+ - `--base-url` (kind=string; default=https://app.autotouch.ai): API base URL (default: https://app.autotouch.ai)
2460
+ - `--token` (kind=string; sensitive): Developer API key / JWT token
2461
+ - `--use-x-api-key` (kind=boolean; when omitted=False; when present=True): Send token via X-API-Key header
2462
+ - `--timeout` (kind=integer; default=30): HTTP timeout in seconds
2463
+ - `--output` (kind=string; choices=json,ndjson,human; default=json): Output mode
2464
+ - `--compact` (kind=boolean; when omitted=False; when present=True): Print compact JSON
2465
+ - `--select` (kind=string): Extract a dotted field path from the final result (for example: id or items.0.id)
2466
+ - `--json-pointer` (kind=string): Extract a JSON pointer from the final result (for example: /id)
2467
+ - `--verbose` (kind=boolean; when omitted=False; when present=True): Print request metadata to stderr
2468
+
2469
+ #### `autotouch linkedin list-build status`
2470
+
2471
+ Get LinkedIn list-build job status
2472
+
2473
+ - Auth: `developer_key_or_user_session`
2474
+ - Stability: `stable`
2475
+ - Destructive: `no`
2476
+ - Required flags: `--job-id`
2477
+ - Output modes: `json, ndjson, human`
2478
+ - Example:
2479
+ - `autotouch linkedin list-build status [-h] --job-id JOB_ID
2480
+ [--base-url BASE_URL]
2481
+ [--token TOKEN] [--use-x-api-key]
2482
+ [--timeout TIMEOUT]
2483
+ [--output {json,ndjson,human}]
2484
+ [--compact] [--select SELECT |
2485
+ --json-pointer JSON_POINTER]
2486
+ [--verbose]`
2487
+ - Options:
2488
+ - `--job-id` (required; kind=string): LinkedIn list-build job id
2489
+ - `--base-url` (kind=string; default=https://app.autotouch.ai): API base URL (default: https://app.autotouch.ai)
2490
+ - `--token` (kind=string; sensitive): Developer API key / JWT token
2491
+ - `--use-x-api-key` (kind=boolean; when omitted=False; when present=True): Send token via X-API-Key header
2492
+ - `--timeout` (kind=integer; default=30): HTTP timeout in seconds
2493
+ - `--output` (kind=string; choices=json,ndjson,human; default=json): Output mode
2494
+ - `--compact` (kind=boolean; when omitted=False; when present=True): Print compact JSON
2495
+ - `--select` (kind=string): Extract a dotted field path from the final result (for example: id or items.0.id)
2496
+ - `--json-pointer` (kind=string): Extract a JSON pointer from the final result (for example: /id)
2497
+ - `--verbose` (kind=boolean; when omitted=False; when present=True): Print request metadata to stderr
2498
+
2339
2499
  #### `autotouch linkedin post`
2340
2500
 
2341
2501
  Get full details for a single LinkedIn post
@@ -2436,7 +2596,7 @@ Print LinkedIn payload recipes for search and list-building
2436
2596
  - Output modes: `json, ndjson, human`
2437
2597
  - Example:
2438
2598
  - `autotouch linkedin recipe [-h]
2439
- [--type {all,search,search_url,search_params,posts,comments,reactions}]
2599
+ [--type {all,list_build_company_first_people,search,search_url,search_params,posts,comments,reactions}]
2440
2600
  [--out-file OUT_FILE] [--base-url BASE_URL]
2441
2601
  [--token TOKEN] [--use-x-api-key]
2442
2602
  [--timeout TIMEOUT]
@@ -2444,7 +2604,7 @@ Print LinkedIn payload recipes for search and list-building
2444
2604
  [--select SELECT |
2445
2605
  --json-pointer JSON_POINTER] [--verbose]`
2446
2606
  - Options:
2447
- - `--type` (kind=string; choices=all,search,search_url,search_params,posts,comments,reactions; default=all)
2607
+ - `--type` (kind=string; choices=all,list_build_company_first_people,search,search_url,search_params,posts,comments,reactions; default=all)
2448
2608
  - `--out-file` (kind=file; input=file): Optional path to save the selected payload JSON
2449
2609
  - `--base-url` (kind=string; default=https://app.autotouch.ai): API base URL (default: https://app.autotouch.ai)
2450
2610
  - `--token` (kind=string; sensitive): Developer API key / JWT token