{
  "openapi": "3.0.1",
  "info": {
    "title": "HubSpot Lead Pusher — Auto-Create Contacts, Companies & Deals",
    "description": "Push scraped leads directly into HubSpot CRM as contacts, companies, and deals. Feed in lead data from any Apify actor or paste it manually, and HubSpot Lead Pusher handles the mapping, deduplication, and batch upsert via the HubSpot API.",
    "version": "1.2",
    "x-build-id": "vaE4PwU85Vr9oYloy"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/ryanclinton~hubspot-lead-pusher/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-ryanclinton-hubspot-lead-pusher",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/acts/ryanclinton~hubspot-lead-pusher/runs": {
      "post": {
        "operationId": "runs-sync-ryanclinton-hubspot-lead-pusher",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor and returns information about the initiated run in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/runsResponseSchema"
                }
              }
            }
          }
        }
      }
    },
    "/acts/ryanclinton~hubspot-lead-pusher/run-sync": {
      "post": {
        "operationId": "run-sync-ryanclinton-hubspot-lead-pusher",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "inputSchema": {
        "type": "object",
        "properties": {
          "mode": {
            "title": "Mode (job preset)",
            "enum": [
              "prospect-import",
              "crm-hygiene-sync",
              "signup-gate",
              "event-attendees",
              "account-based-push",
              "audit-only",
              "raw"
            ],
            "type": "string",
            "description": "Preset bundle for common CRM-push jobs. 'prospect-import' = cold-outbound import (companies + contacts + deals, lifecycle=lead). 'crm-hygiene-sync' = weekly refresh (no deals). 'signup-gate' = newsletter capture (subscribers, no deals). 'event-attendees' = webinar/event imports (MQL contacts + deals). 'account-based-push' = ABM mode: one deal per company, decision-maker contacts only, full Contact↔Deal + Company↔Deal associations. 'audit-only' = dry-run mapping preview. 'raw' = no preset, apply your own flags. Explicit createCompanies/createContacts/createDeals/lifecycleStage values always override the preset.",
            "default": "raw"
          },
          "hubspotAccessToken": {
            "title": "HubSpot Access Token",
            "type": "string",
            "description": "Private app access token from HubSpot. Create one at Settings > Integrations > Private Apps. Required scopes: crm.objects.contacts.write, crm.objects.companies.write, crm.objects.deals.write. Leave empty for dry-run mode."
          },
          "leads": {
            "title": "Leads (inline data)",
            "maxItems": 5000,
            "type": "array",
            "description": "Lead data to push to HubSpot. Each object should have at least a domain or email. Supports output from B2B Lead Gen Suite, Google Maps Lead Enricher, Lead Scoring Engine, Lead Enrichment Pipeline, or custom data. Capped at 5000 leads per run.",
            "default": [
              {
                "domain": "apify.com",
                "companyName": "Apify",
                "emails": [
                  "hello@apify.com"
                ],
                "phones": [
                  "+420-234-567-891"
                ],
                "contacts": [
                  {
                    "name": "Jan Curn",
                    "title": "CEO",
                    "email": "jan@apify.com"
                  }
                ],
                "score": 85,
                "grade": "A"
              }
            ]
          },
          "datasetId": {
            "title": "Apify Dataset ID",
            "type": "string",
            "description": "Apify dataset ID to pull leads from (alternative to inline leads). Use this to chain with other actors like B2B Lead Gen Suite, Lead Scoring Engine, or Lead Enrichment Pipeline."
          },
          "createCompanies": {
            "title": "Create companies",
            "type": "boolean",
            "description": "Create or update HubSpot company records from lead domains. Override the mode preset if set explicitly.",
            "default": true
          },
          "createContacts": {
            "title": "Create contacts",
            "type": "boolean",
            "description": "Create or update HubSpot contact records from lead emails and contacts. Override the mode preset if set explicitly.",
            "default": true
          },
          "createDeals": {
            "title": "Create deals",
            "type": "boolean",
            "description": "Create a HubSpot deal for each lead. Useful for sales pipeline automation. Override the mode preset if set explicitly.",
            "default": false
          },
          "dealStage": {
            "title": "Deal stage",
            "type": "string",
            "description": "HubSpot deal stage for new deals. Common values: appointmentscheduled, qualifiedtobuy, presentationscheduled, decisionmakerboughtin, contractsent, closedwon, closedlost.",
            "default": "appointmentscheduled"
          },
          "lifecycleStage": {
            "title": "Lifecycle stage",
            "type": "string",
            "description": "HubSpot lifecycle stage for new contacts. Values: subscriber, lead, marketingqualifiedlead, salesqualifiedlead, opportunity, customer, evangelist, other. Override the mode preset if set explicitly.",
            "default": "lead"
          },
          "dryRun": {
            "title": "Dry run (preview only)",
            "type": "boolean",
            "description": "Preview the mapped HubSpot data without actually pushing to CRM. Useful for verifying field mapping before committing. Auto-on when mode='audit-only'.",
            "default": true
          },
          "outputProfile": {
            "title": "Output profile",
            "enum": [
              "minimal",
              "standard",
              "full",
              "llm"
            ],
            "type": "string",
            "description": "Shape the dataset records for different consumers. 'minimal' = ids + status only (CSV-friendly). 'standard' = full result minus diagnostic blocks. 'full' = every field including decisionSnapshot for audit/replay. 'llm' = decision-friendly subset for AI agents.",
            "default": "standard"
          },
          "systemMode": {
            "title": "System mode (auto-enable batch + cohort insights)",
            "type": "boolean",
            "description": "Auto-enables batch insights (run-level list-quality summary) and cohort insights (per-domain rollup) without setting them individually. Use when integrating into recurring workflows.",
            "default": false
          },
          "includeBatchInsights": {
            "title": "Include batch insights",
            "type": "boolean",
            "description": "Append a run-level summary record with success rate, failure category distribution, and sibling-actor recommendations. Auto-on with systemMode.",
            "default": false
          },
          "includeCohortInsights": {
            "title": "Include cohort insights (per-domain)",
            "type": "boolean",
            "description": "Group leads by canonical domain and emit per-domain push outcome on each record + a COHORT_INSIGHTS key in KV. Useful for ABM workflows. Auto-on with systemMode.",
            "default": false
          },
          "pushStrategy": {
            "title": "Push strategy",
            "type": "object",
            "description": "Fine-grained control over WHO gets pushed and HOW. contactPolicy ('all' | 'best-only' | 'role-based') filters which contacts per lead get pushed (best-only = top by seniority; role-based = only senior roles). dealPolicy ('one-per-lead' | 'one-per-company' | 'one-per-contact' | 'score-threshold' | 'none') controls deal creation strategy. dealScoreThreshold (default 70) is used when dealPolicy='score-threshold'. companyPolicy ('always' | 'only-if-new') skips company updates on existing companies when 'only-if-new'. associationDepth ('minimal' = no associations, 'standard' = Contact↔Company only, 'full' = adds Contact↔Deal + Company↔Deal). seniorityRoles (string array) overrides the default seniority keyword list for role-based contactPolicy. Each field is optional — defaults come from the mode preset."
          },
          "pushRules": {
            "title": "Push rules (if/then logic)",
            "maxItems": 50,
            "type": "array",
            "description": "Programmable per-lead rules evaluated in order. Each rule has 'if' (conditions: score / grade / emails.count / contacts.count / industry / domain) and 'then' (actions: skip with reason, override lifecycleStage / dealStage / createDeals / createCompanies / createContacts). Rules with skip:true halt evaluation for that lead. Useful for branching CRM behavior without external orchestration. Example: [{\"if\":{\"score\":{\"gte\":80}},\"then\":{\"lifecycleStage\":\"salesqualifiedlead\",\"createDeals\":true}},{\"if\":{\"emails\":{\"count\":{\"eq\":0}}},\"then\":{\"skip\":true,\"skipReason\":\"no_contacts\"}}]"
          },
          "qualityGate": {
            "title": "Quality gate (pre-push filter)",
            "type": "object",
            "description": "Prevent garbage leads from reaching HubSpot AND from being charged. Set any combination: requireEmail / requireDomain / requirePhone (booleans), minScore (number; lead.score must meet), minFields (number; at least N input fields populated), requireDecisionMaker (boolean; at least one contact with senior title). Failing leads are output as recordType:'skipped' with a skipReason — never billed."
          },
          "fieldOverrides": {
            "title": "Field overrides (custom HubSpot properties)",
            "type": "object",
            "description": "Remap default HubSpot property names before sending. Useful when your HubSpot account uses custom property names. Shape: {company: {industry: 'customIndustryField'}, contact: {jobtitle: 'role'}, deal: {dealname: 'opportunityName'}}. Only the specified keys are remapped; everything else is sent as-is."
          },
          "watchlistName": {
            "title": "Watchlist name (cross-run state)",
            "type": "string",
            "description": "Name a watchlist to enable cross-run state: skip leads already pushed in a prior run on the same watchlist (replayMode='skip'), and emit run-over-run delta on the summary record. Leave empty to disable. Each watchlist gets its own named KV store ('hubspot-lead-pusher-state-<name>') bounded at 50K eventIds."
          },
          "monitorStateKey": {
            "title": "Monitor state key (alias for watchlistName)",
            "type": "string",
            "description": "Suite-aligned alias for watchlistName. Either input works; if both are set, watchlistName wins. Lets the same upstream orchestrator pass one consistent field name across hubspot-lead-pusher, salesforce-lead-pusher, lead-scoring-engine, bulk-email-verifier, waterfall-contact-enrichment, phone-number-finder, company-deep-research, and lead-enrichment-pipeline."
          },
          "lastAction": {
            "title": "Last action (closes the feedback loop)",
            "type": "object",
            "description": "Optional. Tells the actor what action you took on this watchlist since the last run. On the next scheduled run, the actor compares the prior push outcome against the current one and emits decisionMemory with an inferred outcome. Honest: only push-result delta is observable — direct CRM-side activity (deal stage, contact engagement) is not. Shape: { type: 'pushed-batch' | 'manual-review' | string, takenAt: ISO date, note?: string }. Requires watchlistName / monitorStateKey."
          },
          "replayMode": {
            "title": "Replay mode",
            "enum": [
              "skip",
              "force"
            ],
            "type": "string",
            "description": "When watchlistName is set: 'skip' (default) skips leads whose eventId already appears in the watchlist's processed set — prevents accidental double-billing on re-runs. 'force' pushes regardless (useful for full refresh runs).",
            "default": "skip"
          },
          "safety": {
            "title": "Safety limits (hard caps + abort guards)",
            "type": "object",
            "description": "Hard caps that abort the run BEFORE any HubSpot writes if exceeded — protects against runaway input or upstream bugs. Set any combination: maxDealsPerRun (number; abort if planned deal count would exceed), maxCompaniesPerRun (number; same for companies), maxContactsPerCompany (number; cap contacts per domain), abortIfDuplicateRate (0-1; abort if input has more than this fraction of duplicate domains — likely upstream dedup issue), abortIfErrorRate (0-1; reserved for future error-rate-based abort). On abort, the actor pushes an error record and exits cleanly — no partial CRM writes."
          }
        }
      },
      "runsResponseSchema": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "actId": {
                "type": "string"
              },
              "userId": {
                "type": "string"
              },
              "startedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "finishedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "status": {
                "type": "string",
                "example": "READY"
              },
              "meta": {
                "type": "object",
                "properties": {
                  "origin": {
                    "type": "string",
                    "example": "API"
                  },
                  "userAgent": {
                    "type": "string"
                  }
                }
              },
              "stats": {
                "type": "object",
                "properties": {
                  "inputBodyLen": {
                    "type": "integer",
                    "example": 2000
                  },
                  "rebootCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "restartCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "resurrectCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "computeUnits": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "options": {
                "type": "object",
                "properties": {
                  "build": {
                    "type": "string",
                    "example": "latest"
                  },
                  "timeoutSecs": {
                    "type": "integer",
                    "example": 300
                  },
                  "memoryMbytes": {
                    "type": "integer",
                    "example": 1024
                  },
                  "diskMbytes": {
                    "type": "integer",
                    "example": 2048
                  }
                }
              },
              "buildId": {
                "type": "string"
              },
              "defaultKeyValueStoreId": {
                "type": "string"
              },
              "defaultDatasetId": {
                "type": "string"
              },
              "defaultRequestQueueId": {
                "type": "string"
              },
              "buildNumber": {
                "type": "string",
                "example": "1.0.0"
              },
              "containerUrl": {
                "type": "string"
              },
              "usage": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "integer",
                    "example": 1
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "usageTotalUsd": {
                "type": "number",
                "example": 0.00005
              },
              "usageUsd": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "number",
                    "example": 0.00005
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}