# Job Posting Buying Signal Extractor (`zinin/job-posting-buying-signal-extractor`) Actor

Turn job posting datasets into company hiring signals with matched text and deduplicated job evidence. Identify recurring role demand using transparent rules for sales and staffing research.

- **URL**: https://apify.com/zinin/job-posting-buying-signal-extractor.md
- **Developed by:** [Tim Zinin](https://apify.com/zinin) (community)
- **Categories:** Business, Marketing
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $8.40 / 1,000 hiring signals

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Job Posting Buying Signal Extractor — turn an existing job-postings dataset into company hiring-need signals

Feed it an existing job-postings dataset and get back one company-plus-need hiring signal per match, with the matched text, the deduplicated job count, and a next action — built from explicit keyword rules you can read in full below, never a semantic AI guess.

![Job posting buying signals — hero diagram](https://raw.githubusercontent.com/TimmyZinin/apify-actor-assets/11f25d23572c568596846355492142a15e8cd537/value-add-20260923/job-posting-buying-signal-extractor/readme-hero.webp)

This Actor does not scrape LinkedIn, Himalayas, or any job board. It reads job-posting rows you already have — from an upstream job-scraper Actor's Dataset, from an Integrations payload, or pasted in directly — and turns them into a structured view of which companies are showing recurring, evidence-linked hiring activity in specific functional areas (sales, marketing, data, security, cloud, software, operations). Every signal names the exact keyword that matched, the exact source row it came from, and whether the underlying job identity was actually confirmed (a real `jobId`/URL) or only inferred from posting content. It is a research and prioritization tool for sales and staffing teams working from a job-postings batch they already collected — it is not a purchase-intent score, a budget estimate, a live vacancy checker, or a way to contact anyone.

### What you get

For each distinct company and matched hiring-need category found in your source batch, you get one signal record containing:

- **`companyName`** — the company as reported by the source (a string field, or `company.name`/`company.companyName` on an object), and **`need`** — which of seven fixed categories matched (`sales`, `marketing`, `data`, `security`, `cloud`, `software`, `operations`).
- **`jobCount`**, **`confirmedJobCount`**, and **`inferredJobCount`** — how many distinct job postings support this signal in total, how many of those had a real, verifiable identity (`jobId` or a canonicalized job URL), and how many were only distinguishable by their title/description/date content because the source gave no `jobId`/URL at all. These three numbers are never conflated: a company with five postings but no job IDs shows `jobCount: 5, confirmedJobCount: 0, inferredJobCount: 5`, and the recommended `action` reacts to that distinction (see **Decision routing**).
- **`matchedJobs`** — up to 25 of the actual distinct postings behind the count, each with its own `jobId`/`jobUrl` (when confirmed), `title`, `postedDate`, and `categories` — so you can see exactly which postings drove the signal, not just a number.
- **`evidence`** — the literal matched keyword, which need-category it belongs to, whether it matched in the `title` or the `description`, and the exact source row index it came from — up to 12 evidence entries per signal, with the truncation itself disclosed when there are more.
- **`action`** — one of three plain labels (`prioritize_outreach`, `monitor_recurring_demand`, `log_single_signal`) based strictly on `confirmedJobCount`, and **`confidence`** — `title_match` when at least one matched job had the keyword in its title, `description_match_only` otherwise.
- **Honest diagnostics for everything that isn't a signal** — a row with neither a title nor a description, a row with no identifiable company, a row whose text matched none of the seven need categories, or a row the source itself reported as failed — are free business diagnostics. The initial list also includes source-read notices and writes at most 200 entries; later result-size/cap notices can raise total free rows above 200.

What this Actor explicitly is **not**: it does not claim proven purchase intent, an open budget, confirmed headcount growth, or that a posting is a currently-open vacancy (a `postedDate` only tells you when the source observed the posting, never that it's still live today). It does not send outreach messages, does not look up or expose personal contact details, and does not infer meaning semantically — every match is a literal, documented keyword hit against a fixed, disclosed dictionary (see **Field dictionary**), not an AI judgment call.

### Who uses it

Sales researchers, recruiters and category analysts use these records to prioritize review of companies with observed hiring needs. The output supplies literal source evidence and confirmed-versus-inferred identity counts. It does not verify purchasing intent, budget, urgency or a current vacancy beyond the supplied observation date. Use it with your existing account research process and refresh the upstream dataset when freshness matters.

### How to run

1. **Console (fastest for a one-off run).** Open the Actor, go to Input, and either paste your job rows into **Source records (inline)** or fill in **Source Dataset** with the Dataset ID from your job-postings scrape. Leave everything else at its default and hit **Start**.
2. **From an existing job-postings Dataset.** If you already have a Dataset ID from a job-scraper run, put it in `datasetId`. The Dataset is read with your own run's permissions — no separate authorization step, and this Actor never elevates access beyond what your token already has.
3. **Chained after an upstream job-scraper Actor via Integrations.** Add this Actor as an "Actor/task run" integration on your upstream job-scraper Actor. Apify's Integrations UI auto-populates the payload with `{{resource.defaultDatasetId}}`; map that value into this Actor's `datasetId` field explicitly (see **Integration recipes**) to request `READ` access under `LIMITED_PERMISSIONS`, conditional on resource-picker or integration authorization — a payload reference alone does not grant access to a private Dataset.
4. **Via the API.** Call `POST /v2/acts/Uzd4yKIybbufQ9oV4/runs` (or `run-sync-get-dataset-items` for a synchronous single call) with a JSON body containing `datasetId` (or `items`) and, if you want a hard spending ceiling, the run option `maxTotalChargeUsd`.
5. **Read the results.** One row per matched company+need pair lands in the run's default Dataset. A matching run-level `OUTPUT`/`SUMMARY` record in the Key-value store tells you how many signals were delivered, how many rows were free diagnostics, and whether a row or spending cap ended the run early.

Every run is independent processing — see **Operating guide** for exactly what that means for re-running against the same batch.

### Pricing

Pay-per-event, one event type: **`result-found`** — one delivered hiring signal (one company+need pair). There is **no start fee**, and every free diagnostic (an unmatched row, a missing company, a budget stop, an empty batch) requests no charge event at all.

| Tier | Price per signal | Discount |
|---|---|---|
| Free (default) | $0.012 | — |
| Bronze | $0.0108 | 10% |
| Silver | $0.0096 | 20% |
| Gold | $0.0084 | 30% |
| Platinum | $0.0084 | 30% |
| Diamond | $0.0084 | 30% |

These are Apify's platform-wide account pricing tiers — not a volume schedule this Actor invents itself — assigned automatically based on your account's own usage; you don't select one. One "signal" is one company+need assessment, which can represent multiple deduplicated job postings behind it (see `jobCount` in **What you get**) — it is never billed per individual input job row. A company showing hiring signals in three different need categories in the same run produces (and is billed for) three separate signal rows, one per category, because each is a distinct, independently-evidenced finding. Upstream job-scraping costs (running the source Actor that produced your batch) are entirely separate from this Actor's own price.

Set the platform's own **Max total charge (USD)** run option to cap total spend for a single run. See **Evidence and boundaries** for a documented case of a `maxTotalChargeUsd` value that does **not** behave as its name suggests when set via a raw API call.

### Input contract

| Field | Type | Default | Notes |
|---|---|---|---|
| `items` | array (JSON editor), max 1000 entries | prefilled real example | Inline source records. Ignored if `datasetId`, `runId`, or a resolvable `payload.resource` is also given. |
| `datasetId` | string (Dataset picker, READ) | — | Dataset ID from a job-postings scrape. Read with your own run's permissions. Overrides inline `items`. |
| `runId` | string, max 64 chars | — | An Actor run ID to read instead of a Dataset ID directly; its default Dataset is resolved automatically. |
| `payload` | object (JSON editor) | — | Optional `ACTOR.RUN.SUCCEEDED`-shaped payload carrying `resource.defaultDatasetId`/`resource.id` from an upstream run. The resource picker on `datasetId` is the recommended way to grant private-Dataset access; a bare payload reference does not itself grant access. |
| `maxInputRows` | integer | 100 | Hard cap on source records examined before grouping (1–1000). Bounded to 4 MiB total and 64 KiB per row regardless of this value. |
| `maxResults` | integer | 10 | Maximum number of useful hiring-signal results this run can deliver (1–1000), independent of the platform's Max total charge run option. |

**Source precedence, exactly:** an explicit `datasetId` or `payload.resource.defaultDatasetId` (they must agree if both are present) beats a `runId` or `payload.resource.id`, which beats inline `items`. A dataset/run source is never merged with inline rows. A malformed or conflicting reference is rejected as invalid input, never silently downgraded to the inline example.

**Accepted row fields** (any subset present is used; nothing here is strictly required except enough to identify a company and some text — see **Evidence and boundaries** for what happens with less):

| Field | Accepted as | Role |
|---|---|---|
| `title` | string; display capped at 200 characters, including the final ellipsis | Matched against the need-keyword dictionary; also read for `confidence: title_match`. |
| `description` | string | Matched against the dictionary when `title` alone doesn't cover a need. |
| `company` (string), `companyName` (string), `company.name` / `company.companyName` (object) | string | Required for a row to become a signal — no fuzzy/first-result company joining is ever performed. |
| `jobId`, `guid`, `id` | string (≤200 chars, no control characters) or a non-negative safe integer | Confirmed job identity, in that priority order. |
| `jobURL`, `applicationLink`, `url` | string, http(s) only, ≤2048 chars | Confirmed job identity via a canonicalized URL (fragment dropped, only recognized tracking parameters like `utm_*`/`gclid`/`fbclid` stripped — a functional query parameter like `?id=123` is preserved, so it never falsely equates two different postings). |
| `postedDate`, `publishedAt` | string; display capped at 64 characters, including the final ellipsis | The posting's own reported date. A separate crawl/`fetchedAt` timestamp is never read as if it were the posting date. |
| `categories` | array of strings | Up to 10 entries, each up to 120 characters; excess is truncated and disclosed. |
| `found`, `error`, `errors`, `failed`, `status` | various | `found:false`, `failed:true`, or a failed/error/timed-out/aborted status always yields a free diagnostic, even when contradictory `found:true, partial:true` flags coexist. A non-empty `error`/`errors` warning may survive only with explicit `found:true, partial:true` and no hard failure; the result preserves source incompleteness. |

Title/date shortening alone does not set `partial`. Matching uses the original title/description. Inferred identity hashes the title, description and shortened date; dates differing only beyond that bound can merge. Dates are not validated as calendar values.

**Hard read bounds, always enforced regardless of `maxInputRows`:** at most 1000 source rows, at most 4 MiB of total source JSON per run, at most 64 KiB per individual row (an oversized row is dropped and disclosed). This Actor reads only the fixed `https://api.apify.com` origin with your run's own token — it never fetches an arbitrary URL and never starts an upstream Actor.

### Output examples

These four outputs reproduce actual September 23 canaries from source-observation build `ROYBvPErVmNhfrCbI`, with values, IDs and timestamps unchanged. Example 1 reads the real Dataset; example 2 projects its identity fields; examples 3–4 are budget and empty-source controls. Underlying job observations remain September 13. Run IDs: `BHQS5Fey5nGTnrrwB`, `Ujkam31i4TSGsn80g`, `lMafcR2hpNxcSLIUP`, `xm3B8j1gVqPf7a0Bw`.

#### 1. First useful signal — a full, confirmed dataset row

This is not a fresh LinkedIn scrape. The five underlying job postings were observed by the upstream job-scraper on **2026-09-13** (`observedAt` inside each source row) and processed by this Actor on **2026-09-23** — a 10-day-old saved batch, not today's hiring status.

Actor input:

```json
{
  "datasetId": "ErVyHjUdtLa1Dftkn",
  "maxResults": 10,
  "maxInputRows": 100
}
```

First Dataset output row (of four delivered from this run):

```json
{
  "entityId": "company:amazon web services (aws)|need:cloud",
  "found": true,
  "status": "observed_hiring_signal",
  "action": "monitor_recurring_demand",
  "confidence": "title_match",
  "sourceRowCount": 2,
  "companyName": "Amazon Web Services (AWS)",
  "need": "cloud",
  "jobCount": 2,
  "confirmedJobCount": 2,
  "inferredJobCount": 0,
  "matchedJobs": [
    {
      "jobId": "4455931376",
      "jobUrl": "https://www.linkedin.com/jobs/view/software-development-engineer-aws-iam-distributed-database-system-at-amazon-web-services-aws-4455931376",
      "title": "Software Development Engineer, AWS IAM Distributed Database System",
      "postedDate": "2026-09-09",
      "categories": []
    },
    {
      "jobId": "4455914852",
      "jobUrl": "https://www.linkedin.com/jobs/view/software-dev-engineer-ii-aws-sts-at-amazon-web-services-aws-4455914852",
      "title": "Software Dev Engineer II, AWS STS",
      "postedDate": "2026-09-09",
      "categories": []
    }
  ],
  "observedAt": "2026-09-13T15:50:54.556Z",
  "sourceObservationWindow": {
    "earliest": "2026-09-13T15:50:54.556Z",
    "latest": "2026-09-13T15:50:54.556Z",
    "validCount": 2,
    "totalRowCount": 2
  },
  "evidence": [
    {
      "field": "title",
      "value": "matched \"aws\" in \"Software Development Engineer, AWS IAM Distributed Database System\"",
      "rule": "keyword_dictionary:cloud",
      "sourceRowIndex": 1
    },
    {
      "field": "title",
      "value": "matched \"aws\" in \"Software Dev Engineer II, AWS STS\"",
      "rule": "keyword_dictionary:cloud",
      "sourceRowIndex": 3
    }
  ],
  "businessPartial": false,
  "sourceRowIndexes": [
    1,
    3
  ],
  "partial": false,
  "sourceCoverage": {
    "complete": true,
    "reason": null,
    "droppedOversized": 0
  },
  "product": "job-posting-buying-signal-extractor",
  "schemaVersion": "1.0",
  "sourceDatasetId": "ErVyHjUdtLa1Dftkn",
  "sourceRunId": null,
  "suppliedSourceRunId": null,
  "sourceRunIdVerified": null,
  "processedAt": "2026-09-23T05:10:39.182Z"
}
```

This run's Dataset `ErVyHjUdtLa1Dftkn` (the public example named in the Input contract) is a curated real copy of an upstream `zinin/linkedin-public-jobs-scraper`-shaped run (`_exampleProvenance.sourceActorId: JQgY5E6jpd3bvtCmU`, `sourceRunId: JrRgbvNEFop2XoObT`, `sourceDatasetId: sagPWb8mF8Q9TyChd`). Both AWS postings had real `jobId`/`jobUrl` values, so `confirmedJobCount` equals `jobCount`, both matched "aws" in their title (hence `confidence: title_match`), and two confirmed jobs at one company produce `action: monitor_recurring_demand` — not yet the three-job `prioritize_outreach` threshold. This run delivered 4 signals total across 3 companies from the 5-row batch; the remaining 3 rows are in the accepted Dataset alongside this one.

#### 2. Same batch with `jobId`/`jobURL` removed — a controlled projection, not a new scrape

This is the identical 5-row 2026-09-13 batch above, with `jobId` and `jobURL` deliberately stripped from every row before submission — a controlled demonstration of confirmed-vs-inferred identity handling, not a fresh measurement of anything.

Actor input (first record of five submitted inline; company/title/postedDate otherwise unchanged from example 1):

```json
{
  "items": [
    {
      "schemaVersion": "1.0",
      "recordType": "linkedin_public_job",
      "title": "Senior Software Engineer – Go (Golang)",
      "company": "General Motors",
      "location": "Warren, MI",
      "postedTimeText": "1 day ago",
      "postedDate": "2026-09-12",
      "keywords": "software engineer",
      "searchLocation": "United States",
      "pageStart": 0,
      "sourceURL": "https://www.linkedin.com/jobs-guest/jobs/api/seeMoreJobPostings/search?keywords=software+engineer&location=United+States&start=0",
      "observedAt": "2026-09-13T15:50:54.556Z",
      "source": { "htmlSha256": "7394931a2e2a538b365c1d5f422aa4e6e38b2e6d2a5c12e6204e7db8ae880606" },
      "_exampleProvenance": {
        "sourceActorId": "JQgY5E6jpd3bvtCmU",
        "sourceRunId": "JrRgbvNEFop2XoObT",
        "sourceDatasetId": "sagPWb8mF8Q9TyChd",
        "curatedPublicSnapshot": true,
        "redaction": "Allowlisted public business/product fields only; review excerpts and social captions truncated; no reviewer identities."
      }
    }
  ]
}
```

Resulting Dataset output row for the AWS/cloud pair (`partial: true`):

```json
{
  "entityId": "company:amazon web services (aws)|need:cloud",
  "found": true,
  "status": "observed_hiring_signal",
  "action": "log_single_signal",
  "confidence": "title_match",
  "sourceRowCount": 2,
  "companyName": "Amazon Web Services (AWS)",
  "need": "cloud",
  "jobCount": 2,
  "confirmedJobCount": 0,
  "inferredJobCount": 2,
  "matchedJobs": [
    {
      "jobId": null,
      "jobUrl": null,
      "title": "Software Development Engineer, AWS IAM Distributed Database System",
      "postedDate": "2026-09-09",
      "categories": []
    },
    {
      "jobId": null,
      "jobUrl": null,
      "title": "Software Dev Engineer II, AWS STS",
      "postedDate": "2026-09-09",
      "categories": []
    }
  ],
  "observedAt": "2026-09-13T15:50:54.556Z",
  "sourceObservationWindow": {
    "earliest": "2026-09-13T15:50:54.556Z",
    "latest": "2026-09-13T15:50:54.556Z",
    "validCount": 2,
    "totalRowCount": 2
  },
  "evidence": [
    {
      "field": "title",
      "value": "matched \"aws\" in \"Software Development Engineer, AWS IAM Distributed Database System\"",
      "rule": "keyword_dictionary:cloud",
      "sourceRowIndex": 1
    },
    {
      "field": "title",
      "value": "matched \"aws\" in \"Software Dev Engineer II, AWS STS\"",
      "rule": "keyword_dictionary:cloud",
      "sourceRowIndex": 3
    }
  ],
  "businessPartial": true,
  "sourceRowIndexes": [
    1,
    3
  ],
  "partial": true,
  "sourceCoverage": {
    "complete": true,
    "reason": null,
    "droppedOversized": 0
  },
  "product": "job-posting-buying-signal-extractor",
  "schemaVersion": "1.0",
  "sourceDatasetId": null,
  "sourceRunId": null,
  "suppliedSourceRunId": null,
  "sourceRunIdVerified": null,
  "processedAt": "2026-09-23T05:11:04.289Z"
}
```

Same two postings, same `jobCount: 2` — but with no `jobId`/URL in the source, these two are only distinguishable by title/description/company/date content (the module's `content:`-hash fallback identity), so `confirmedJobCount` drops to 0 and `inferredJobCount` rises to 2. Because `action` is driven by `confirmedJobCount`, not `jobCount`, this pair now reads `log_single_signal` instead of example 1's `monitor_recurring_demand` — the same underlying postings, correctly downgraded because the source no longer proves they're actually two distinct, trackable jobs rather than duplicate or malformed records that happen to differ in text.

#### 3. Below-price run — free `budget_stopped` diagnostic, no partial charge

```json
[
  {
    "product": "job-posting-buying-signal-extractor",
    "schemaVersion": "1.0",
    "status": "budget_stopped",
    "reason": "Run charge limit cannot cover any result; no source was read.",
    "found": false,
    "processedAt": "2026-09-23T05:11:16.569Z"
  }
]
```

This run was started with the platform run option `maxTotalChargeUsd: 0.005` — below every pricing tier's per-signal price (even Diamond's $0.0084). The Actor never reads the source batch, delivers zero paid signals, and writes this one free diagnostic. See **Evidence and boundaries** for what the literal value `0` does instead, which is different from this.

#### 4. Empty batch — free `no_results` diagnostic

Actor input:

```json
{ "items": [] }
```

Dataset output:

```json
[
  {
    "product": "job-posting-buying-signal-extractor",
    "schemaVersion": "1.0",
    "status": "no_results",
    "found": false,
    "reason": "no_usable_rows_in_batch",
    "sourceCoverage": {
      "complete": true,
      "reason": null,
      "droppedOversized": 0
    },
    "processedAt": "2026-09-23T05:11:26.037Z"
  }
]
```

An empty or entirely-unusable batch is a free diagnostic, never a silent zero-row success and never a charge.

### Field dictionary

| Field | Type | Meaning |
|---|---|---|
| `entityId` | string | `"company:<lowercased company>|need:<need>"` — stable key for this company+need signal. |
| `found` | boolean | `true` on every billed signal; `false` on every free diagnostic. |
| `status` | string | `"observed_hiring_signal"` on a signal; a diagnostic reason (`invalid_input`, `source_unavailable`, `invalid_row`, `source_reported_failure`, `missing_title_and_description`, `missing_company`, `no_keyword_match`, `budget_stopped`, `no_results`, `max_results_reached`, `result_dropped_oversized`, `source_rows_dropped`, `partial_source`) on a free row. |
| `companyName` | string | The company exactly as extracted from the source (original casing preserved for display; matching/grouping is case-insensitive). |
| `need` | string | One of `sales`, `marketing`, `data`, `security`, `cloud`, `software`, `operations` — see the full keyword dictionary below. |
| `jobCount` | number | Distinct job identities (confirmed + inferred) behind this signal, uncapped — this is the true count even when `matchedJobs` is display-truncated. |
| `confirmedJobCount` | number | Of `jobCount`, how many had a real `jobId` or canonicalized job URL. |
| `inferredJobCount` | number | `jobCount − confirmedJobCount` — postings distinguished only by title/description/company/date content, because the source gave no identity field at all. |
| `matchedJobs` | array | Up to 25 of the actual distinct postings, each `{ jobId, jobUrl, title, postedDate, categories }` (`jobId`/`jobUrl` are `null` for an inferred-only posting). |
| `evidence` | array | Up to 12 entries, each `{ field: "title"\|"description", value, rule: "keyword_dictionary:<need>", sourceRowIndex }`, plus a reserved slot each for a `job_list_truncated` or `identity_bridge_conflict` note when those apply. |
| `action` | string | `prioritize_outreach` (`confirmedJobCount` ≥ 3), `monitor_recurring_demand` (`confirmedJobCount` = 2), or `log_single_signal` (0–1) — driven by *confirmed*, not total, job count. |
| `confidence` | string | `title_match` if any displayed matched job hit the keyword in its title; `description_match_only` otherwise. |
| `partial` / `businessPartial` | boolean | `businessPartial` is this module's own signal (a truncated job list, an identity conflict, a truncated category list, a source row marked `partial: true`, `confirmedJobCount < jobCount`, or more than 50 contributing source rows). `partial` also folds in run-level source-read incompleteness — check `partial` if you only check one flag. |
| `sourceRowCount` / `sourceRowIndexes` | number / array | True count and (capped at 50) list of original source rows contributing to this signal. |
| `sourceCoverage` | object | Run-level: `{ complete, reason, droppedOversized }` — whether the source read itself hit a cap. |
| `sourceDatasetId`, `sourceRunId`, `suppliedSourceRunId`, `sourceRunIdVerified` | string/null, boolean/null | Where the batch came from; `sourceRunId` is populated only when independently verified against the Dataset. |
| `observedAt` | string/null | Latest valid source observation across the signal’s complete contributing identity clusters. Uses only source `observedAt`, never `postedDate` or processing time. |
| `sourceObservationWindow` | object | `{earliest, latest, validCount, totalRowCount}` over contributing accepted source occurrences before display caps. Missing/invalid timestamps increase only `totalRowCount`; endpoints are null without valid observations. Keyword-free identity-bridging rows contribute to their cluster window. |
| `processedAt` | string (ISO 8601) | When this Actor processed the row. Never a claim about when the underlying posting was made. |
| `reason` / `error` | string | Present on free diagnostic rows only. |

**The full need-keyword dictionary** (case-insensitive, word-boundary matched — `"aws"` matches "AWS-based platform" but not "awsome" or "claws"):

| Need | Keywords |
|---|---|
| `sales` | sales, account executive, business development, sales representative, sdr, bdr |
| `marketing` | marketing, seo, content marketing, brand manager, digital marketing, growth marketer |
| `data` | data engineer, data scientist, data analyst, machine learning, data engineering, analytics engineer |
| `security` | security engineer, cybersecurity, infosec, application security, security analyst, penetration tester |
| `cloud` | cloud engineer, cloud architect, aws, azure, kubernetes, devops engineer |
| `software` | software engineer, software developer, backend engineer, frontend engineer, full stack, programmer |
| `operations` | operations manager, supply chain, logistics, operations analyst, process improvement, ops manager |

A posting can match more than one need (e.g. "DevOps Engineer" matches `cloud`; "Senior Software Engineer – Go" matches `software`) and will appear as a separate signal row per matched need. This dictionary is fixed and disclosed in full above — it is not adjustable per run and not an AI classifier, so the same posting text always produces the same match, every time.

### Evidence and boundaries

**Company identity is never fuzzy-joined.** A row becomes part of a company's signal only via an explicit `company`/`companyName` string or `company.name`/`company.companyName` object field. There is no first-result matching, no "closest name" heuristic, and no cross-company merging by similar spelling — "Amazon Web Services (AWS)" and "Amazon" are two different `companyName` values and are never silently unified.

**Job identity resolution happens company-wide, before need-grouping, and includes keyword-free rows.** Every accepted row for a company — including a row whose own title/description matched *no* configured need keyword — participates in identity resolution: if that keyword-free row shares a `jobId` or job URL with a row that *did* match a need, it correctly "bridges" into that job's identity (e.g. confirming the same posting was seen twice, once with enough text to match and once without). A keyword-free row never creates a signal on its own, but it can still legitimately affect `jobCount`/`confirmedJobCount` for a need another row already matched. This was independently verified against a 999-row batch where 998 keyword-free bridge rows correctly collapsed into a single confirmed job under one real signal, while a separate 1,000-genuinely-distinct-ID batch correctly produced 1,000 counted jobs (with `matchedJobs` display capped at 25, `jobCount` itself never capped).

**Identity conflicts are resolved conservatively, never by fabricating separate demand.** If a later row's shared identity keys bridge two previously-separate job clusters for the same company (a genuine ambiguity in the source data), they are merged into one job — favoring undercounting over inventing two postings that might actually be duplicates — and the signal is marked `partial: true` with an `identity_bridge_conflict` evidence entry.

**Confirmed vs. inferred identity is not a detail — it drives `action`.** An `inferredJobCount` posting was only ever distinguished from another by matching company + title + description + posted date (hashed together) because the source gave no `jobId`/URL. This is a real, disclosed signal that the underlying source data is thinner than ideal — it is never silently treated the same as a confirmed, independently-trackable job. Compare examples 1 and 2 above: identical postings, different `action`, because identity confirmation genuinely changed.

**Bounded, disclosed caps, applied only to display, never to the underlying count:** `matchedJobs` is capped at 25 postings per signal (`jobCount`/`confirmedJobCount`/`inferredJobCount` remain the true totals); `evidence` is capped at 12 entries per signal, with truncation/conflict notes given their own reserved slot so they can never be crowded out; `sourceRowIndexes` is capped at 50 per signal (`sourceRowCount` is the true total); `categories` is capped at 10 entries of up to 120 characters each, with truncation disclosed. The initial business-diagnostic plus source-notice list writes at most 200 entries. `businessSummary.diagnosticsCount` counts business diagnostics only; `diagnosticsTruncated` flags the combined-list cap. Later result-size/cap notices add free rows.

**Keyword matching is literal and deterministic, never semantic.** A match requires the exact configured phrase (case-insensitive, word-boundary bounded) to appear in `title` or `description`. This Actor does not use an LLM, does not infer synonyms not in the dictionary above, and does not weigh context — "we need more sales" and "Sales Representative — Enterprise" both match `sales` identically, by the literal word. This is a deliberate trade-off for full auditability: every match is traceable to one documented rule, never an opaque model decision.

**No proof of purchase intent, budget, live vacancy, or outreach permission.** A hiring-need signal means the source data contained a job posting whose text matched a configured keyword — nothing more. It is not evidence the company has an approved budget, is actually growing headcount, or that the posting is still open today (`postedDate` is the source's own reported date, and a separate `fetchedAt`-style crawl timestamp is deliberately never substituted for it). This Actor never sends a message to anyone and never looks up or exposes a personal contact — it only classifies job-posting text you already have.

**Budget behavior — read this before relying on a specific `maxTotalChargeUsd` value.** The platform's SDK-level budget check is real and independently verified: a positive `maxTotalChargeUsd` below the price of one signal correctly delivers zero paid signals and one free `budget_stopped` diagnostic (example 3 above). However, a raw API request setting `maxTotalChargeUsd` to exactly `0` has been independently observed to be **normalized by the platform to an account-level default remaining allowance** rather than passed through as a literal zero-spend instruction, after which a run could bill normally under that restored default. **Do not rely on `maxTotalChargeUsd: 0` as a guaranteed no-spend switch when calling the API directly — always inspect the run's actual, effective `options.maxTotalChargeUsd` after it starts**, and prefer a small positive value below one signal's price if your intent is to exercise the free-limit-stop path. This is a platform-level API behavior, not specific to this Actor.

**Delivery is not transactional.** Dataset storage precedes event charging. A lost acknowledgment can leave an unconfirmed row; the run stops without retry and can fail after some deliveries succeeded. Inspect the Dataset, platform event counts and available summary before retrying. A new run can bill again. If summary persistence fails, a complete `OUTPUT`/`SUMMARY` pair may be unavailable.

#### Reading the run summary

`OUTPUT` and `SUMMARY` contain the same run record when both writes succeed. These counters describe acknowledged processing, not every storage side effect that might have happened during a failed request:

| Field | Meaning |
|---|---|
| `schemaVersion`, `product`, `outcome`, `processedAt` | Contract version, product identifier, outcome and processing time (not a posting date). |
| `requested` | Number of source rows encountered by the source reader. It is zero if the budget precheck stopped before reading. |
| `usefulResults` | Useful result rows remaining after oversized-result filtering, before delivery caps. |
| `delivered` | Useful Dataset writes for which the complete delivery and charge check succeeded. |
| `paid` | Confirmed named `result-found` events in this platform run. |
| `free` | Acknowledged diagnostic Dataset writes without a named result event. |
| `failed` | Oversized useful result rows dropped before delivery; this is not the count of fatal exceptions. |
| `fatalFailure`, `errorCode` | Whether the run failed and its fixed diagnostic code. Input-policy diagnostics can succeed with a non-null `errorCode`, so read both fields. |
| `deliveryUncertain` | A Dataset write or event-charge acknowledgment could not be confirmed. Actual Dataset rows may exceed confirmed counters. |
| `replaySafety` | Text reminder that a new run can bill again. |
| `replayBlocked` | The same run/storage already had a processing claim or named result events, so automatic replay was refused. |
| `budgetStopped`, `resultsCapped` | Delivery stopped because of the effective charge allowance or `maxResults`. |
| `sourcePartial`, `sourcePartialReason`, `sourceDroppedOversized` | Source-read coverage limits and rows discarded for size. |
| `businessPartialResults` | Useful transform results carrying incomplete business evidence, counted before delivery filtering. |
| `oversizedDiagnosticsDropped`, `diagnosticsTruncated` | Diagnostics omitted because of size or the 200-entry combined business/source-notice limit; later result-size/cap notices are outside it. |
| `partialOverall` | At least one source, output, diagnostic or business-coverage limit was recorded. It does not replace `fatalFailure`. |
| `budgetMode`, `maxTotalChargeUsd` | Verified finite/unlimited limit mode; the limit is null when no finite verified limit is available. |
| `businessSummary` | Module counts can exceed delivered counts. `sourceObservationWindow` spans all accepted source rows using `earliest`, `latest` and `validCount` (no summary `totalRowCount`). Legacy `observedAt` remains null; use the explicit source window. |

### Decision routing

- **`action: prioritize_outreach`** — at least 3 *confirmed* distinct postings for this company+need. The strongest available signal in this dataset: real, independently-identified job records, not inferred duplicates.
- **`action: monitor_recurring_demand`** — exactly 2 confirmed postings. Worth tracking across your next batch to see if it becomes 3, but not yet the strongest tier.
- **`action: log_single_signal`** — 0 or 1 confirmed postings, regardless of `jobCount`. This includes both a genuinely single posting and a case (like example 2 above) where multiple postings exist but none could be confirmed as distinct — check `inferredJobCount` before treating this as "weak" outright; it may just mean your source data lacks job IDs/URLs for otherwise-real postings.
- **`confidence: description_match_only`** — the keyword only appeared in body text, not the job title. Still a real, literal match, but worth a quick manual glance at the matched evidence before treating it with the same weight as a title match.
- **`partial: true` with `identity_bridge_conflict` in evidence** — the source data itself was ambiguous about whether two postings were the same job. The count was resolved conservatively (merged, undercounted), but the underlying ambiguity is worth understanding if this account matters.
- **Free diagnostic rows (`found: false`)** — never a signal about the company. `missing_title_and_description`/`missing_company` mean the row couldn't be interpreted at all; `no_keyword_match` means real content existed but matched none of the seven configured needs (it may still have bridged into another row's identity — see **Evidence and boundaries**); `budget_stopped`/`max_results_reached` mean a run-level cap was hit — re-run with a higher cap to see the rest of the batch.

### Commercial playbooks

Filter by need and confirmed job count, then verify matched jobs, source dates and partial flags before using a signal in account research. Hiring activity is an observation, not proof of purchasing authority or budget.

Compare repeated batches using the same company+need keys and preserve every capture window. Replaying a saved batch supplies no fresh observation and can charge again. A high inferred-job share suggests missing upstream IDs or URLs; improve that capture before interpreting apparent growth. This Actor does not contact prospects.

### Integration recipes

![Job posting buying signals — workflow diagram](https://raw.githubusercontent.com/TimmyZinin/apify-actor-assets/11f25d23572c568596846355492142a15e8cd537/value-add-20260923/job-posting-buying-signal-extractor/readme-workflow.webp)

This Actor's ID is **`Uzd4yKIybbufQ9oV4`**. A natural upstream source is [LinkedIn Jobs Scraper](https://apify.com/zinin/linkedin-public-jobs-scraper) (Actor ID `JQgY5E6jpd3bvtCmU`); any Actor or manual process producing the row shape in **Input contract** works identically. The recipes below describe exactly how to configure each mechanism — they are not a claim that any specific trigger is currently installed on your account. A saved public example is available in the Tasks tab.

**1. Console-native chaining (no code).** On your job-scraper Actor's run page, open the **Integrations** tab, add an "Actor/task run" action targeting this Actor, and let Apify's Integrations UI populate the payload with `{{resource.defaultDatasetId}}` from the finished upstream run. Map that value explicitly into this Actor's `datasetId` field — not the generic `payload` pass-through alone — to request `READ` access under `LIMITED_PERMISSIONS`, conditional on resource-picker or integration authorization. This is the pattern documented at `docs.apify.com/integrations/actors`.

**2. Direct webhook (`POST /v2/webhooks`), full recipe.** Configure a webhook on your upstream job-scraper Actor for the `ACTOR.RUN.SUCCEEDED` event, scoped to that specific Actor via its `condition.actorId`, targeting this Actor's run-creation endpoint:

```json
{
  "isApifyIntegration": true,
  "shouldInterpolateStrings": true,
  "eventTypes": ["ACTOR.RUN.SUCCEEDED"],
  "condition": { "actorId": "JQgY5E6jpd3bvtCmU" },
  "requestUrl": "https://api.apify.com/v2/acts/Uzd4yKIybbufQ9oV4/runs?maxTotalChargeUsd=0.50",
  "doNotRetry": true,
  "headersTemplate": "{\"Authorization\": \"Bearer <APIFY_TOKEN>\"}",
  "payloadTemplate": "{\"datasetId\": \"{{resource.defaultDatasetId}}\", \"payload\": {\"resource\": {\"defaultDatasetId\": \"{{resource.defaultDatasetId}}\", \"id\": \"{{resource.id}}\"}}, \"maxResults\": 25}"
}
```

Submit this to `POST https://api.apify.com/v2/webhooks` with your own `Authorization: Bearer <APIFY_TOKEN>` header — the `<APIFY_TOKEN>` placeholder in `headersTemplate` above is filled in by whichever secrets-management step provisions the webhook, never hardcoded into the template itself or placed in a URL query string. `doNotRetry: true` avoids a duplicate-charge risk from an automatic webhook retry. Note `datasetId` is set explicitly alongside `payload.resource.defaultDatasetId`, pointing at the same Dataset — an authorized resource-picker selection or integration can request scoped `READ` access. The raw `datasetId` string and `payload.resource` alone do not grant access to a private Dataset; the run still needs platform-authorized permission. A positive `maxTotalChargeUsd` on the request URL caps this chained run's spend; per **Evidence and boundaries**, avoid the literal value `0` here.

**3. API-level integration outside webhooks.** For a programmatic caller that isn't a webhook — per `docs.apify.com/integrations/actors/integrating-actors-via-api` — the same `isApifyIntegration: true` / `shouldInterpolateStrings: true` / string-encoded `payloadTemplate` shape from recipe 2 applies to any integration definition your own tooling submits against this Actor's ID.

**4. Export / CRM-adjacent mapping.** Every run's Dataset supports the platform's standard export formats (CSV, Excel, JSON) from the Console or via `GET /v2/datasets/{datasetId}/items?format=csv`. Map `companyName`, `need`, `jobCount`, `confirmedJobCount`, `action`, and `matchedJobs` into a CRM import or spreadsheet — those fields alone are enough to drive an account-prioritization view.

**5. Generic automation tools (n8n, Zapier, Make).** Use each tool's generic Apify/HTTP node to call `run-sync-get-dataset-items` on this Actor's ID with a JSON body containing `datasetId` (from the upstream job-scraper run) and your chosen `maxResults`/`maxInputRows`. This is a plain authenticated HTTPS POST and works without native Apify-integration support in the automation tool.

This Actor being publicly searchable as an Apify integration target (once public) does not imply a recommended-placement partnership with any specific upstream Actor — per `docs.apify.com/integrations/actors/integration-ready-actors`, that requires a separate request this Actor has not made. No outreach to any third party was performed to produce this README.

### Operating guide

1. **Confirm your source batch shape first.** Spot-check a few rows against **Input contract** — specifically that each has a `title` or `description`, and an explicit `company`/`companyName`. A batch missing company data entirely will produce mostly `missing_company` diagnostics, which is worth knowing before a full run.
2. **Start with a small `maxResults` on a new source.** For a source you haven't run through this Actor before, set `maxResults` low (e.g. 5) to confirm the output matches your expectations before committing to a full batch.
3. **Set `maxTotalChargeUsd` deliberately, and check the effective value after the run starts.** Use the platform run option, not an Actor input field. If calling the API directly and you want zero paid signals guaranteed, use a small positive value below your applicable tier price rather than literal `0` — see **Evidence and boundaries**.
4. **Read the `OUTPUT`/`SUMMARY` Key-value store record, not just the Dataset row count.** It reports `requested`/`delivered`/`paid`/`free`/`failed`, whether `budgetStopped`/`resultsCapped` ended the run early, `diagnosticsTruncated` when the initial combined diagnostic list exceeded 200, and `sourcePartial` completeness.
5. **If a run finalizes `FAILED`, inspect before retrying.** Check that run's Dataset and `OUTPUT` record for what was actually delivered and charged up to the failure point before deciding whether to re-run — a blind retry can duplicate already-successful paid signals.
6. **Re-running is always new billing.** There is no dedup key across runs. Treat "run again" as "process (and pay for) this batch again," reserved for when you actually have a new or updated batch, not as a routine safety retry.
7. **Use `confirmedJobCount` as your primary trust signal, not `jobCount`.** When deciding how much weight to put on a signal, check whether it's backed by confirmed job identities or mostly inferred ones (see example 2) — the same headline count can mean very different data quality underneath.

### FAQ

**Does this Actor scrape LinkedIn or any job board itself?** No. It only reads an existing job-postings batch you or an upstream Actor already collected. It never fetches a page from the open web and never starts another Actor.

**Can I use a source other than LinkedIn Jobs Scraper?** Yes — any source producing rows with the fields in **Input contract** (title/description, a company field, optionally jobId/URL/postedDate/categories) works identically.

**Does a hiring signal mean the company has budget or is actively hiring right now?** No. It means a job posting in your source batch, observed on the date the source recorded (`postedDate`), contained matching text. It is not evidence of an approved budget, confirmed headcount growth, or that the position is still open today.

**Can this Actor send outreach messages or find someone's email/phone?** No. It only classifies job-posting text you already have. It has no messaging capability and does not look up, infer, or expose personal contact information.

**Why did the same two postings get a weaker `action` when I removed `jobId`/`jobURL`?** Because `action` is driven by `confirmedJobCount`, not raw `jobCount`. Without an identity field, the module can only distinguish postings by content, which is a genuinely weaker guarantee that they're actually two distinct, trackable jobs — see example 2 in **Output examples**.

**What happens if a posting doesn't match any of the seven need categories?** It produces a free `no_keyword_match` diagnostic — unless it shares a `jobId`/URL with a row that did match a need, in which case it still contributes to that need's job/identity counts as a "bridge" row, without creating a signal of its own.

**Is `matchedJobs` the complete list of postings behind a signal?** Only up to 25 — `jobCount`/`confirmedJobCount`/`inferredJobCount` are always the true, uncapped totals even when `matchedJobs` is truncated (disclosed via a reserved `job_list_truncated` evidence entry).

**Can I set a hard spending cap for a run?** Yes, via the platform's own **Max total charge (USD)** run option. See **Pricing** and **Evidence and boundaries** for how a cap below one signal's price behaves, and an important caveat about the literal value `0` via a raw API call.

**Does re-running the same batch avoid double-billing?** No. Every run is independent processing with no cross-run deduplication — re-running the identical batch is billed again for every signal it produces.

**What does a `FAILED` run mean for what was actually delivered?** It means the run's own delivery/billing state could not be confirmed at some point — not necessarily that zero signals were delivered. Inspect that run's Dataset and `OUTPUT` record before deciding whether to retry.

**Is the public example Dataset (`ErVyHjUdtLa1Dftkn`) something I should point production traffic at?** It's a small, curated real example for trying the Actor without your own source — usable to see real output shape, not a general-purpose data source.

**Why do I see fewer than 200 free diagnostic rows even though my batch had many more unmatched rows?** The initial business-diagnostic plus source-notice list has a 200-entry cap. `businessSummary.diagnosticsCount` counts business diagnostics only; `diagnosticsTruncated` covers that combined list. Later result-size/cap notices are additional.

### Sources and rights

This Actor reads only Datasets and runs your own Apify account token already has permission to read; it never uses another user's credentials and never starts an upstream Actor on your behalf. The public prefilled example (Dataset `ErVyHjUdtLa1Dftkn`) is a curated, non-sensitive copy of real postings originally captured by an upstream `zinin/linkedin-public-jobs-scraper`-shaped run (`sourceActorId JQgY5E6jpd3bvtCmU`, `sourceRunId JrRgbvNEFop2XoObT`, `sourceDatasetId sagPWb8mF8Q9TyChd`) observed on 2026-09-13, reused here with its original observation timestamps and measured field values unchanged — it is a saved example, not a live re-scrape, and contains only allowlisted public job-posting fields with no reviewer/personal identities. All output values shown in this README are copied verbatim from real runs of this Actor's accepted build; none are illustrative or invented.

#### Related tools

Related tools for adjacent workflows in B2B lead generation and data enrichment, jobs and hiring.

| Actor | What it does |
|---|---|
| [Company Hiring Radar](https://apify.com/zinin/company-hiring-radar) | Pair it in the jobs and hiring workflow: Turn buyer-supplied Greenhouse, Lever, or Ashby board tokens into evidence-backed public hiring... |
| [LinkedIn Jobs Scraper](https://apify.com/zinin/linkedin-public-jobs-scraper) | Pair it in the jobs and hiring workflow: Scrape current public LinkedIn job search cards with job IDs, titles, companies, locations, posted dates,... |
| [Himalayas Remote Jobs API](https://apify.com/zinin/himalayas-remote-jobs-api) | Pair it in the jobs and hiring workflow: Return a bounded, attributed set of current remote jobs from the official Himalayas public JSON API |

# Actor input Schema

## `items` (type: `array`):

Small real public example: https://api.apify.com/v2/datasets/ErVyHjUdtLa1Dftkn/items?clean=true . This saved snapshot is not a new scrape.

## `datasetId` (type: `string`):

Read an existing source dataset with your run permissions. Overrides inline items. The resource picker can request scoped READ permission. Integration mapping must use an authorized resource; a plain Dataset ID or webhook payload alone does not grant access. Public example: ErVyHjUdtLa1Dftkn.

## `runId` (type: `string`):

Optional Actor run ID to read instead of Source Dataset. Its default Dataset is resolved with your run's own permissions — no elevated access is used, and no upstream Actor is started.

## `maxInputRows` (type: `integer`):

Maximum source records examined before grouping. At most 1000 rows, 4 MiB total and 64 KiB per row. Capped or incomplete source coverage is reported.

## `maxResults` (type: `integer`):

Maximum useful hiring signal results delivered, independently of the platform Max total charge setting. Free diagnostics are reported separately.

## `payload` (type: `object`):

Optional ACTOR.RUN.SUCCEEDED event payload with resource.defaultDatasetId and resource.id. Dataset resourcePicker is recommended for private datasets; a payload alone does not grant access.

## Actor input object example

```json
{
  "items": [
    {
      "schemaVersion": "1.0",
      "recordType": "linkedin_public_job",
      "jobId": "4419969671",
      "jobURL": "https://www.linkedin.com/jobs/view/senior-software-engineer-%E2%80%93-go-golang-at-general-motors-4419969671",
      "title": "Senior Software Engineer – Go (Golang)",
      "company": "General Motors",
      "location": "Warren, MI",
      "postedTimeText": "1 day ago",
      "postedDate": "2026-09-12",
      "keywords": "software engineer",
      "searchLocation": "United States",
      "pageStart": 0,
      "sourceURL": "https://www.linkedin.com/jobs-guest/jobs/api/seeMoreJobPostings/search?keywords=software+engineer&location=United+States&start=0",
      "observedAt": "2026-09-13T15:50:54.556Z",
      "source": {
        "htmlSha256": "7394931a2e2a538b365c1d5f422aa4e6e38b2e6d2a5c12e6204e7db8ae880606"
      },
      "_exampleProvenance": {
        "sourceActorId": "JQgY5E6jpd3bvtCmU",
        "sourceRunId": "JrRgbvNEFop2XoObT",
        "sourceDatasetId": "sagPWb8mF8Q9TyChd",
        "curatedPublicSnapshot": true,
        "redaction": "Allowlisted public business/product fields only; review excerpts and social captions truncated; no reviewer identities."
      }
    },
    {
      "schemaVersion": "1.0",
      "recordType": "linkedin_public_job",
      "jobId": "4455931376",
      "jobURL": "https://www.linkedin.com/jobs/view/software-development-engineer-aws-iam-distributed-database-system-at-amazon-web-services-aws-4455931376",
      "title": "Software Development Engineer, AWS IAM Distributed Database System",
      "company": "Amazon Web Services (AWS)",
      "location": "Seattle, WA",
      "postedTimeText": "3 days ago",
      "postedDate": "2026-09-09",
      "keywords": "software engineer",
      "searchLocation": "United States",
      "pageStart": 0,
      "sourceURL": "https://www.linkedin.com/jobs-guest/jobs/api/seeMoreJobPostings/search?keywords=software+engineer&location=United+States&start=0",
      "observedAt": "2026-09-13T15:50:54.556Z",
      "source": {
        "htmlSha256": "7394931a2e2a538b365c1d5f422aa4e6e38b2e6d2a5c12e6204e7db8ae880606"
      },
      "_exampleProvenance": {
        "sourceActorId": "JQgY5E6jpd3bvtCmU",
        "sourceRunId": "JrRgbvNEFop2XoObT",
        "sourceDatasetId": "sagPWb8mF8Q9TyChd",
        "curatedPublicSnapshot": true,
        "redaction": "Allowlisted public business/product fields only; review excerpts and social captions truncated; no reviewer identities."
      }
    },
    {
      "schemaVersion": "1.0",
      "recordType": "linkedin_public_job",
      "jobId": "4453670973",
      "jobURL": "https://www.linkedin.com/jobs/view/software-engineer-iii-java-aws-at-jpmorganchase-4453670973",
      "title": "Software Engineer III (Java/AWS)",
      "company": "JPMorganChase",
      "location": "New York, NY",
      "postedTimeText": "1 week ago",
      "postedDate": "2026-09-03",
      "keywords": "software engineer",
      "searchLocation": "United States",
      "pageStart": 0,
      "sourceURL": "https://www.linkedin.com/jobs-guest/jobs/api/seeMoreJobPostings/search?keywords=software+engineer&location=United+States&start=0",
      "observedAt": "2026-09-13T15:50:54.556Z",
      "source": {
        "htmlSha256": "7394931a2e2a538b365c1d5f422aa4e6e38b2e6d2a5c12e6204e7db8ae880606"
      },
      "_exampleProvenance": {
        "sourceActorId": "JQgY5E6jpd3bvtCmU",
        "sourceRunId": "JrRgbvNEFop2XoObT",
        "sourceDatasetId": "sagPWb8mF8Q9TyChd",
        "curatedPublicSnapshot": true,
        "redaction": "Allowlisted public business/product fields only; review excerpts and social captions truncated; no reviewer identities."
      }
    },
    {
      "schemaVersion": "1.0",
      "recordType": "linkedin_public_job",
      "jobId": "4455914852",
      "jobURL": "https://www.linkedin.com/jobs/view/software-dev-engineer-ii-aws-sts-at-amazon-web-services-aws-4455914852",
      "title": "Software Dev Engineer II, AWS STS",
      "company": "Amazon Web Services (AWS)",
      "location": "Seattle, WA",
      "postedTimeText": "3 days ago",
      "postedDate": "2026-09-09",
      "keywords": "software engineer",
      "searchLocation": "United States",
      "pageStart": 0,
      "sourceURL": "https://www.linkedin.com/jobs-guest/jobs/api/seeMoreJobPostings/search?keywords=software+engineer&location=United+States&start=0",
      "observedAt": "2026-09-13T15:50:54.556Z",
      "source": {
        "htmlSha256": "7394931a2e2a538b365c1d5f422aa4e6e38b2e6d2a5c12e6204e7db8ae880606"
      },
      "_exampleProvenance": {
        "sourceActorId": "JQgY5E6jpd3bvtCmU",
        "sourceRunId": "JrRgbvNEFop2XoObT",
        "sourceDatasetId": "sagPWb8mF8Q9TyChd",
        "curatedPublicSnapshot": true,
        "redaction": "Allowlisted public business/product fields only; review excerpts and social captions truncated; no reviewer identities."
      }
    },
    {
      "schemaVersion": "1.0",
      "recordType": "linkedin_public_job",
      "jobId": "4465023265",
      "jobURL": "https://www.linkedin.com/jobs/view/software-engineer-iii-java-aws-ai-at-jpmorganchase-4465023265",
      "title": "Software Engineer III (Java/AWS/AI)",
      "company": "JPMorganChase",
      "location": "Columbus, OH",
      "postedTimeText": "4 days ago",
      "postedDate": "2026-09-09",
      "keywords": "software engineer",
      "searchLocation": "United States",
      "pageStart": 0,
      "sourceURL": "https://www.linkedin.com/jobs-guest/jobs/api/seeMoreJobPostings/search?keywords=software+engineer&location=United+States&start=0",
      "observedAt": "2026-09-13T15:50:54.556Z",
      "source": {
        "htmlSha256": "7394931a2e2a538b365c1d5f422aa4e6e38b2e6d2a5c12e6204e7db8ae880606"
      },
      "_exampleProvenance": {
        "sourceActorId": "JQgY5E6jpd3bvtCmU",
        "sourceRunId": "JrRgbvNEFop2XoObT",
        "sourceDatasetId": "sagPWb8mF8Q9TyChd",
        "curatedPublicSnapshot": true,
        "redaction": "Allowlisted public business/product fields only; review excerpts and social captions truncated; no reviewer identities."
      }
    }
  ],
  "maxInputRows": 100,
  "maxResults": 10
}
```

# Actor output Schema

## `results` (type: `string`):

API URL for the default dataset items produced by this run.

## `summary` (type: `string`):

API URL for the OUTPUT record in the default key-value store.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "items": [
        {
            "schemaVersion": "1.0",
            "recordType": "linkedin_public_job",
            "jobId": "4419969671",
            "jobURL": "https://www.linkedin.com/jobs/view/senior-software-engineer-%E2%80%93-go-golang-at-general-motors-4419969671",
            "title": "Senior Software Engineer – Go (Golang)",
            "company": "General Motors",
            "location": "Warren, MI",
            "postedTimeText": "1 day ago",
            "postedDate": "2026-09-12",
            "keywords": "software engineer",
            "searchLocation": "United States",
            "pageStart": 0,
            "sourceURL": "https://www.linkedin.com/jobs-guest/jobs/api/seeMoreJobPostings/search?keywords=software+engineer&location=United+States&start=0",
            "observedAt": "2026-09-13T15:50:54.556Z",
            "source": {
                "htmlSha256": "7394931a2e2a538b365c1d5f422aa4e6e38b2e6d2a5c12e6204e7db8ae880606"
            },
            "_exampleProvenance": {
                "sourceActorId": "JQgY5E6jpd3bvtCmU",
                "sourceRunId": "JrRgbvNEFop2XoObT",
                "sourceDatasetId": "sagPWb8mF8Q9TyChd",
                "curatedPublicSnapshot": true,
                "redaction": "Allowlisted public business/product fields only; review excerpts and social captions truncated; no reviewer identities."
            }
        },
        {
            "schemaVersion": "1.0",
            "recordType": "linkedin_public_job",
            "jobId": "4455931376",
            "jobURL": "https://www.linkedin.com/jobs/view/software-development-engineer-aws-iam-distributed-database-system-at-amazon-web-services-aws-4455931376",
            "title": "Software Development Engineer, AWS IAM Distributed Database System",
            "company": "Amazon Web Services (AWS)",
            "location": "Seattle, WA",
            "postedTimeText": "3 days ago",
            "postedDate": "2026-09-09",
            "keywords": "software engineer",
            "searchLocation": "United States",
            "pageStart": 0,
            "sourceURL": "https://www.linkedin.com/jobs-guest/jobs/api/seeMoreJobPostings/search?keywords=software+engineer&location=United+States&start=0",
            "observedAt": "2026-09-13T15:50:54.556Z",
            "source": {
                "htmlSha256": "7394931a2e2a538b365c1d5f422aa4e6e38b2e6d2a5c12e6204e7db8ae880606"
            },
            "_exampleProvenance": {
                "sourceActorId": "JQgY5E6jpd3bvtCmU",
                "sourceRunId": "JrRgbvNEFop2XoObT",
                "sourceDatasetId": "sagPWb8mF8Q9TyChd",
                "curatedPublicSnapshot": true,
                "redaction": "Allowlisted public business/product fields only; review excerpts and social captions truncated; no reviewer identities."
            }
        },
        {
            "schemaVersion": "1.0",
            "recordType": "linkedin_public_job",
            "jobId": "4453670973",
            "jobURL": "https://www.linkedin.com/jobs/view/software-engineer-iii-java-aws-at-jpmorganchase-4453670973",
            "title": "Software Engineer III (Java/AWS)",
            "company": "JPMorganChase",
            "location": "New York, NY",
            "postedTimeText": "1 week ago",
            "postedDate": "2026-09-03",
            "keywords": "software engineer",
            "searchLocation": "United States",
            "pageStart": 0,
            "sourceURL": "https://www.linkedin.com/jobs-guest/jobs/api/seeMoreJobPostings/search?keywords=software+engineer&location=United+States&start=0",
            "observedAt": "2026-09-13T15:50:54.556Z",
            "source": {
                "htmlSha256": "7394931a2e2a538b365c1d5f422aa4e6e38b2e6d2a5c12e6204e7db8ae880606"
            },
            "_exampleProvenance": {
                "sourceActorId": "JQgY5E6jpd3bvtCmU",
                "sourceRunId": "JrRgbvNEFop2XoObT",
                "sourceDatasetId": "sagPWb8mF8Q9TyChd",
                "curatedPublicSnapshot": true,
                "redaction": "Allowlisted public business/product fields only; review excerpts and social captions truncated; no reviewer identities."
            }
        },
        {
            "schemaVersion": "1.0",
            "recordType": "linkedin_public_job",
            "jobId": "4455914852",
            "jobURL": "https://www.linkedin.com/jobs/view/software-dev-engineer-ii-aws-sts-at-amazon-web-services-aws-4455914852",
            "title": "Software Dev Engineer II, AWS STS",
            "company": "Amazon Web Services (AWS)",
            "location": "Seattle, WA",
            "postedTimeText": "3 days ago",
            "postedDate": "2026-09-09",
            "keywords": "software engineer",
            "searchLocation": "United States",
            "pageStart": 0,
            "sourceURL": "https://www.linkedin.com/jobs-guest/jobs/api/seeMoreJobPostings/search?keywords=software+engineer&location=United+States&start=0",
            "observedAt": "2026-09-13T15:50:54.556Z",
            "source": {
                "htmlSha256": "7394931a2e2a538b365c1d5f422aa4e6e38b2e6d2a5c12e6204e7db8ae880606"
            },
            "_exampleProvenance": {
                "sourceActorId": "JQgY5E6jpd3bvtCmU",
                "sourceRunId": "JrRgbvNEFop2XoObT",
                "sourceDatasetId": "sagPWb8mF8Q9TyChd",
                "curatedPublicSnapshot": true,
                "redaction": "Allowlisted public business/product fields only; review excerpts and social captions truncated; no reviewer identities."
            }
        },
        {
            "schemaVersion": "1.0",
            "recordType": "linkedin_public_job",
            "jobId": "4465023265",
            "jobURL": "https://www.linkedin.com/jobs/view/software-engineer-iii-java-aws-ai-at-jpmorganchase-4465023265",
            "title": "Software Engineer III (Java/AWS/AI)",
            "company": "JPMorganChase",
            "location": "Columbus, OH",
            "postedTimeText": "4 days ago",
            "postedDate": "2026-09-09",
            "keywords": "software engineer",
            "searchLocation": "United States",
            "pageStart": 0,
            "sourceURL": "https://www.linkedin.com/jobs-guest/jobs/api/seeMoreJobPostings/search?keywords=software+engineer&location=United+States&start=0",
            "observedAt": "2026-09-13T15:50:54.556Z",
            "source": {
                "htmlSha256": "7394931a2e2a538b365c1d5f422aa4e6e38b2e6d2a5c12e6204e7db8ae880606"
            },
            "_exampleProvenance": {
                "sourceActorId": "JQgY5E6jpd3bvtCmU",
                "sourceRunId": "JrRgbvNEFop2XoObT",
                "sourceDatasetId": "sagPWb8mF8Q9TyChd",
                "curatedPublicSnapshot": true,
                "redaction": "Allowlisted public business/product fields only; review excerpts and social captions truncated; no reviewer identities."
            }
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("zinin/job-posting-buying-signal-extractor").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "items": [
        {
            "schemaVersion": "1.0",
            "recordType": "linkedin_public_job",
            "jobId": "4419969671",
            "jobURL": "https://www.linkedin.com/jobs/view/senior-software-engineer-%E2%80%93-go-golang-at-general-motors-4419969671",
            "title": "Senior Software Engineer – Go (Golang)",
            "company": "General Motors",
            "location": "Warren, MI",
            "postedTimeText": "1 day ago",
            "postedDate": "2026-09-12",
            "keywords": "software engineer",
            "searchLocation": "United States",
            "pageStart": 0,
            "sourceURL": "https://www.linkedin.com/jobs-guest/jobs/api/seeMoreJobPostings/search?keywords=software+engineer&location=United+States&start=0",
            "observedAt": "2026-09-13T15:50:54.556Z",
            "source": { "htmlSha256": "7394931a2e2a538b365c1d5f422aa4e6e38b2e6d2a5c12e6204e7db8ae880606" },
            "_exampleProvenance": {
                "sourceActorId": "JQgY5E6jpd3bvtCmU",
                "sourceRunId": "JrRgbvNEFop2XoObT",
                "sourceDatasetId": "sagPWb8mF8Q9TyChd",
                "curatedPublicSnapshot": True,
                "redaction": "Allowlisted public business/product fields only; review excerpts and social captions truncated; no reviewer identities.",
            },
        },
        {
            "schemaVersion": "1.0",
            "recordType": "linkedin_public_job",
            "jobId": "4455931376",
            "jobURL": "https://www.linkedin.com/jobs/view/software-development-engineer-aws-iam-distributed-database-system-at-amazon-web-services-aws-4455931376",
            "title": "Software Development Engineer, AWS IAM Distributed Database System",
            "company": "Amazon Web Services (AWS)",
            "location": "Seattle, WA",
            "postedTimeText": "3 days ago",
            "postedDate": "2026-09-09",
            "keywords": "software engineer",
            "searchLocation": "United States",
            "pageStart": 0,
            "sourceURL": "https://www.linkedin.com/jobs-guest/jobs/api/seeMoreJobPostings/search?keywords=software+engineer&location=United+States&start=0",
            "observedAt": "2026-09-13T15:50:54.556Z",
            "source": { "htmlSha256": "7394931a2e2a538b365c1d5f422aa4e6e38b2e6d2a5c12e6204e7db8ae880606" },
            "_exampleProvenance": {
                "sourceActorId": "JQgY5E6jpd3bvtCmU",
                "sourceRunId": "JrRgbvNEFop2XoObT",
                "sourceDatasetId": "sagPWb8mF8Q9TyChd",
                "curatedPublicSnapshot": True,
                "redaction": "Allowlisted public business/product fields only; review excerpts and social captions truncated; no reviewer identities.",
            },
        },
        {
            "schemaVersion": "1.0",
            "recordType": "linkedin_public_job",
            "jobId": "4453670973",
            "jobURL": "https://www.linkedin.com/jobs/view/software-engineer-iii-java-aws-at-jpmorganchase-4453670973",
            "title": "Software Engineer III (Java/AWS)",
            "company": "JPMorganChase",
            "location": "New York, NY",
            "postedTimeText": "1 week ago",
            "postedDate": "2026-09-03",
            "keywords": "software engineer",
            "searchLocation": "United States",
            "pageStart": 0,
            "sourceURL": "https://www.linkedin.com/jobs-guest/jobs/api/seeMoreJobPostings/search?keywords=software+engineer&location=United+States&start=0",
            "observedAt": "2026-09-13T15:50:54.556Z",
            "source": { "htmlSha256": "7394931a2e2a538b365c1d5f422aa4e6e38b2e6d2a5c12e6204e7db8ae880606" },
            "_exampleProvenance": {
                "sourceActorId": "JQgY5E6jpd3bvtCmU",
                "sourceRunId": "JrRgbvNEFop2XoObT",
                "sourceDatasetId": "sagPWb8mF8Q9TyChd",
                "curatedPublicSnapshot": True,
                "redaction": "Allowlisted public business/product fields only; review excerpts and social captions truncated; no reviewer identities.",
            },
        },
        {
            "schemaVersion": "1.0",
            "recordType": "linkedin_public_job",
            "jobId": "4455914852",
            "jobURL": "https://www.linkedin.com/jobs/view/software-dev-engineer-ii-aws-sts-at-amazon-web-services-aws-4455914852",
            "title": "Software Dev Engineer II, AWS STS",
            "company": "Amazon Web Services (AWS)",
            "location": "Seattle, WA",
            "postedTimeText": "3 days ago",
            "postedDate": "2026-09-09",
            "keywords": "software engineer",
            "searchLocation": "United States",
            "pageStart": 0,
            "sourceURL": "https://www.linkedin.com/jobs-guest/jobs/api/seeMoreJobPostings/search?keywords=software+engineer&location=United+States&start=0",
            "observedAt": "2026-09-13T15:50:54.556Z",
            "source": { "htmlSha256": "7394931a2e2a538b365c1d5f422aa4e6e38b2e6d2a5c12e6204e7db8ae880606" },
            "_exampleProvenance": {
                "sourceActorId": "JQgY5E6jpd3bvtCmU",
                "sourceRunId": "JrRgbvNEFop2XoObT",
                "sourceDatasetId": "sagPWb8mF8Q9TyChd",
                "curatedPublicSnapshot": True,
                "redaction": "Allowlisted public business/product fields only; review excerpts and social captions truncated; no reviewer identities.",
            },
        },
        {
            "schemaVersion": "1.0",
            "recordType": "linkedin_public_job",
            "jobId": "4465023265",
            "jobURL": "https://www.linkedin.com/jobs/view/software-engineer-iii-java-aws-ai-at-jpmorganchase-4465023265",
            "title": "Software Engineer III (Java/AWS/AI)",
            "company": "JPMorganChase",
            "location": "Columbus, OH",
            "postedTimeText": "4 days ago",
            "postedDate": "2026-09-09",
            "keywords": "software engineer",
            "searchLocation": "United States",
            "pageStart": 0,
            "sourceURL": "https://www.linkedin.com/jobs-guest/jobs/api/seeMoreJobPostings/search?keywords=software+engineer&location=United+States&start=0",
            "observedAt": "2026-09-13T15:50:54.556Z",
            "source": { "htmlSha256": "7394931a2e2a538b365c1d5f422aa4e6e38b2e6d2a5c12e6204e7db8ae880606" },
            "_exampleProvenance": {
                "sourceActorId": "JQgY5E6jpd3bvtCmU",
                "sourceRunId": "JrRgbvNEFop2XoObT",
                "sourceDatasetId": "sagPWb8mF8Q9TyChd",
                "curatedPublicSnapshot": True,
                "redaction": "Allowlisted public business/product fields only; review excerpts and social captions truncated; no reviewer identities.",
            },
        },
    ] }

# Run the Actor and wait for it to finish
run = client.actor("zinin/job-posting-buying-signal-extractor").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "items": [
    {
      "schemaVersion": "1.0",
      "recordType": "linkedin_public_job",
      "jobId": "4419969671",
      "jobURL": "https://www.linkedin.com/jobs/view/senior-software-engineer-%E2%80%93-go-golang-at-general-motors-4419969671",
      "title": "Senior Software Engineer – Go (Golang)",
      "company": "General Motors",
      "location": "Warren, MI",
      "postedTimeText": "1 day ago",
      "postedDate": "2026-09-12",
      "keywords": "software engineer",
      "searchLocation": "United States",
      "pageStart": 0,
      "sourceURL": "https://www.linkedin.com/jobs-guest/jobs/api/seeMoreJobPostings/search?keywords=software+engineer&location=United+States&start=0",
      "observedAt": "2026-09-13T15:50:54.556Z",
      "source": {
        "htmlSha256": "7394931a2e2a538b365c1d5f422aa4e6e38b2e6d2a5c12e6204e7db8ae880606"
      },
      "_exampleProvenance": {
        "sourceActorId": "JQgY5E6jpd3bvtCmU",
        "sourceRunId": "JrRgbvNEFop2XoObT",
        "sourceDatasetId": "sagPWb8mF8Q9TyChd",
        "curatedPublicSnapshot": true,
        "redaction": "Allowlisted public business/product fields only; review excerpts and social captions truncated; no reviewer identities."
      }
    },
    {
      "schemaVersion": "1.0",
      "recordType": "linkedin_public_job",
      "jobId": "4455931376",
      "jobURL": "https://www.linkedin.com/jobs/view/software-development-engineer-aws-iam-distributed-database-system-at-amazon-web-services-aws-4455931376",
      "title": "Software Development Engineer, AWS IAM Distributed Database System",
      "company": "Amazon Web Services (AWS)",
      "location": "Seattle, WA",
      "postedTimeText": "3 days ago",
      "postedDate": "2026-09-09",
      "keywords": "software engineer",
      "searchLocation": "United States",
      "pageStart": 0,
      "sourceURL": "https://www.linkedin.com/jobs-guest/jobs/api/seeMoreJobPostings/search?keywords=software+engineer&location=United+States&start=0",
      "observedAt": "2026-09-13T15:50:54.556Z",
      "source": {
        "htmlSha256": "7394931a2e2a538b365c1d5f422aa4e6e38b2e6d2a5c12e6204e7db8ae880606"
      },
      "_exampleProvenance": {
        "sourceActorId": "JQgY5E6jpd3bvtCmU",
        "sourceRunId": "JrRgbvNEFop2XoObT",
        "sourceDatasetId": "sagPWb8mF8Q9TyChd",
        "curatedPublicSnapshot": true,
        "redaction": "Allowlisted public business/product fields only; review excerpts and social captions truncated; no reviewer identities."
      }
    },
    {
      "schemaVersion": "1.0",
      "recordType": "linkedin_public_job",
      "jobId": "4453670973",
      "jobURL": "https://www.linkedin.com/jobs/view/software-engineer-iii-java-aws-at-jpmorganchase-4453670973",
      "title": "Software Engineer III (Java/AWS)",
      "company": "JPMorganChase",
      "location": "New York, NY",
      "postedTimeText": "1 week ago",
      "postedDate": "2026-09-03",
      "keywords": "software engineer",
      "searchLocation": "United States",
      "pageStart": 0,
      "sourceURL": "https://www.linkedin.com/jobs-guest/jobs/api/seeMoreJobPostings/search?keywords=software+engineer&location=United+States&start=0",
      "observedAt": "2026-09-13T15:50:54.556Z",
      "source": {
        "htmlSha256": "7394931a2e2a538b365c1d5f422aa4e6e38b2e6d2a5c12e6204e7db8ae880606"
      },
      "_exampleProvenance": {
        "sourceActorId": "JQgY5E6jpd3bvtCmU",
        "sourceRunId": "JrRgbvNEFop2XoObT",
        "sourceDatasetId": "sagPWb8mF8Q9TyChd",
        "curatedPublicSnapshot": true,
        "redaction": "Allowlisted public business/product fields only; review excerpts and social captions truncated; no reviewer identities."
      }
    },
    {
      "schemaVersion": "1.0",
      "recordType": "linkedin_public_job",
      "jobId": "4455914852",
      "jobURL": "https://www.linkedin.com/jobs/view/software-dev-engineer-ii-aws-sts-at-amazon-web-services-aws-4455914852",
      "title": "Software Dev Engineer II, AWS STS",
      "company": "Amazon Web Services (AWS)",
      "location": "Seattle, WA",
      "postedTimeText": "3 days ago",
      "postedDate": "2026-09-09",
      "keywords": "software engineer",
      "searchLocation": "United States",
      "pageStart": 0,
      "sourceURL": "https://www.linkedin.com/jobs-guest/jobs/api/seeMoreJobPostings/search?keywords=software+engineer&location=United+States&start=0",
      "observedAt": "2026-09-13T15:50:54.556Z",
      "source": {
        "htmlSha256": "7394931a2e2a538b365c1d5f422aa4e6e38b2e6d2a5c12e6204e7db8ae880606"
      },
      "_exampleProvenance": {
        "sourceActorId": "JQgY5E6jpd3bvtCmU",
        "sourceRunId": "JrRgbvNEFop2XoObT",
        "sourceDatasetId": "sagPWb8mF8Q9TyChd",
        "curatedPublicSnapshot": true,
        "redaction": "Allowlisted public business/product fields only; review excerpts and social captions truncated; no reviewer identities."
      }
    },
    {
      "schemaVersion": "1.0",
      "recordType": "linkedin_public_job",
      "jobId": "4465023265",
      "jobURL": "https://www.linkedin.com/jobs/view/software-engineer-iii-java-aws-ai-at-jpmorganchase-4465023265",
      "title": "Software Engineer III (Java/AWS/AI)",
      "company": "JPMorganChase",
      "location": "Columbus, OH",
      "postedTimeText": "4 days ago",
      "postedDate": "2026-09-09",
      "keywords": "software engineer",
      "searchLocation": "United States",
      "pageStart": 0,
      "sourceURL": "https://www.linkedin.com/jobs-guest/jobs/api/seeMoreJobPostings/search?keywords=software+engineer&location=United+States&start=0",
      "observedAt": "2026-09-13T15:50:54.556Z",
      "source": {
        "htmlSha256": "7394931a2e2a538b365c1d5f422aa4e6e38b2e6d2a5c12e6204e7db8ae880606"
      },
      "_exampleProvenance": {
        "sourceActorId": "JQgY5E6jpd3bvtCmU",
        "sourceRunId": "JrRgbvNEFop2XoObT",
        "sourceDatasetId": "sagPWb8mF8Q9TyChd",
        "curatedPublicSnapshot": true,
        "redaction": "Allowlisted public business/product fields only; review excerpts and social captions truncated; no reviewer identities."
      }
    }
  ]
}' |
apify call zinin/job-posting-buying-signal-extractor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,zinin/job-posting-buying-signal-extractor"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/Uzd4yKIybbufQ9oV4/builds/MjlfUVNW38boKNa4D/openapi.json
