{
  "openapi": "3.0.1",
  "info": {
    "title": "CharityJob Scraper — UK Charity Jobs, Volunteers & Leads",
    "description": "$1 per 1,000 jobs, $0 to start. Scrape CharityJob.co.uk paid AND volunteer roles by keyword, location, cause, salary, workplace and date posted, then add each charity's own website, LinkedIn, HQ and open-role counts. Saved-search monitor with Slack/webhook alerts. No login, no API key.",
    "version": "0.1",
    "x-build-id": "JXVjcgREkaTQYRJFS"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/scrapersdelight~charityjob-uk-jobs-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-scrapersdelight-charityjob-uk-jobs-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/scrapersdelight~charityjob-uk-jobs-scraper/runs": {
      "post": {
        "operationId": "runs-sync-scrapersdelight-charityjob-uk-jobs-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/scrapersdelight~charityjob-uk-jobs-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-scrapersdelight-charityjob-uk-jobs-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": {
          "startUrls": {
            "title": "Start URLs (optional)",
            "type": "array",
            "description": "Paste any CharityJob search URL (https://www.charityjob.co.uk/jobs?keywords=fundraising&location=london) or any single job URL (https://www.charityjob.co.uk/jobs/org/role/1082796). A pasted URL's own querystring IS the filter set — the fields below are merged in only where the URL is silent, so your URL always wins. Leave empty to build the search from the fields below.",
            "default": [],
            "items": {
              "type": "object",
              "required": [
                "url"
              ],
              "properties": {
                "url": {
                  "type": "string",
                  "title": "URL of a web page",
                  "format": "uri"
                }
              }
            }
          },
          "jobType": {
            "title": "Job type",
            "enum": [
              "paid",
              "volunteer",
              "both"
            ],
            "type": "string",
            "description": "Which of the site's two corpora to crawl. 'paid' = /jobs. 'volunteer' = /volunteer-jobs — the same search grammar and the same fields. 'both' crawls each in turn. Measured on the live site 2026-09-05 (run NI8sMc1CRWmghfm1l): 1,652 live paid adverts, 1,622 volunteer. The Actor logs the site's own counter every run, so you always see today's figure.",
            "default": "paid"
          },
          "keywords": {
            "title": "Keywords",
            "type": "string",
            "description": "Free-text search across job titles and descriptions, e.g. 'fundraising', 'database manager', 'trusts and foundations'. Maps to the site's own ?keywords= parameter.",
            "default": ""
          },
          "location": {
            "title": "Location",
            "type": "string",
            "description": "Town, city or postcode, e.g. 'london', 'manchester', 'BS1'. Maps to ?location= and is combined with the radius below.",
            "default": ""
          },
          "radius": {
            "title": "Search radius (miles)",
            "enum": [
              "1",
              "3",
              "5",
              "10",
              "20",
              "40",
              "80"
            ],
            "type": "string",
            "description": "Distance around the location. Only these radii exist on the site; anything else is rounded down. Ignored when no location is set.",
            "default": "20"
          },
          "cause": {
            "title": "Causes",
            "type": "array",
            "description": "Charity cause areas, repeatable — selecting several returns the union. These are the site's own 21 cause slugs.",
            "items": {
              "type": "string",
              "enum": [
                "animal",
                "arts-culture-heritage",
                "charity-support",
                "community",
                "disability",
                "dei",
                "education",
                "elderly",
                "environment",
                "faith-based",
                "health",
                "housing-and-homelessness",
                "human-rights",
                "international-development",
                "justice",
                "membership",
                "mental-health",
                "research",
                "social-welfare",
                "sport",
                "youth-and-children"
              ],
              "enumTitles": [
                "Animal",
                "Arts, culture & heritage",
                "Charity support",
                "Community development",
                "Disability",
                "Equity, diversity & inclusion",
                "Education",
                "Elderly / older people",
                "Environment",
                "Faith-based",
                "Health & medical",
                "Housing & homelessness",
                "Human rights",
                "International development",
                "Justice",
                "Membership",
                "Mental health",
                "Research",
                "Social welfare",
                "Sport",
                "Youth & children"
              ]
            },
            "default": []
          },
          "contractType": {
            "title": "Contract types",
            "type": "array",
            "description": "Repeatable contract filter. Maps to the site's ?contracttype= parameter.",
            "items": {
              "type": "string",
              "enum": [
                "full-time",
                "part-time",
                "permanent",
                "contract",
                "temporary",
                "internship"
              ],
              "enumTitles": [
                "Full-time",
                "Part-time",
                "Permanent",
                "Contract",
                "Temporary",
                "Internship"
              ]
            },
            "default": []
          },
          "workplace": {
            "title": "Workplace",
            "type": "array",
            "description": "On-site, hybrid or remote. Repeatable. Maps to ?workplace=.",
            "items": {
              "type": "string",
              "enum": [
                "on-site",
                "hybrid",
                "remote"
              ],
              "enumTitles": [
                "On-site",
                "Hybrid",
                "Remote"
              ]
            },
            "default": []
          },
          "minSalary": {
            "title": "Minimum salary (GBP / year)",
            "minimum": 0,
            "type": "integer",
            "description": "Only roles advertised at or above this annual salary. Maps to ?minsalary=. Note that a salary filter drops every advert with no stated salary."
          },
          "maxSalary": {
            "title": "Maximum salary (GBP / year)",
            "minimum": 0,
            "type": "integer",
            "description": "Only roles advertised at or below this annual salary. Maps to ?maxsalary=."
          },
          "postedWithinDays": {
            "title": "Posted within",
            "enum": [
              "0",
              "1",
              "3",
              "7",
              "14"
            ],
            "type": "string",
            "description": "Only adverts listed in the last N days — the key filter for a monitoring run. Measured on the live site 2026-09-05: 3 days = 351 paid adverts (run iRVhHbCIbbauu1d1v), 7 days = 686 (yrqe2Ct8glpQWnfAm), 14 days = 1,225 (2SpeTyiXZmG1JtMKe). The 1-day bucket is calendar-today, so it reads low late in the UTC day — 27 at 23:00 UTC (zekT3x2hm9N41d6wB).",
            "default": "0"
          },
          "sortBy": {
            "title": "Sort by",
            "enum": [
              "latest",
              "closing"
            ],
            "type": "string",
            "description": "Result order. 'latest' is the site default (newest first) and is what makes contiguous pagination stable; 'closing' sorts by closing date.",
            "default": "latest"
          },
          "entryLevelOnly": {
            "title": "Entry-level roles only",
            "type": "boolean",
            "description": "Only roles flagged entry level. Maps to ?joblevel=entry_level.",
            "default": false
          },
          "applyNowOnly": {
            "title": "Apply-on-CharityJob roles only",
            "type": "boolean",
            "description": "Exclude adverts that redirect to an external recruiter ATS. Maps to ?applytype=online.",
            "default": false
          },
          "hideAgencies": {
            "title": "Direct charity employers only (hide recruitment agencies)",
            "type": "boolean",
            "description": "Exclude recruitment agencies so every row is a charity you can actually sell to. Maps to ?employerType=direct-employer.",
            "default": false
          },
          "excludeTopJobs": {
            "title": "Exclude paid 'Top job' promos",
            "type": "boolean",
            "description": "CharityJob injects sponsored 'Top job' adverts into EVERY result set regardless of your filters — a 'Remote' promo shows up under location=london. Turn this on to drop them, at the cost of a few genuinely matching sponsored roles.",
            "default": false
          },
          "excludeExpired": {
            "title": "Exclude expired / not-yet-live adverts",
            "type": "boolean",
            "description": "Drop rows the site marks is-expired-job or is-future-job.",
            "default": true
          },
          "maxItems": {
            "title": "Max jobs",
            "minimum": 0,
            "type": "integer",
            "description": "Hard cap on rows returned — this is also your billing cap, since you are charged per row delivered. Set 0 for no cap (measured 2026-09-05, run NI8sMc1CRWmghfm1l: the whole paid corpus is 1,652 rows, volunteer 1,622 — 3,274 for jobType 'both').",
            "default": 100
          },
          "maxPages": {
            "title": "Max pages per search",
            "minimum": 0,
            "type": "integer",
            "description": "Alternative cap, in pages of 15 results. 0 = no page cap. Whichever of maxItems / maxPages is reached first stops the crawl.",
            "default": 0
          },
          "enrichOrganisation": {
            "title": "Enrich with the charity's profile (website, LinkedIn, HQ)",
            "type": "boolean",
            "description": "Fetch /organisation/<slug> for each charity to add its own website URL, LinkedIn / Facebook / X / YouTube / Instagram / TikTok, HQ postcode, mission, about text and current open-role counts. Each charity is fetched — and billed — ONCE per run, even when it has ten adverts in your result set.",
            "default": true
          },
          "enrichStructuredSalary": {
            "title": "Enrich with numeric salary + ISO dates",
            "type": "boolean",
            "description": "Fetch each job page for its schema.org JobPosting block: numeric salaryMin / salaryMax / currency / period, ISO datePosted and validThrough, the employmentType enum and every listed locality. Off by default because it costs one extra request per job.",
            "default": false
          },
          "includeDescriptionHtml": {
            "title": "Include the raw HTML description",
            "type": "boolean",
            "description": "Add descriptionHtml alongside the plain-text description. Off by default because it roughly triples the size of each row.",
            "default": false
          },
          "outputShape": {
            "title": "Output shape",
            "enum": [
              "full",
              "lead"
            ],
            "type": "string",
            "description": "'full' returns every field (62 columns). 'lead' returns 23 of those SAME fields under the SAME names — the compact charity-centric row a CRM import wants: organisation, charityWebsiteUrl, linkedinUrl, organisationType/Size, orgHeadquarters, open-role counts, title, salary, locationName, workplace, causes, closingDate, URLs. Both dataset views work in either shape. Two of the 23, salaryMin and salaryMax, fill only when enrichStructuredSalary is on: run 2aP61qySUDcGNCYES (2026-09-05, shipped defaults) returned 0 of 10, salaryRaw 10 of 10.",
            "default": "full"
          },
          "deduplicateBy": {
            "title": "Deduplicate by",
            "enum": [
              "jobId",
              "none"
            ],
            "type": "string",
            "description": "'jobId' collapses the same advert appearing twice (sponsored 'Top job' promos repeat across pages) so you are never charged twice for one job. 'none' returns the raw stream.",
            "default": "jobId"
          },
          "monitorMode": {
            "title": "Monitor mode — return only jobs new since the last run",
            "type": "boolean",
            "description": "Remembers every job ID it has already returned for this exact search (in a named key-value store that survives between runs) and outputs only the new ones. Pair it with a schedule and postedWithinDays to watch a niche. Billed as one monitor-run-completed plus new-job-detected per new advert, on top of the per-row charge.",
            "default": false
          },
          "alertOnNewJob": {
            "title": "Send an alert for each new job",
            "type": "boolean",
            "description": "Only applies in monitor mode. Alerts are free — there is no alert charge event.",
            "default": true
          },
          "webhookUrl": {
            "title": "Webhook URL",
            "type": "string",
            "description": "POST a JSON payload for each new job found in monitor mode.",
            "default": ""
          },
          "slackWebhookUrl": {
            "title": "Slack incoming-webhook URL",
            "type": "string",
            "description": "POST a formatted Slack card for each new job found in monitor mode."
          },
          "emailRecipients": {
            "title": "Email recipients",
            "type": "array",
            "description": "Email addresses to notify (via apify/send-mail) when monitor mode finds new jobs.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "proxyConfiguration": {
            "title": "Proxy configuration",
            "type": "object",
            "description": "MEASURED: an Apify DATACENTER proxy is sufficient — 97.5% clean on 40 sequential requests, with zero blocks from the site itself. Residential is not needed, but you can pin it here (apifyProxyGroups: ['RESIDENTIAL'], countryCode: 'GB') if you prefer.",
            "default": {
              "useApifyProxy": true
            }
          },
          "maxConcurrency": {
            "title": "Max concurrent requests",
            "minimum": 1,
            "maximum": 10,
            "type": "integer",
            "description": "MEASURED on the live site: 5 concurrent -> 10/10 clean, 10 concurrent -> 19/20. 5 is the recommended setting.",
            "default": 5
          },
          "maxRequestRetries": {
            "title": "Max retries per request",
            "minimum": 1,
            "maximum": 8,
            "type": "integer",
            "description": "Each retry uses a fresh proxy exit IP. The only failures observed on this target were Apify-proxy-side 595 ECONNRESET transients, which 3 retries absorb entirely.",
            "default": 3
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}