{
  "data": {
    "id": "pztgDP2WnbscQoRq3",
    "actId": "UNNeJwTTgLV1LkLh4",
    "userId": "02uzIX6Tp5mOTVMWw",
    "startedAt": "2026-09-03T16:03:46.184Z",
    "finishedAt": "2026-09-03T16:05:24.682Z",
    "status": "SUCCEEDED",
    "meta": {
      "origin": "API"
    },
    "stats": {
      "durationMillis": 98403,
      "runTimeSecs": 98.403,
      "computeUnits": 0.10933666666666667,
      "imageSizeBytes": 1310459904
    },
    "options": {
      "useCache": false,
      "betaPackages": false,
      "tag": "latest",
      "memoryMbytes": 4096,
      "diskMbytes": 8192
    },
    "exitCode": 0,
    "inputSchema": "{\n  \"title\": \"LinkedIn profile URLs and enrichment options\",\n  \"type\": \"object\",\n  \"schemaVersion\": 1,\n  \"properties\": {\n    \"profileUrls\": {\n      \"title\": \"Profile URLs\",\n      \"type\": \"array\",\n      \"description\": \"LinkedIn public profile URLs to enrich, one record per URL in output order. Apify free-plan users are limited to 5 URLs per run and 5 email lookups per UTC day; paid Apify plans have no trial caps.\",\n      \"editor\": \"stringList\",\n      \"prefill\": [\n        \"https://www.linkedin.com/in/satyanadella/\"\n      ],\n      \"minItems\": 1,\n      \"items\": {\n        \"type\": \"string\"\n      }\n    },\n    \"findEmail\": {\n      \"title\": \"Find email\",\n      \"type\": \"boolean\",\n      \"description\": \"When true, run the email cascade after a usable profile is acquired.\",\n      \"default\": true\n    },\n    \"acceptPatternEmails\": {\n      \"title\": \"Accept risky catch-all emails\",\n      \"type\": \"boolean\",\n      \"description\": \"Catch-all guesses are always returned as emailConfidence=risky and never charged as email-found. Kept for stored tasks; turning this off no longer hides the address.\",\n      \"default\": true\n    },\n    \"skipDuplicates\": {\n      \"title\": \"Skip duplicate URLs\",\n      \"type\": \"boolean\",\n      \"description\": \"Deduplicate repeated URLs within the same run while preserving first-seen inputIndex.\",\n      \"default\": true\n    },\n    \"maxRetriesPerProfile\": {\n      \"title\": \"Max retries per profile\",\n      \"type\": \"integer\",\n      \"description\": \"Datacenter HTTP attempt budget. Default is one cheap attempt; permanent errors (404) never retry. Residential fallback is independently capped at two attempts.\",\n      \"default\": 1,\n      \"minimum\": 0,\n      \"maximum\": 10\n    },\n    \"enableBrowserFallback\": {\n      \"title\": \"Enable guest browser fallback\",\n      \"type\": \"boolean\",\n      \"description\": \"After HTTP attempts, try anonymous Firefox on a sticky residential identity. Never uses LinkedIn login cookies or credentials. Repeated HTTP 999s open a circuit so a dead browser layer cannot dominate run time.\",\n      \"default\": false\n    },\n    \"maxConcurrency\": {\n      \"title\": \"Max concurrency\",\n      \"type\": \"integer\",\n      \"description\": \"In-flight profile fetches. Default 8 blends into LinkedIn traffic; 15–25 is the measured ceiling (ARCHITETTURA.md §4).\",\n      \"default\": 8,\n      \"minimum\": 1,\n      \"maximum\": 50\n    },\n    \"proxyConfiguration\": {\n      \"title\": \"Proxy configuration\",\n      \"type\": \"object\",\n      \"description\": \"Apify Proxy settings for LinkedIn requests. Default uses datacenter IPs (VALIDAZIONE §9.8).\",\n      \"editor\": \"proxy\",\n      \"default\": {\n        \"useApifyProxy\": true,\n        \"groups\": [\n          \"DATACENTER\"\n        ]\n      }\n    }\n  },\n  \"required\": [\n    \"profileUrls\"\n  ]\n}",
    "readme": "# LinkedIn Profile + Verified Email — Pay Only When Found\n\nPay-per-event actor that delivers **one dataset row per input URL**, in input\norder, and bills only **after** the row is written to the dataset.\n\nProvide public LinkedIn `/in/<slug>` profile URLs. The actor fetches profile\nfields from an upstream people scraper (name, headline, company, location,\ncompany website) and optionally runs an offline-first email cascade that\ncharges only when a deliverable email is found.\n\n## Features\n\n- **One row per URL** — input order preserved; duplicates can be skipped\n- **Full public profiles** — name, headline, company, location, and company website from an upstream people scraper (not guest HTML)\n- **Verified work email when MillionVerifier says sendable** — domain resolve → person-shaped patterns (`{first}.{last}`, `{f}.{last}`, …) → industry-grade verification\n- **Catch-all guesses returned, never billed** — `emailConfidence=risky` on catch-all domains; `email-found` fires only for `verified`\n- **Transparent billing** — `qualifiedEvents` / `excludedEvents` on every row; amounts in KV `billing-reconciliation`\n- **Resume-safe** — reconciliation flushed on `ABORTING` / `MIGRATING`\n\n## Input\n\n| Field | Type | Default | Description |\n|-------|------|---------|-------------|\n| `profileUrls` | string[] | required | LinkedIn public profile URLs (`/in/...`) |\n| `findEmail` | boolean | `true` | Run email cascade after a usable profile |\n| `acceptPatternEmails` | boolean | `true` | Catch-all guesses are always written as `risky` and never billed. Kept for stored tasks; the flag no longer hides the address |\n| `skipDuplicates` | boolean | `true` | Deduplicate URLs within the run |\n| `maxRetriesPerProfile` | integer | `1` | Datacenter attempts; residential HTTP fallback is capped at 2 |\n| `enableBrowserFallback` | boolean | `false` | Anonymous Firefox fallback on residential proxy; never accepts authenticated LinkedIn cookies |\n| `maxConcurrency` | integer | `8` | In-flight profile fetches |\n| `proxyConfiguration` | object | DATACENTER | Apify Proxy settings |\n\n### Apify free trial (platform)\n\nOn the Apify platform, **free-plan** users get the full product (profile + email\ncascade) with tight caps so upstream verification costs stay sustainable:\n\n| Limit | Free plan | Paid Apify plan |\n|-------|-----------|-----------------|\n| `profileUrls` per run | 5 max (extra URLs dropped) | No cap |\n| Email cascades per UTC day | 5 across runs | No cap |\n\nWhen the daily email quota is used up, profiles are still fetched but email lookup\nis skipped (`emailSkipReason`: `free_trial_exhausted`). Upgrade at\n[Apify pricing](https://apify.com/pricing) for unlimited usage.\n\n## Output\n\nEach dataset row includes `inputUrl`, `inputIndex`, `status`\n(`ok` \\| `partial` \\| `not_found` \\| `blocked` \\| `error`), profile fields\n(`fullName`, `headline`, `location`, `companyName`, `companyLinkedinUrl`,\n`companyLinkedinId`, `companyDomain`, `companyDomainConfidence`), email\nfields (`email`, `emailConfidence`, `emailSkipReason`, `emailEvidence`), and\nbilling eligibility (`qualifiedEvents`, `excludedEvents`).\n\n## Events (Store monetization)\n\n| Event | Price (USD) | When |\n|---|---:|---|\n| `apify-actor-start` | 0.00005 | Automatic once per run at 1 GB |\n| `profile` | 0.004 | Row qualifies: `fullName` + `companyName`, status not blocked/error/not_found |\n| `email-found` | 0.028 | Strictly verified email only. Catch-all / `risky` addresses are written on the row and never billed |\n\nDomain search uses hostname, result title/snippet, search rank, repeated-result,\nand LinkedIn company identity signals. Low-score and near-tied matches are\nrejected instead of guessing. Dutch surname particles are retained when\nbuilding the top five verification candidates.\n\n## How to verify your invoice\n\nOpen the run's **Key-value store** → record **`billing-reconciliation`**:\n\n```json\n{\n  \"byInputIndex\": {\n    \"0\": { \"profile\": 0.004, \"email-found\": 0.028 },\n    \"1\": {}\n  },\n  \"totalUsd\": 0.032,\n  \"rowsDelivered\": 2,\n  \"rowsCharged\": 1\n}\n```\n\nRows do **not** embed charged amounts (datasets are append-only). Use the KV\nrecord to match the Apify invoice.\n\n## Legal / GDPR\n\nPublic Art. 13–14 privacy notices (hosted on Apify KV, permanent signed URLs):\n\n- [English](https://api.apify.com/v2/key-value-stores/jZUn8TR3AeaEwtT2h/records/linkedin-profile-verified-email-privacy.en.html?signature=PcrXf7uRJ0kRmb0GyaoF)\n- [Italiano](https://api.apify.com/v2/key-value-stores/jZUn8TR3AeaEwtT2h/records/linkedin-profile-verified-email-privacy.it.html?signature=1hw4BrYTxQxCkyN0CToYp)\n\nSource stubs and URL manifest: [`docs/privacy/`](./docs/privacy/README.md).\n\n## Development (monorepo)\n\nThis actor lives at `actors/linkedin-profile-verified-email/` in the Pequod\nmonorepo. It is **self-contained** (not a `packages/pequod` thin wrapper).\n\n```bash\ncd actors/linkedin-profile-verified-email\npython3.13 -m venv .venv && source .venv/bin/activate\npip install -r requirements.txt -c constraints.txt -r requirements-dev.txt\npython -m pytest -q\npython -m src.main --local\n```\n\nLive platform smoke:\n\n```bash\nAPIFY_TOKEN=... python3 scripts/live_smoke.py --profile-only\n```\n\nDeploy:\n\n```bash\ncd actors/linkedin-profile-verified-email\nAPIFY_TOKEN=... python3 scripts/deploy_prod.py --dry-run\n# live deploy only from origin/main:\nAPIFY_TOKEN=... python3 scripts/deploy_prod.py\n```\n\nNever use `npx apify push` — it wipes Console secrets. See `DEVELOPMENT.md`.\n\nMemory is pinned to **1024 MB**. Docker installs `requirements.txt` with\n`constraints.txt` and the Firefox runtime so transitive pins stay aligned with\nlocal dev. Browser acquisition is still opt-in and safely reports\n`browser_unavailable` if Playwright or Firefox cannot start.\n\nSee `DEVELOPMENT.md` for secrets, publication checklist, and architecture notes.\n\n## Pequod ecommerce pipeline\n\n| Step | Actor | When |\n|------|-------|------|\n| 1. Discover restaurants | [Restaurant Leads](https://apify.com/pequod-labs/restaurant-leads) | Restaurant email list from Google Maps |\n| 1. Discover local businesses | [Google Maps Local Leads](https://apify.com/pequod-labs/google-maps-local-leads) | Horizontal local leads |\n| 2. Enrich contact | [Decision Maker Finder](https://apify.com/pequod-labs/company-decision-maker-finder) | Named decision makers on a company domain |\n",
    "actorDefinition": {
      "actorSpecification": 1,
      "name": "linkedin-profile-verified-email",
      "title": "LinkedIn Profile + Verified Email — Pay Only When Found",
      "seoTitle": "LinkedIn Profile Scraper with Verified Email | Pay Per Find",
      "seoDescription": "Scrape public LinkedIn profiles and optionally find verified work emails. Pay only when a usable profile or deliverable email is found.",
      "description": "Given LinkedIn public profile URLs, deliver one dataset row per URL with profile fields and optional verified work email. Pay-per-event: charge only for usable profiles and emails found.",
      "version": "0.1",
      "buildTag": "latest",
      "categories": [
        "LEAD_GENERATION",
        "SOCIAL_MEDIA"
      ],
      "defaultMemoryMbytes": 1024,
      "minMemoryMbytes": 1024,
      "maxMemoryMbytes": 1024,
      "usesStandbyMode": false,
      "environmentVariables": {
        "MV_API_KEY": "@MV_API_KEY",
        "MILLIONVERIFIER_API_KEY": "@MILLIONVERIFIER_API_KEY",
        "SERPER_API_KEY": "@SERPER_API_KEY",
        "EXA_API_KEY": "@EXA_API_KEY",
        "UNDERLYING_API_TOKEN": "@UNDERLYING_API_TOKEN",
        "GITHUB_TOKEN": "@GITHUB_TOKEN",
        "BRIGHTDATA_API_KEY": "@BRIGHTDATA_API_KEY",
        "DOMAIN_CACHE_STORE_NAME": "linkedin-profile-verified-email-domain-cache",
        "TRIAL_STATE_TOKEN": "@TRIAL_STATE_TOKEN",
        "TRIAL_STATE_STORE_NAME": "linkedin-email-finder-trial-state",
        "TRIAL_OWNER_USER_ID": "@TRIAL_OWNER_USER_ID"
      },
      "dockerfile": "./Dockerfile",
      "readme": "# LinkedIn Profile + Verified Email — Pay Only When Found\n\nPay-per-event actor that delivers **one dataset row per input URL**, in input\norder, and bills only **after** the row is written to the dataset.\n\nProvide public LinkedIn `/in/<slug>` profile URLs. The actor fetches profile\nfields from an upstream people scraper (name, headline, company, location,\ncompany website) and optionally runs an offline-first email cascade that\ncharges only when a deliverable email is found.\n\n## Features\n\n- **One row per URL** — input order preserved; duplicates can be skipped\n- **Full public profiles** — name, headline, company, location, and company website from an upstream people scraper (not guest HTML)\n- **Verified work email when MillionVerifier says sendable** — domain resolve → person-shaped patterns (`{first}.{last}`, `{f}.{last}`, …) → industry-grade verification\n- **Catch-all guesses returned, never billed** — `emailConfidence=risky` on catch-all domains; `email-found` fires only for `verified`\n- **Transparent billing** — `qualifiedEvents` / `excludedEvents` on every row; amounts in KV `billing-reconciliation`\n- **Resume-safe** — reconciliation flushed on `ABORTING` / `MIGRATING`\n\n## Input\n\n| Field | Type | Default | Description |\n|-------|------|---------|-------------|\n| `profileUrls` | string[] | required | LinkedIn public profile URLs (`/in/...`) |\n| `findEmail` | boolean | `true` | Run email cascade after a usable profile |\n| `acceptPatternEmails` | boolean | `true` | Catch-all guesses are always written as `risky` and never billed. Kept for stored tasks; the flag no longer hides the address |\n| `skipDuplicates` | boolean | `true` | Deduplicate URLs within the run |\n| `maxRetriesPerProfile` | integer | `1` | Datacenter attempts; residential HTTP fallback is capped at 2 |\n| `enableBrowserFallback` | boolean | `false` | Anonymous Firefox fallback on residential proxy; never accepts authenticated LinkedIn cookies |\n| `maxConcurrency` | integer | `8` | In-flight profile fetches |\n| `proxyConfiguration` | object | DATACENTER | Apify Proxy settings |\n\n### Apify free trial (platform)\n\nOn the Apify platform, **free-plan** users get the full product (profile + email\ncascade) with tight caps so upstream verification costs stay sustainable:\n\n| Limit | Free plan | Paid Apify plan |\n|-------|-----------|-----------------|\n| `profileUrls` per run | 5 max (extra URLs dropped) | No cap |\n| Email cascades per UTC day | 5 across runs | No cap |\n\nWhen the daily email quota is used up, profiles are still fetched but email lookup\nis skipped (`emailSkipReason`: `free_trial_exhausted`). Upgrade at\n[Apify pricing](https://apify.com/pricing) for unlimited usage.\n\n## Output\n\nEach dataset row includes `inputUrl`, `inputIndex`, `status`\n(`ok` \\| `partial` \\| `not_found` \\| `blocked` \\| `error`), profile fields\n(`fullName`, `headline`, `location`, `companyName`, `companyLinkedinUrl`,\n`companyLinkedinId`, `companyDomain`, `companyDomainConfidence`), email\nfields (`email`, `emailConfidence`, `emailSkipReason`, `emailEvidence`), and\nbilling eligibility (`qualifiedEvents`, `excludedEvents`).\n\n## Events (Store monetization)\n\n| Event | Price (USD) | When |\n|---|---:|---|\n| `apify-actor-start` | 0.00005 | Automatic once per run at 1 GB |\n| `profile` | 0.004 | Row qualifies: `fullName` + `companyName`, status not blocked/error/not_found |\n| `email-found` | 0.028 | Strictly verified email only. Catch-all / `risky` addresses are written on the row and never billed |\n\nDomain search uses hostname, result title/snippet, search rank, repeated-result,\nand LinkedIn company identity signals. Low-score and near-tied matches are\nrejected instead of guessing. Dutch surname particles are retained when\nbuilding the top five verification candidates.\n\n## How to verify your invoice\n\nOpen the run's **Key-value store** → record **`billing-reconciliation`**:\n\n```json\n{\n  \"byInputIndex\": {\n    \"0\": { \"profile\": 0.004, \"email-found\": 0.028 },\n    \"1\": {}\n  },\n  \"totalUsd\": 0.032,\n  \"rowsDelivered\": 2,\n  \"rowsCharged\": 1\n}\n```\n\nRows do **not** embed charged amounts (datasets are append-only). Use the KV\nrecord to match the Apify invoice.\n\n## Legal / GDPR\n\nPublic Art. 13–14 privacy notices (hosted on Apify KV, permanent signed URLs):\n\n- [English](https://api.apify.com/v2/key-value-stores/jZUn8TR3AeaEwtT2h/records/linkedin-profile-verified-email-privacy.en.html?signature=PcrXf7uRJ0kRmb0GyaoF)\n- [Italiano](https://api.apify.com/v2/key-value-stores/jZUn8TR3AeaEwtT2h/records/linkedin-profile-verified-email-privacy.it.html?signature=1hw4BrYTxQxCkyN0CToYp)\n\nSource stubs and URL manifest: [`docs/privacy/`](./docs/privacy/README.md).\n\n## Development (monorepo)\n\nThis actor lives at `actors/linkedin-profile-verified-email/` in the Pequod\nmonorepo. It is **self-contained** (not a `packages/pequod` thin wrapper).\n\n```bash\ncd actors/linkedin-profile-verified-email\npython3.13 -m venv .venv && source .venv/bin/activate\npip install -r requirements.txt -c constraints.txt -r requirements-dev.txt\npython -m pytest -q\npython -m src.main --local\n```\n\nLive platform smoke:\n\n```bash\nAPIFY_TOKEN=... python3 scripts/live_smoke.py --profile-only\n```\n\nDeploy:\n\n```bash\ncd actors/linkedin-profile-verified-email\nAPIFY_TOKEN=... python3 scripts/deploy_prod.py --dry-run\n# live deploy only from origin/main:\nAPIFY_TOKEN=... python3 scripts/deploy_prod.py\n```\n\nNever use `npx apify push` — it wipes Console secrets. See `DEVELOPMENT.md`.\n\nMemory is pinned to **1024 MB**. Docker installs `requirements.txt` with\n`constraints.txt` and the Firefox runtime so transitive pins stay aligned with\nlocal dev. Browser acquisition is still opt-in and safely reports\n`browser_unavailable` if Playwright or Firefox cannot start.\n\nSee `DEVELOPMENT.md` for secrets, publication checklist, and architecture notes.\n\n## Pequod ecommerce pipeline\n\n| Step | Actor | When |\n|------|-------|------|\n| 1. Discover restaurants | [Restaurant Leads](https://apify.com/pequod-labs/restaurant-leads) | Restaurant email list from Google Maps |\n| 1. Discover local businesses | [Google Maps Local Leads](https://apify.com/pequod-labs/google-maps-local-leads) | Horizontal local leads |\n| 2. Enrich contact | [Decision Maker Finder](https://apify.com/pequod-labs/company-decision-maker-finder) | Named decision makers on a company domain |\n",
      "input": {
        "title": "LinkedIn profile URLs and enrichment options",
        "type": "object",
        "schemaVersion": 1,
        "properties": {
          "profileUrls": {
            "title": "Profile URLs",
            "type": "array",
            "description": "LinkedIn public profile URLs to enrich, one record per URL in output order. Apify free-plan users are limited to 5 URLs per run and 5 email lookups per UTC day; paid Apify plans have no trial caps.",
            "editor": "stringList",
            "prefill": [
              "https://www.linkedin.com/in/satyanadella/"
            ],
            "minItems": 1,
            "items": {
              "type": "string"
            }
          },
          "findEmail": {
            "title": "Find email",
            "type": "boolean",
            "description": "When true, run the email cascade after a usable profile is acquired.",
            "default": true
          },
          "acceptPatternEmails": {
            "title": "Accept risky catch-all emails",
            "type": "boolean",
            "description": "Catch-all guesses are always returned as emailConfidence=risky and never charged as email-found. Kept for stored tasks; turning this off no longer hides the address.",
            "default": true
          },
          "skipDuplicates": {
            "title": "Skip duplicate URLs",
            "type": "boolean",
            "description": "Deduplicate repeated URLs within the same run while preserving first-seen inputIndex.",
            "default": true
          },
          "maxRetriesPerProfile": {
            "title": "Max retries per profile",
            "type": "integer",
            "description": "Datacenter HTTP attempt budget. Default is one cheap attempt; permanent errors (404) never retry. Residential fallback is independently capped at two attempts.",
            "default": 1,
            "minimum": 0,
            "maximum": 10
          },
          "enableBrowserFallback": {
            "title": "Enable guest browser fallback",
            "type": "boolean",
            "description": "After HTTP attempts, try anonymous Firefox on a sticky residential identity. Never uses LinkedIn login cookies or credentials. Repeated HTTP 999s open a circuit so a dead browser layer cannot dominate run time.",
            "default": false
          },
          "maxConcurrency": {
            "title": "Max concurrency",
            "type": "integer",
            "description": "In-flight profile fetches. Default 8 blends into LinkedIn traffic; 15–25 is the measured ceiling (ARCHITETTURA.md §4).",
            "default": 8,
            "minimum": 1,
            "maximum": 50
          },
          "proxyConfiguration": {
            "title": "Proxy configuration",
            "type": "object",
            "description": "Apify Proxy settings for LinkedIn requests. Default uses datacenter IPs (VALIDAZIONE §9.8).",
            "editor": "proxy",
            "default": {
              "useApifyProxy": true,
              "groups": [
                "DATACENTER"
              ]
            }
          }
        },
        "required": [
          "profileUrls"
        ]
      },
      "output": {
        "actorOutputSchemaVersion": 1,
        "title": "LinkedIn Profile + Verified Email output",
        "description": "One dataset row per input profile URL (input order). Key-value records hold the run summary and billing reconciliation.",
        "properties": {
          "profiles": {
            "type": "string",
            "title": "Profiles",
            "template": "{{links.apiDefaultDatasetUrl}}/items"
          },
          "runSummary": {
            "type": "string",
            "title": "Run summary",
            "template": "{{links.apiDefaultKeyValueStoreUrl}}/records/RUN_SUMMARY"
          },
          "billingReconciliation": {
            "type": "string",
            "title": "Billing reconciliation",
            "template": "{{links.apiDefaultKeyValueStoreUrl}}/records/billing-reconciliation"
          }
        }
      },
      "storages": {
        "dataset": {
          "actorSpecification": 1,
          "fields": {
            "inputUrl": {
              "type": "string",
              "description": "Original LinkedIn profile URL from input."
            },
            "inputIndex": {
              "type": "integer",
              "description": "Zero-based index in profileUrls; output order matches input order."
            },
            "status": {
              "type": "string",
              "description": "Delivery outcome: ok | partial | not_found | blocked | error."
            },
            "fullName": {
              "type": "string",
              "description": "Person name from the upstream profile lookup when available."
            },
            "headline": {
              "type": "string",
              "description": "Profile headline or job title."
            },
            "location": {
              "type": "string",
              "description": "Profile location when available."
            },
            "companyName": {
              "type": "string",
              "description": "Current employer when available."
            },
            "companyLinkedinUrl": {
              "type": "string",
              "description": "Canonical LinkedIn company page URL when exposed by the profile source."
            },
            "companyLinkedinId": {
              "type": "string",
              "description": "LinkedIn company slug or id used to disambiguate the employer."
            },
            "companyDomain": {
              "type": "string",
              "description": "Resolved company domain when email cascade runs."
            },
            "companyDomainSource": {
              "type": "string",
              "description": "How companyDomain was resolved (e.g. linkedin_company_page)."
            },
            "companyDomainConfidence": {
              "type": "number",
              "description": "Confidence from 0 to 1 for the accepted company-domain match."
            },
            "companyDomainSignals": {
              "type": "array",
              "description": "Non-PII signals supporting the company-domain match."
            },
            "email": {
              "type": "string",
              "description": "Work email when found. verified = sendable; risky = catch-all guess, not billed."
            },
            "emailConfidence": {
              "type": "string",
              "description": "verified | risky | pattern | null. Pattern is retained for legacy rows; new catch-all candidates are risky."
            },
            "emailSkipReason": {
              "type": "string",
              "description": "Why email was not delivered: no_domain, catch_all, no_candidate_valid, find_email_disabled, etc."
            },
            "emailEvidence": {
              "type": "object",
              "description": "Pattern, verification, and MX metadata supporting the email field."
            },
            "mobile": {
              "type": "string",
              "description": "Reserved for v2; always null in this version."
            },
            "duplicateOfInputIndex": {
              "type": "integer",
              "description": "When skipDuplicates=true and this URL repeats, index of the first billed occurrence."
            },
            "qualifiedEvents": {
              "type": "array",
              "description": "Billable events this row qualifies for based on its content (name, email, status, input flags). Does NOT assert you were charged — verify via run key-value store billing-reconciliation."
            },
            "excludedEvents": {
              "type": "object",
              "description": "Billable events this row does not qualify for, with human-readable reasons (event name → reason)."
            },
            "errorMessage": {
              "type": "string",
              "description": "Diagnostic message when status is error."
            },
            "acquisitionSource": {
              "type": "string",
              "description": "How the profile was acquired: ldjson, opengraph, brightdata, etc."
            },
            "attempts": {
              "type": "integer",
              "description": "HTTP fetch attempts before the profile was classified."
            },
            "lastHttpStatus": {
              "type": "integer",
              "description": "Last HTTP status from profile acquisition (e.g. 200, 999)."
            },
            "scrapedAt": {
              "type": "string",
              "description": "ISO-8601 UTC timestamp when the record was finalized."
            }
          },
          "views": {
            "overview": {
              "title": "Profiles",
              "transformation": {
                "fields": [
                  "inputIndex",
                  "inputUrl",
                  "status",
                  "fullName",
                  "companyName",
                  "companyLinkedinUrl",
                  "companyDomain",
                  "companyDomainConfidence",
                  "email",
                  "emailConfidence",
                  "emailSkipReason",
                  "acquisitionSource",
                  "lastHttpStatus",
                  "qualifiedEvents",
                  "excludedEvents"
                ]
              },
              "display": {
                "component": "table",
                "properties": {
                  "inputIndex": {
                    "label": "#",
                    "format": "number"
                  },
                  "status": {
                    "label": "Status",
                    "format": "text"
                  },
                  "fullName": {
                    "label": "Name",
                    "format": "text"
                  },
                  "companyName": {
                    "label": "Company",
                    "format": "text"
                  },
                  "email": {
                    "label": "Email",
                    "format": "text"
                  },
                  "emailConfidence": {
                    "label": "Confidence",
                    "format": "text"
                  },
                  "qualifiedEvents": {
                    "label": "Qualified events",
                    "format": "object"
                  }
                }
              }
            }
          }
        }
      }
    },
    "buildNumber": "0.1.32",
    "actVersion": {
      "sourceType": "SOURCE_FILES",
      "buildTag": "latest",
      "versionNumber": "0.1"
    },
    "usage": {
      "ACTOR_COMPUTE_UNITS": 0.10933666666666667
    }
  }
}