{
  "openapi": "3.0.1",
  "info": {
    "title": "Eluta.ca Jobs Scraper",
    "description": "Scrape eluta.ca — Canada's national job search engine — by keyword and city. Full descriptions, CAD salary min/max, employer website, NAICS code, HQ geo, Top-100 employer rating, and the real ATS apply link (not an eluta redirect). Incremental monitoring built in. JSON or CSV out.",
    "version": "0.0",
    "x-build-id": "cVOQyK48kQhJFpO0a"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/memo23~eluta-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-memo23-eluta-scraper",
        "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/memo23~eluta-scraper/runs": {
      "post": {
        "operationId": "runs-sync-memo23-eluta-scraper",
        "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/memo23~eluta-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-memo23-eluta-scraper",
        "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": {
          "query": {
            "title": "Search keywords",
            "type": "array",
            "description": "Job search keywords — each entry runs as its own eluta search. Eluta in-query qualifiers (e.g. `nurse sort:post`) are allowed.",
            "items": {
              "type": "string"
            }
          },
          "location": {
            "title": "Locations",
            "type": "array",
            "description": "City or region filters, e.g. `Toronto` or `Vancouver, BC`. Combined with every keyword. Leave empty to search all of Canada.",
            "items": {
              "type": "string"
            }
          },
          "sortBy": {
            "title": "Sort results by",
            "enum": [
              "relevance",
              "date",
              "popularity"
            ],
            "type": "string",
            "description": "Result ordering on the eluta side. `date` surfaces the newest postings first (recommended for monitoring), `relevance` is eluta's default ranking.",
            "default": "relevance"
          },
          "startUrls": {
            "title": "Eluta.ca URLs (optional)",
            "type": "array",
            "description": "Full eluta.ca URLs to crawl instead of (or in addition to) keyword searches. Supported: `/search?q=...`, SEO pages like `/Nurse-jobs-in-Toronto-ON`, employer pages like `/jobs-at-sunnybrook`, and direct job URLs (`/spl/...`).",
            "items": {
              "type": "string"
            }
          },
          "includeDetails": {
            "title": "Fetch full job details",
            "type": "boolean",
            "description": "Fetch each job's detail page for the full description (HTML + text), ISO posted/expiry dates, employment type, industry + NAICS code, employer website, logo, HQ address with latitude/longitude, and the Canada's-Top-100 employer rating. Disable for fast SERP-only rows.",
            "default": true
          },
          "resolveApplyUrls": {
            "title": "Resolve real apply URLs (employer ATS links)",
            "type": "boolean",
            "description": "Follow eluta's outbound redirect to capture the employer's real apply URL (e.g. `sunnybrook.talcura.com/...JobId=12800`) instead of just the eluta.ca job page. One extra lightweight request per job.",
            "default": true
          },
          "enrichEmails": {
            "title": "Enrich with employer contact emails (experimental, billed per email)",
            "type": "boolean",
            "description": "If enabled, tries to find a contact email for each hiring employer. The employer website usually comes straight from the job page's own metadata, and its contact/about pages are scanned for an email. Adds contactEmail + contactWebsite columns plus a detailed emailEnrichment object. Best-effort, billed per contact email found; only charged when an email is returned, never for misses.",
            "default": false
          },
          "qualifyByPayment": {
            "title": "💳 Qualify by payment (flag businesses that take money online)",
            "type": "boolean",
            "description": "Requires \"Enrich with contact emails\". Scans each employer's website — reusing the pages already fetched for email discovery, so no extra cost or time — for payment processors and e-commerce platforms (Stripe, Shopify, PayPal, Paddle, Lemon Squeezy, WooCommerce, Square, Chargebee and more). Adds takesPayments, paymentProcessors, stripeLiveKey and paymentConfidence. No extra charge — included with each enriched employer.",
            "default": false
          },
          "monitoringMode": {
            "title": "Monitoring mode (only return jobs not seen on previous runs)",
            "type": "boolean",
            "description": "When enabled, jobs whose eluta ID has already been delivered to you are silently skipped (no detail page is fetched and no charge applies for them). The first run after enabling monitoring returns every match — that builds your baseline. Every subsequent run returns only new postings. Combine with Apify's scheduler and `sortBy: date` for a 'jobs posted since last run' feed.",
            "default": false
          },
          "resetMonitoringState": {
            "title": "Reset monitoring state (one-shot)",
            "type": "boolean",
            "description": "One-shot toggle: clear the saved 'jobs already seen' record at the start of this run. Use this when you change search keywords, want to rebuild the baseline, or recover from a missed delivery. Has no effect when monitoring mode is off.",
            "default": false
          },
          "maxItems": {
            "title": "Maximum jobs to scrape",
            "minimum": 1,
            "type": "integer",
            "description": "Hard cap on the number of jobs collected across all searches. Use this to limit billing.",
            "default": 1000
          },
          "maxPagesPerSearch": {
            "title": "Max pages per search",
            "minimum": 1,
            "maximum": 100,
            "type": "integer",
            "description": "Stop paginating each search after this many result pages (~10 jobs per page). The walk also stops automatically when a page returns no new jobs.",
            "default": 20
          },
          "maxConcurrency": {
            "title": "Max concurrency",
            "minimum": 1,
            "type": "integer",
            "description": "Maximum number of job pages processed in parallel.",
            "default": 10
          },
          "minConcurrency": {
            "title": "Min concurrency",
            "minimum": 1,
            "type": "integer",
            "description": "Minimum number of job pages processed in parallel.",
            "default": 1
          },
          "maxRequestRetries": {
            "title": "Max request retries",
            "minimum": 0,
            "type": "integer",
            "description": "Number of retries before a failed request is given up.",
            "default": 5
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}