{
  "openapi": "3.0.1",
  "info": {
    "title": "SwitchSignal - Competitor Switching Intent Leads",
    "description": "Find public competitor pain signals, score switching intent, and output sales-ready contact candidates with evidence and outreach angles.",
    "version": "1.0",
    "x-build-id": "NPUteQl694dlSox9h"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/neoscala~switchsignal/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-neoscala-switchsignal",
        "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/neoscala~switchsignal/runs": {
      "post": {
        "operationId": "runs-sync-neoscala-switchsignal",
        "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/neoscala~switchsignal/run-sync": {
      "post": {
        "operationId": "run-sync-neoscala-switchsignal",
        "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",
        "required": [
          "competitorName",
          "productCategory",
          "yourProductDescription",
          "sources"
        ],
        "properties": {
          "competitorName": {
            "title": "Competitor name",
            "minLength": 2,
            "type": "string",
            "description": "The main competitor to monitor, for example Intercom, Zendesk, HubSpot, Salesforce, ClickUp, Monday, Notion, Mailchimp, or a Shopify app."
          },
          "competitorAliases": {
            "title": "Competitor aliases",
            "uniqueItems": true,
            "type": "array",
            "description": "Alternative spellings, domains, product names, or common ways people mention the competitor.",
            "items": {
              "type": "string"
            }
          },
          "productCategory": {
            "title": "Product category",
            "minLength": 2,
            "type": "string",
            "description": "The category your product competes in. This helps classify whether a complaint is commercially relevant."
          },
          "yourProductDescription": {
            "title": "Your product description",
            "minLength": 5,
            "type": "string",
            "description": "Short description of your product or positioning. Used to create more relevant outreach openers."
          },
          "sources": {
            "title": "Sources",
            "uniqueItems": true,
            "type": "array",
            "description": "Choose which sources SwitchSignal should search.",
            "items": {
              "type": "string",
              "enum": [
                "reddit",
                "hackerNews",
                "publicWebUrls"
              ],
              "enumTitles": [
                "Reddit",
                "Hacker News",
                "Specific public URLs"
              ]
            },
            "default": [
              "hackerNews"
            ]
          },
          "targetUrls": {
            "title": "Specific public URLs",
            "type": "array",
            "description": "Optional specific public URLs to crawl when the Specific public URLs source is selected. This is not an open-ended web crawler.",
            "items": {
              "type": "string"
            }
          },
          "publicUrlSnippets": {
            "title": "Specific public URL snippets or copied text",
            "type": "array",
            "description": "Optional copied page text or search-result snippets paired with targetUrls by position. If supplied, SwitchSignal scores the snippet even when the live page cannot be fetched.",
            "items": {
              "type": "string"
            }
          },
          "allowedDomains": {
            "title": "Allowed domains for public URL crawling",
            "uniqueItems": true,
            "type": "array",
            "description": "Optional domain allowlist for public URL crawling. Reddit and Hacker News are handled by their own collectors.",
            "items": {
              "type": "string"
            }
          },
          "maxPublicUrlBytes": {
            "title": "Maximum bytes per public URL",
            "minimum": 10000,
            "maximum": 1000000,
            "type": "integer",
            "description": "Safety limit for each fetched public page before text extraction.",
            "default": 250000
          },
          "daysBack": {
            "title": "Time window in days",
            "minimum": 1,
            "maximum": 365,
            "type": "integer",
            "description": "Only return posts from this many days back where a source provides dates.",
            "default": 90
          },
          "maxResults": {
            "title": "Maximum qualified results",
            "minimum": 1,
            "maximum": 500,
            "type": "integer",
            "description": "Maximum number of qualified switch signals to write to the dataset.",
            "default": 100
          },
          "maxItemsPerSource": {
            "title": "Maximum raw items per source",
            "minimum": 10,
            "maximum": 1000,
            "type": "integer",
            "description": "Safety limit before filtering and scoring.",
            "default": 150
          },
          "minIntentScore": {
            "title": "Minimum intent score",
            "minimum": 0,
            "maximum": 100,
            "type": "integer",
            "description": "Only output records with this score or higher.",
            "default": 60
          },
          "includeComments": {
            "title": "Include comments",
            "type": "boolean",
            "description": "When supported by the source, include comments as candidate signals, not only top-level posts.",
            "default": true
          },
          "maxCommentsPerThread": {
            "title": "Maximum comments per thread",
            "minimum": 0,
            "maximum": 100,
            "type": "integer",
            "description": "Limits how many comments we inspect from each thread.",
            "default": 25
          },
          "extractPublicContactEmails": {
            "title": "Extract visibly public email addresses",
            "type": "boolean",
            "description": "Disabled by default. When enabled, only extracts email addresses visibly present in the crawled public text. It does not verify, enrich, guess, or search for emails.",
            "default": false
          },
          "enableContactResearch": {
            "title": "Enable public contact research",
            "type": "boolean",
            "description": "Fetch lightweight public profile metadata where a supported source exposes it, for example Hacker News user profile about text and links. This does not verify identities or enrich private contact data.",
            "default": true
          },
          "maxProfilesToResearch": {
            "title": "Maximum public profiles to research",
            "minimum": 0,
            "maximum": 100,
            "type": "integer",
            "description": "Safety limit for source profile lookups such as Hacker News user profiles.",
            "default": 25
          },
          "enableAiEnrichment": {
            "title": "Enable AI enrichment",
            "type": "boolean",
            "description": "Use OpenAI to improve summaries, categories, evidence, confidence and outreach openers. If no API key is supplied, the Actor falls back to rules-only output.",
            "default": true
          },
          "aiProvider": {
            "title": "AI provider",
            "enum": [
              "openai",
              "none"
            ],
            "type": "string",
            "description": "AI provider for enrichment. Use OpenAI Platform for v1. Select Rules-only to disable external AI calls even if AI enrichment is enabled.",
            "default": "openai"
          },
          "openAiApiKey": {
            "title": "OpenAI API key",
            "type": "string",
            "description": "Optional OpenAI Platform API key. Use a project or service-account key from platform.openai.com, not an Azure AI Foundry key. Stored as a secret input field. If empty, the Actor uses rules-only mode unless OPENAI_API_KEY is set as a secret environment variable."
          },
          "aiModel": {
            "title": "AI model",
            "type": "string",
            "description": "OpenAI Platform model used for optional AI enrichment. For Apify Store v1, keep this as an OpenAI model name, not an Azure deployment name.",
            "default": "gpt-5.4-mini"
          },
          "redditMode": {
            "title": "Reddit mode",
            "enum": [
              "auto",
              "approvedApi",
              "userProvided",
              "searchIndex",
              "externalApifyActor"
            ],
            "type": "string",
            "description": "How the Reddit source should run. Auto uses approved API credentials if available, otherwise falls back to user-provided Reddit URLs/text when supplied. Search index and external Actor modes are explicit fallback/connector modes.",
            "default": "auto"
          },
          "redditClientId": {
            "title": "Reddit client ID",
            "type": "string",
            "description": "Optional Reddit API client ID. If empty, the Actor can read REDDIT_CLIENT_ID from environment variables."
          },
          "redditClientSecret": {
            "title": "Reddit client secret",
            "type": "string",
            "description": "Optional Reddit API client secret. If empty, the Actor can read REDDIT_CLIENT_SECRET from environment variables."
          },
          "redditUserAgent": {
            "title": "Reddit user agent",
            "type": "string",
            "description": "Optional Reddit API user agent, for example: nodejs:SwitchSignal:v1.0.0 (by /u/your_username)."
          },
          "allowRedditPublicJsonFallback": {
            "title": "Allow Reddit public JSON fallback",
            "type": "boolean",
            "description": "Disabled by default. This legacy unauthenticated mode is useful only for testing and can be blocked with HTTP 403. Do not rely on it for commercial runs.",
            "default": false
          },
          "redditSeedUrls": {
            "title": "Reddit seed URLs",
            "type": "array",
            "description": "Optional Reddit thread/comment URLs supplied by the user or another discovery process. Used by the user-provided and search-index fallback modes.",
            "items": {
              "type": "string"
            }
          },
          "redditSeedTexts": {
            "title": "Reddit seed texts or snippets",
            "type": "array",
            "description": "Optional copied Reddit post/comment text or search-result snippets. Items are paired with redditSeedUrls by position. This allows SwitchSignal to score Reddit discussions without direct Reddit API access.",
            "items": {
              "type": "string"
            }
          },
          "redditSearchIndexQueries": {
            "title": "Reddit search-index queries",
            "type": "array",
            "description": "Optional search-index queries such as site:reddit.com/r/ \"Intercom alternative\". SwitchSignal records these as diagnostics and can score supplied search-index result URLs/titles/snippets.",
            "items": {
              "type": "string"
            }
          },
          "redditSearchIndexResultUrls": {
            "title": "Reddit search-index result URLs",
            "type": "array",
            "description": "Optional Reddit result URLs discovered outside the Actor, for example from a search index query. Items are paired by position with result titles and snippets below.",
            "items": {
              "type": "string"
            }
          },
          "redditSearchIndexResultTitles": {
            "title": "Reddit search-index result titles",
            "type": "array",
            "description": "Optional titles for Reddit search-index results, paired by position with redditSearchIndexResultUrls.",
            "items": {
              "type": "string"
            }
          },
          "redditSearchIndexResultSnippets": {
            "title": "Reddit search-index result snippets",
            "type": "array",
            "description": "Optional snippets copied from search-index results, paired by position with redditSearchIndexResultUrls. This is scored without directly crawling Reddit.",
            "items": {
              "type": "string"
            }
          },
          "redditExternalActorId": {
            "title": "External Apify Reddit Actor ID",
            "type": "string",
            "description": "Optional. Future connector setting for calling a third-party or internal Reddit Actor. SwitchSignal validates the mode and warns if this is selected without a configured integration."
          },
          "redditExternalActorInputJson": {
            "title": "External Apify Reddit Actor input JSON",
            "type": "string",
            "description": "Optional JSON payload for a future external Reddit Actor connector. Leave empty unless the external Actor integration is configured."
          },
          "debugMode": {
            "title": "Debug mode",
            "type": "boolean",
            "description": "Write extra diagnostics to logs and the run summary. Do not enable for normal paid runs.",
            "default": false
          },
          "aiMaxSignals": {
            "title": "Maximum signals to enrich with AI",
            "minimum": 0,
            "maximum": 100,
            "type": "integer",
            "description": "Cost safeguard. Only the top N qualified signals are sent for AI enrichment.",
            "default": 25
          },
          "aiMinimumRulesScore": {
            "title": "Minimum rules score for AI enrichment",
            "minimum": 0,
            "maximum": 100,
            "type": "integer",
            "description": "Only qualified signals with at least this rules-based score are sent for AI enrichment.",
            "default": 60
          },
          "aiTimeoutMs": {
            "title": "AI request timeout in milliseconds",
            "minimum": 5000,
            "maximum": 120000,
            "type": "integer",
            "description": "Timeout per AI enrichment request.",
            "default": 30000
          },
          "aiMaxTextChars": {
            "title": "Maximum text characters sent to AI",
            "minimum": 500,
            "maximum": 8000,
            "type": "integer",
            "description": "Privacy and cost safeguard. Long posts are truncated before AI enrichment.",
            "default": 3500
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}