pii_list_detectors
List PII/secret detectors and pricing (free)
WHAT: Catalog of every PII and secret entity type, which ones the free tools run on this Worker (pii_scan_text / pii_redact_text) vs only in the paid Actor (NER names/locations, street addresses, URL/PDF documents), redaction styles, and the price of every paid tool in this server.
WHEN: Before pii_scan_text / pii_redact_text to pick entityTypes, or to explain coverage and costs to a user.
WHEN NOT: To actually scan text (pii_scan_text) or redact it (pii_redact_text).
COST: Free; no token.
RETURNS: One catalog object; local:true marks the detectors the free tools run (see PARAMETERS).
BEHAVIOR: Runs on this Fairquery-hosted Worker (Cloudflare), not on the caller's machine; inputs leave the client. This Worker's code is designed not to store inputs, results, or an Apify token. No further network call; the catalog is compiled into this Worker, instant (<10 ms). No rate limits.
PARAMETERS: None: call with an empty object {}; the catalog is always complete and cannot be filtered. Its output feeds other tools' parameters: copy detector "type" values verbatim into entityTypes of pii_scan_text / pii_redact_text (only rows with local:true can match there) or pii_guard_documents (all rows, incl. PERSON / LOCATION / STREET_ADDRESS); redaction_styles keys are the allowed redactionStyle values.
EXAMPLE: {} -> {"detectors":[{"type":"AWS_ACCESS_KEY","category":"secret","local":true},...]}
Takes no parameters.
pii_scan_text
Scan text for PII and secrets (free, on this Worker)
WHAT: Detect PII (emails, phones, US SSNs, Luhn-valid cards, mod-97 IBANs, UK NINOs, IPv4/IPv6) and secrets (AWS/GitHub/GitLab/Slack/Stripe/Google/OpenAI/Anthropic/HF/npm/SendGrid/Twilio/Azure keys, JWTs, private keys, URL credentials, key=value secrets) in text.
WHEN: Before sending prompts, tickets, logs or files to an LLM or third party; to audit text for leaked credentials. Findings are paged across all documents.
WHEN NOT: To get sanitized text use pii_redact_text. For person names/addresses (NER), public URLs or PDFs use pii_guard_documents (paid). Not for images (no OCR).
COST: Free. Regex and validators on this Worker; no APIFY_TOKEN.
RETURNS: Paged findings across all documents, each with a masked preview; raw values are never returned. Errors: INPUT_TOO_LARGE.
BEHAVIOR: Runs on this Fairquery-hosted Worker (Cloudflare), not on the caller's machine; inputs leave the client. This Worker's code is designed not to store inputs, results, or an Apify token. No further network call; the text is not forwarded to another service. Milliseconds.
PARAMETERS: texts: one array element per document; each finding carries doc_index = the element's 0-based position, and the 500,000-char cap applies to the SUM of all elements (over it -> INPUT_TOO_LARGE; split into several calls). entityTypes: filters findings after detection; names are case-insensitive, unknown names silently match nothing, and NER-only types (PERSON, LOCATION, STREET_ADDRESS) never match here. allowList: compared with the whole matched value, case-insensitively (allow "[email protected]", not "yourco.com"). entropyScan: only adds HIGH_ENTROPY_STRING findings; it never removes others. defaultPhoneRegion: affects only national-format numbers such as "030 1234567" (needs "DE"); "+49 ..." numbers parse with any region. limit/offset page the flat findings list across all documents, while meta.documents always summarises every document; fetch the next page with offset = nextOffset until hasMore is false.
EXAMPL
ParameterslimittextsrequiredoffsetallowListentityTypesentropyScandefaultPhoneRegion
pii_redact_text
Redact PII and secrets (free, on this Worker)
WHAT: Return sanitized copies of texts with every local PII/secret finding replaced (placeholder [EMAIL_1], mask, or salted hash).
WHEN: Right before sending user data to an LLM/third party. Use returnPlaceholderMap=true if you need to restore originals in the LLM answer later.
WHEN NOT: For a findings report only use pii_scan_text. For names/addresses NER, URLs or PDFs use pii_guard_documents (paid).
COST: Free; no token.
RETURNS: One "redacted_document" row per text with output_text; meta.placeholder_map only when requested. Errors: INPUT_TOO_LARGE.
BEHAVIOR: Same input gives the same output except redactionStyle "hash" (random per-call salt). Runs on this Fairquery-hosted Worker (Cloudflare), not on the caller's machine; inputs leave the client. This Worker's code is designed not to store inputs, results, or an Apify token. No further network call; texts are not forwarded. Milliseconds.
PARAMETERS: texts: one element per document, 500,000 chars in total; the same value gets the same placeholder in every document of one call ([EMAIL_1] everywhere), but numbering restarts on each call. redactionStyle: "placeholder" is the only reversible style; "mask" keeps a few characters for human review; "hash" output differs between calls (random salt), so do not compare hashes across calls. returnPlaceholderMap: only has an effect with redactionStyle="placeholder" (ignored for mask/hash); the map in meta.placeholder_map holds the ORIGINAL values, so keep it out of the LLM prompt and restore answers with pii_restore_text (free, on this Worker). entityTypes / allowList / entropyScan / defaultPhoneRegion: identical semantics to pii_scan_text (filter after detection, whole-value case-insensitive allow-list). limit/offset page whole documents (one item per text, default 10 per page), not findings.
EXAMPLE: {"texts":["Call +1 415 555 0100 or mail [email protected]"]} -> output_text "Call [PHONE_1] or mail [EMAIL_1]".
ParameterslimittextsrequiredoffsetallowListentityTypesentropyScanredactionStyledefaultPhoneRegionreturnPlaceholderMap
pii_restore_text
Restore placeholders with original values (free, on this Worker)
WHAT: Put the original values back into texts (typically an LLM answer) that contain placeholders such as [EMAIL_1], using the placeholder map from pii_redact_text or pii_guard_documents.
WHEN: After an LLM or third party answered a prompt you sanitized with pii_redact_text (redactionStyle "placeholder", returnPlaceholderMap=true), before showing the answer to the user.
WHEN NOT: To redact (pii_redact_text) or find PII (pii_scan_text). Masked and hashed values cannot be restored; only placeholder style is reversible.
COST: Free; no token.
RETURNS: One "restored_document" row per text with output_text, replacements and unknown_placeholders. Errors: INPUT_TOO_LARGE.
BEHAVIOR: Runs on this Fairquery-hosted Worker (Cloudflare), not on the caller's machine; inputs leave the client. This Worker's code is designed not to store inputs, results, or an Apify token. No further network call; the placeholder map is not forwarded. Milliseconds. Max 50 texts, 200,000 chars each, 500,000 total; map up to 10,000 entries.
PARAMETERS: placeholderMap: pass meta.placeholder_map unchanged; every key is replaced wherever it occurs exactly (case-sensitive, longest key first, one pass, so a restored value is never replaced again). unknown_placeholders lists [TYPE_N]-shaped tokens left in the text that the map does not contain (the LLM invented or altered them); they stay as they are. A placeholder the LLM rewrote (e.g. "EMAIL_1" without brackets) is not restored. The output contains the ORIGINAL sensitive values: show it to the user, do not send it back to the LLM. limit/offset page whole documents (default 10 per page).
EXAMPLE: {"texts":["I will email [EMAIL_1] today."],"placeholderMap":{"[EMAIL_1]":"[email protected]"}} -> output_text "I will email [email protected] today.", replacements 1.
ParameterslimittextsrequiredoffsetplaceholderMaprequired
pii_guard_documents
Deep PII/secret guard for documents and URLs (paid)
WHAT: Runs the Fairquery Apify Actor llm-data-guard-pii-secrets: everything pii_scan_text does PLUS person-name/location NER, street addresses, public document URLs (txt/md/json/csv/HTML/PDF text layer, <= 10 MB) and restore mode (put originals back into LLM output using a placeholder map).
WHEN: Only when you need NER names/addresses, files at URLs/PDFs, or the hosted pipeline.
WHEN NOT: Plain text scans (pii_scan_text / pii_redact_text, free), restoring placeholders in an LLM answer (pii_restore_text, free, same result as restore mode), images (no OCR), email deliverability.
COST: Paid, billed to YOUR Apify account via your APIFY_TOKEN: $1.50 per 1,000 documents + $0.20 per 1,000 findings. Example: 10 docs with 20 findings ~ $0.02.
RETURNS: Paged "document" rows (findings masked; output_text in redact/restore modes) or "error" rows. Tool errors: APIFY_TOKEN_MISSING, APIFY_TOKEN_INVALID, APIFY_PAYMENT_REQUIRED, APIFY_ACTOR_RUN_FAILED, APIFY_TIMEOUT, INPUT_EMPTY.
BEHAVIOR: Called from this Fairquery-hosted Worker, which forwards your input and Apify token to Apify and waits 20 s (APIFY_TIMEOUT if the run has not finished). This Worker's code is designed not to store them. The Actor runs in your Apify account and may fetch documentUrls. Up to 1000 texts / 100 URLs (10 MB each).
PARAMETERS: texts and/or documentUrls: at least one non-empty (the schema marks both optional; neither -> INPUT_EMPTY, not billed); both may be combined and each text or URL becomes one billed document row. mode="restore" ignores all detector flags; a placeholder missing from placeholderMap stays as is. Cost scales with documents and findings, so narrow entityTypes to cut finding charges. limit/offset only page the returned rows: every call processes and bills the whole input again (also when only offset changes), so pick a limit (max 1000) that covers all rows instead of paging.
EXAMPLE: {"documentUrls":["https://example.com/report.pdf"],"mode":"redact","detectNames":true}
ParametersmodelimittextsoffsetallowListdetectNamesentityTypesentropyScandocumentUrlsplaceholderMapredactionStyledetectAddresses+1 more
email_check_syntax
Check email syntax, typos, disposable & role (free)
WHAT: Offline email checks: RFC-style syntax + normalization, common domain typo "did you mean" (gmial.com -> gmail.com), disposable/temporary domain (bundled CC0 list, ~thousands of domains), role account (info@, sales@), free webmail provider.
WHEN: Fast pre-filtering of signups or lead lists, before paying for email_validate_deliverability.
WHEN NOT: Does NOT check DNS/MX, so it cannot tell whether the domain receives mail; use email_validate_deliverability (paid) for MX/SPF/DMARC.
COST: Free; no token.
RETURNS: Paged "email_check" rows; verdict is invalid | risky | unknown, never valid (dns_checked is always false).
BEHAVIOR: Runs on this Fairquery-hosted Worker (Cloudflare), not on the caller's machine; inputs leave the client. This Worker's code is designed not to store inputs, results, or an Apify token. No further network call (no DNS/SMTP); addresses are not forwarded. Synchronous and CPU-bound, no rate limits: 10,000 addresses (the per-call maximum) return in well under a second.
PARAMETERS: emails: each element is parsed on its own (one address per element; a comma-separated list in one element is INVALID_SYNTAX, not split). Before checking, "Name <addr>" is reduced to addr, a leading "mailto:" is dropped, the domain is lowercased (local part keeps its case), a trailing dot is removed and IDN domains are converted to punycode; the normalized value is returned as email, the original as input. Duplicates are not merged: every element yields one row, in input order. Role detection ignores +tags (sales+eu@ counts as sales@) and disposable matching also covers subdomains of listed domains. limit/offset page those rows; meta.summary always counts verdicts over ALL rows, not just the current page.
EXAMPLE: {"emails":["[email protected]"]} -> verdict "risky", reasons ["POSSIBLE_TYPO","DNS_NOT_CHECKED"], did_you_mean "[email protected]".
Parameterslimitemailsrequiredoffset
email_validate_deliverability
Validate email deliverability: MX, SPF, DMARC (paid)
WHAT: Runs the Fairquery Apify Actor email-validator-mx-disposable: syntax, domain existence, MX/null-MX, disposable, role, free provider, typo suggestion, SPF/DMARC policy, mail provider; final verdict valid | risky | invalid | unknown.
WHEN: Only when MX/DNS matters (can the domain receive mail?), e.g. cleaning lists before a send or verifying a lead's domain; pre-filter with email_check_syntax to avoid paying for obviously bad rows.
WHEN NOT: Offline format, typo, disposable or role checks (free email_check_syntax). Leads that also need sanctions screening: trust_screen_lead (one merged decision). It does not SMTP-probe mailboxes.
COST: Paid, billed to YOUR Apify account via your APIFY_TOKEN: $0.79 per 1,000 emails (+ $0.05 per 1,000 runs). 100 emails ~ $0.08.
RETURNS: Paged "email" rows (verdict valid | risky | invalid | unknown with reasons[]) or "error" rows. Tool errors: APIFY_TOKEN_MISSING, APIFY_TOKEN_INVALID, APIFY_PAYMENT_REQUIRED, APIFY_ACTOR_RUN_FAILED, APIFY_TIMEOUT.
BEHAVIOR: No email is sent; results change only with live DNS. Called from this Fairquery-hosted Worker, which forwards your input and Apify token to Apify and waits 20 s (APIFY_TIMEOUT if the run has not finished). This Worker's code is designed not to store them. The Actor in your account does the DNS/MX lookups.
PARAMETERS: emails: elements may also hold comma/semicolon/newline-separated lists or "Name <addr>" forms; the Actor splits them, trims, and skips case-insensitive duplicates, so you pay once per unique address. The allow* flags only decide whether a condition downgrades the verdict to "risky": the matching reason code (ROLE_ACCOUNT, DISPOSABLE_DOMAIN, FREE_PROVIDER) is reported in reasons[] either way, and they can never turn an "invalid" address (bad syntax, no domain, null MX, no mail server) into "valid". POSSIBLE_TYPO and IMPLICIT_MX_ONLY always make it "risky" regardless of flags. Typical presets: B2B lead list = allowFreeProviders false + allowRoleAccounts false; consumer
ParameterslimitemailsrequiredoffsetcheckSpfDmarcallowDisposableallowRoleAccountsallowFreeProviders
sanctions_list_sources
List covered sanctions lists (free)
WHAT: Static list of the official sanctions lists sanctions_screen_names checks (id, name, authority, download URL), the score scale and the legal disclaimer.
WHEN: To choose the lists parameter, cite sources in a report, or explain coverage before paying.
WHEN NOT: To screen a name (sanctions_screen_names, paid). It does not download lists or report freshness.
COST: Free; no token.
RETURNS: One static object, including the disclaimer to show with screening results.
BEHAVIOR: Runs on this Fairquery-hosted Worker (Cloudflare), not on the caller's machine; inputs leave the client. This Worker's code is designed not to store inputs, results, or an Apify token. No further network call; static catalog compiled into this Worker, instant. No rate limits.
PARAMETERS: None: call with an empty object {}; the result is static and cannot be filtered. Its output feeds sanctions_screen_names: each sources[].id (OFAC_SDN, OFAC_CONS, EU, UK, UN) is a valid value for its lists parameter, and score_scale explains how its minScore threshold is applied.
EXAMPLE: {} -> {"sources":[{"id":"OFAC_SDN","authority":"US Treasury OFAC",...},...]}
Takes no parameters.
sanctions_screen_names
Screen names against OFAC/EU/UK/UN sanctions (paid)
WHAT: Runs the Fairquery Apify Actor sanctions-watchlist-screener: fuzzy-match people/organisations against OFAC SDN, OFAC Consolidated, EU, UK and UN lists from the official sources (re-downloaded when the cached copy in your Apify account is older than 6 h; every row reports each list's publication date); optional country/DOB filters.
WHEN: KYC/KYB onboarding, vendor/counterparty checks, bulk re-screening. Put all names in ONE call (each call is one run with its own start fee; list loading takes ~2-5 s from the cache, or 10-40 s, up to ~60 s, when lists are re-downloaded). This Worker waits 20 s, so a re-download that runs longer returns APIFY_TIMEOUT.
WHEN NOT: PEP/adverse media, certified compliance decisions. For coverage info use free sanctions_list_sources. Leads that also have an email to validate: trust_screen_lead (one merged decision).
COST: Paid, billed to YOUR Apify account via your APIFY_TOKEN: $3.00 per 1,000 names + $7.00 per 1,000 runs. 200 names in one call ~ $0.61.
RETURNS: Paged "screening" rows (status potential_match | no_match, matches[] best first, lists_unavailable) or "error" rows. Tool errors: INPUT_EMPTY, APIFY_TOKEN_MISSING, APIFY_TOKEN_INVALID, APIFY_PAYMENT_REQUIRED, APIFY_ACTOR_RUN_FAILED, APIFY_TIMEOUT. Not a certified screening service. Automated fuzzy matching against public lists; false positives and misses are possible. Review every potential match manually and consult official sources/legal counsel before acting.
BEHAVIOR: Results are stable for a given list snapshot. Called from this Fairquery-hosted Worker, which forwards your input and Apify token to Apify and waits 20 s (APIFY_TIMEOUT if the run has not finished). This Worker's code is designed not to store them. The Actor runs in your account. Up to 10,000 names. A list re-download can outlast the 20 s wait.
PARAMETERS: names and/or queries: at least one non-empty (the schema marks both optional; neither -> INPUT_EMPTY, not billed). Both may be combined; every entry is bill
ParameterslimitlistsnamesoffsetqueriesminScoremaxMatchesPerName
osv_query_packages
Check package versions for known vulnerabilities (free, OSV.dev)
WHAT: Query the public OSV.dev database (api.osv.dev querybatch) for exact package versions; returns which are vulnerable and the advisory IDs.
WHEN: Quick "is lodash 4.17.20 vulnerable?" checks for up to 200 packages; then osv_get_vulnerability for details of specific IDs.
WHEN NOT: Parsing manifests/lockfiles, severity filtering, fixed/recommended versions in one shot -> osv_audit_dependencies (paid).
COST: Free; no token. Package names and versions leave the client, are received by this Worker, and are forwarded to api.osv.dev. Nothing is sent to Apify. This Worker's code is designed not to store inputs or results.
RETURNS: Paged "package" rows (vulnerable, vuln_ids) or per-entry INVALID_ECOSYSTEM "error" rows. Tool errors: OSV_FETCH_FAILED (retryable).
BEHAVIOR: Runs on this Fairquery-hosted Worker (Cloudflare), not on the caller's machine; inputs leave the client. This Worker's code is designed not to store inputs, results, or an Apify token. One HTTPS request to api.osv.dev (Google-run public API) for all packages; typically <2 s, 20 s timeout. Results change only when OSV publishes advisories.
PARAMETERS: packages: each entry is checked independently and returns exactly one row, in input order. An unknown ecosystem yields a per-entry INVALID_ECOSYSTEM error row while the other entries still run. A version range such as "^4.17.0" or ">=2" is not resolved and normally returns no vulnerabilities (a false "safe"), so pin versions from your lockfile first. Duplicate entries are queried and returned twice. limit/offset page the rows (all packages are sent to OSV in a single request); meta.vulnerable_count counts all packages, not only the page.
EXAMPLE: {"packages":[{"ecosystem":"npm","name":"lodash","version":"4.17.20"}]} -> vulnerable true, vuln_ids ["GHSA-35jh-r3h4-6jhm",...].
Parameterslimitoffsetpackagesrequired
osv_get_vulnerability
Get vulnerability advisory details (free, OSV.dev)
WHAT: Fetch full OSV records (summary, details, aliases, severity vectors, affected ranges, fixed versions, references) for advisory IDs from api.osv.dev.
WHEN: You have IDs (from osv_query_packages or a report) and need details or the fixed version.
WHEN NOT: To find which vulns affect a package version (osv_query_packages) or a whole manifest (osv_audit_dependencies, paid).
COST: Free; no token. Advisory IDs leave the client, are received by this Worker, and are forwarded to api.osv.dev. Nothing is sent to Apify. This Worker's code is designed not to store inputs or results.
RETURNS: Paged "vulnerability" rows with the raw OSV record fields, or "error" rows (VULN_NOT_FOUND | OSV_FETCH_FAILED, see PARAMETERS).
BEHAVIOR: Runs on this Fairquery-hosted Worker (Cloudflare), not on the caller's machine; inputs leave the client. This Worker's code is designed not to store inputs, results, or an Apify token. One HTTPS call per ID to api.osv.dev, in parallel; typically <2 s, 20 s timeout each.
PARAMETERS: ids: each ID is fetched separately and yields exactly one row in input order, so one bad ID never fails the others: an unknown ID returns a VULN_NOT_FOUND row (not retryable), a network/5xx problem an OSV_FETCH_FAILED row (retryable - retry just that ID). Prefer the ecosystem/GHSA IDs returned by osv_query_packages (vuln_ids); a CVE-... ID only resolves when OSV indexes that CVE as its own record, otherwise look up the GHSA alias. IDs are matched as given (no trimming of URLs or prefixes), and duplicates are fetched twice. limit/offset only page the returned rows; every call re-fetches all given IDs, so for a next page resend the same ids with offset = nextOffset.
EXAMPLE: {"ids":["GHSA-35jh-r3h4-6jhm"]} -> lodash command injection, fixed in 4.17.21.
Parametersidsrequiredlimitoffset
osv_audit_dependencies
Audit dependencies/manifests with fix recommendations (paid)
WHAT: Runs the Fairquery Apify Actor osv-dependency-vulnerability-check: parses package.json, package-lock.json (v1-v3), requirements.txt or go.mod (or a package list), checks OSV, and returns per-package max severity/CVSS, fixed versions, a recommended upgrade version and one row per vulnerability (deduped aliases).
WHEN: Only for manifests, severity filtering or fix recommendations: full project audits from a pasted manifest, CI-style reports; for a few exact versions use osv_query_packages (free).
WHEN NOT: Quick checks of a few exact versions (osv_query_packages, free) or one advisory (osv_get_vulnerability, free).
COST: Paid, billed to YOUR Apify account via your APIFY_TOKEN: $0.50 per 1,000 packages + $1.50 per 1,000 vulnerabilities found (+ $0.05 per 1,000 runs). Use minSeverity="HIGH" to cut vuln rows. lodash+django (2 pkgs, 41 vulns) ~ $0.06.
RETURNS: Paged rows type="package" (vulnerable, vuln_count, max_severity, fixed_versions, recommended_version), type="vulnerability" (id, cve_ids, severity, cvss_score, fixed_versions, osv_url) or type="error". Tool errors: INPUT_EMPTY, APIFY_TOKEN_MISSING, APIFY_TOKEN_INVALID, APIFY_PAYMENT_REQUIRED, APIFY_ACTOR_RUN_FAILED, APIFY_TIMEOUT.
BEHAVIOR: Called from this Fairquery-hosted Worker, which forwards your input and Apify token to Apify and waits 20 s (APIFY_TIMEOUT if the run has not finished). This Worker's code is designed not to store them. The Actor in your account queries OSV.dev. Up to 1000 packages or a 2,000,000-char manifest.
PARAMETERS: packages or manifestText = input (one required); manifestType = format, default auto-detect; minSeverity = only report at/above ALL|LOW|MEDIUM|HIGH|CRITICAL (default ALL); includeDevDependencies (default true); limit = page size (default 100, max 1000); offset = items to skip for paging (default 0).
EXAMPLE: {"manifestText":"django==3.2.0\nrequests==2.19.0","minSeverity":"HIGH"}
ParameterslimitoffsetpackagesminSeveritymanifestTextmanifestTypeincludeDevDependencies
trust_screen_lead
Screen leads: email deliverability + sanctions (paid)
WHAT: One call per batch of leads/counterparties: runs email_validate_deliverability on their emails and sanctions_screen_names on their person/company names IN PARALLEL, then merges results per lead with an overall decision: block (invalid email or sanctions potential_match), review (risky email), pass.
WHEN: Onboarding customers/vendors, qualifying inbound leads, CRM hygiene where both email quality and sanctions exposure matter.
WHEN NOT: Email only -> email_validate_deliverability; names only -> sanctions_screen_names (same per-item prices, no merge step). Free pre-filter first: email_check_syntax. Use this tool only when a lead needs both checks and one decision.
COST: Paid, billed to YOUR Apify account via your APIFY_TOKEN: $0.79 per 1,000 leads with email + $3.00 per 1,000 leads with name (= $3.79 per 1,000 full leads) + $7.00 per 1,000 calls for the sanctions run. 100 full leads ~ $0.39.
RETURNS: Paged "lead" rows (decision pass | review | block with reasons[]; sanctions_matches holds the top 3); meta.summary counts by decision. Partial failure: the affected check shows "unavailable" and meta.errors lists codes. Tool errors: INPUT_EMPTY, APIFY_TOKEN_MISSING.
BEHAVIOR: No email is sent. Called from this Fairquery-hosted Worker, which forwards your input and Apify token to Apify and waits 20 s (APIFY_TIMEOUT if the run has not finished). This Worker's code is designed not to store them. Runs the email and sanctions Apify Actors in parallel (2 runs per call) in your account. Sanctions lists come from a cache at most 6 h old, or are downloaded; a download can outlast the 20 s wait.
PARAMETERS: leads: each record needs email and/or name (if no lead has either -> INPUT_EMPTY, nothing billed); a lead with only an email skips sanctions (sanctions_status "not_checked") and one with only a name skips email (email_verdict "not_checked"), so a lead is billed for each check it gets (prices under COST), plus the per-call sanctions run fee when any lead has a name. Identic
ParametersleadsrequiredlimitoffsetminScoreallowFreeProviders
mcp_server_precheck
Pre-check an MCP server (free scan on this Worker)
WHAT: Pre-install check for one MCP server. Scans tool names, descriptions and parameter text you pass for injection phrasing, concealed characters, hidden markup and cross-server shadowing.
WHEN: Before installing or enabling an MCP server, once you have a tools/list result to pass as tools or toolsListJson.
WHEN NOT: For a dependency audit with no tool list, call osv_audit_dependencies. For a few exact versions, call osv_query_packages. This tool does not install, start or execute the package.
COST: The scan is free and runs on this Fairquery-hosted Worker (Cloudflare), not on the caller's machine; tool names and descriptions you send leave the client. This Worker's code is designed not to store them and does not forward them to Apify. path and packageName are refused (PATH_NOT_ALLOWED) because this Worker has no disk, so auditDependencies=true cannot read a manifest and does not start the OSV Actor. To audit a manifest, call osv_audit_dependencies (paid: $0.50 per 1,000 packages + $1.50 per 1,000 vulnerabilities found).
RETURNS: Paged "finding" rows (rule, severity, tool, field, evidence). If auditDependencies is true, one "dependency_audit" row with status no_manifest on this Worker (no disk). meta.risk_level is none, low, medium, high, critical or not_assessed. meta.shared_externally.tool_names_and_descriptions is always false, which means the scan does not forward that text to npm or Apify; the text is still received by this Worker. Errors: INPUT_EMPTY, INVALID_JSON, INVALID_PACKAGE_NAME, PATH_NOT_ALLOWED, INPUT_TOO_LARGE.
BEHAVIOR: Default auditDependencies=false: no further network call and no process spawn. Scans only tools or toolsListJson you pass. path and packageName return PATH_NOT_ALLOWED and nothing is read. This Worker has no disk, so it does not read package.json, lockfiles, manifest.json, or server.json, and it does not follow symlinks. auditDependencies=true does not call registry.npmjs.org or the OSV Actor from this Worker, because a manifest is
ParameterspathlimittoolsoffsetminSeveritypackageNametoolsListJsonauditDependenciesincludeDevDependencies
jobs_get_board
Get live jobs from one ATS board (free)
WHAT: Fetch every job currently published on ONE company board from its official public ATS API (Greenhouse, Lever or Ashby), from Personio's documented XML feed, from Pinpoint's documented postings.json, or from a named Gem job board, normalize it and filter it on this Worker.
WHEN: You know the board (ats + slug), e.g. from jobs_find_board or a careers-page link, and want its live openings now. For Personio, Pinpoint and Gem you already know the company account, subdomain or vanity.
WHEN NOT: One known job's full detail (jobs_get_job). Jobs in a place or by role across the starter list, without a company name (jobs_search_by_location). Do not ask the user for a company and do not call this tool or jobs_find_board first for that ask. Many companies at once, history (new/closed/reposted since last run), or careers-page discovery at scale: use jobs_search_companies (paid). Unknown Greenhouse/Lever/Ashby board: use jobs_find_board first. Personio, Pinpoint and Gem are never discovered. SmartRecruiters, LinkedIn, Workday, Workable, Recruitee and Rippling are not supported and never contacted.
BEHAVIOR: Runs on this Fairquery-hosted Worker (Cloudflare), not on the caller's machine; inputs leave the client. This Worker's code is designed not to store inputs or results. The slug is sent to the public ATS host in the requests below. Greenhouse, Lever and Ashby: one GET to the documented API host only (very large Greenhouse boards: a second, lighter GET). Personio: robots.txt, then GET https://{account}.jobs.personio.de/xml only; all Personio accounts share one lane, one at a time, at least 1.5 s apart. Pinpoint: that tenant's robots.txt, then GET https://{subdomain}.pinpointhq.com/postings.json only (not jobs.json, not /api/v1); each subdomain is its own lane, one at a time, at least 1 s apart. Gem: GET https://api.gem.com/job_board/v0/{vanity}/job_posts/ only (no API key, no POST /applications); every vanity shares one lane, one at a time, at least 1 s apart. Pinpoint and
ParametersatsrequiredslugrequiredlimitoffsetremotecountrieslocationslongOpenDaystitleExcludestitleIncludespostedWithinDaysincludeDescription
jobs_find_board
Find which ATS board a company uses (free)
WHAT: Resolve a company name, domain or careers/board URL to its public job board(s) on Greenhouse, Lever or Ashby. A Personio, Pinpoint or Gem URL (or personio:account, pinpoint:subdomain, gem:vanity) you already know is parsed on this Worker and not looked up.
WHEN: Before jobs_get_board when you only know the company ("Ramp", "sentry.io", "https://stripe.com/jobs") or you have a Personio, Pinpoint or Gem career URL.
WHEN NOT: The user asked for jobs in a place or by role and did not name a company. Call jobs_search_by_location. Do not ask them for a company and do not call this tool first. You already have ats + slug (call jobs_get_board). For many companies plus history use jobs_search_companies (paid). It cannot find Workday, Workable, Recruitee, Rippling or LinkedIn pages, and it does not discover Personio, Pinpoint or Gem boards.
BEHAVIOR: Runs on this Fairquery-hosted Worker (Cloudflare), not on the caller's machine; inputs leave the client. This Worker's code is designed not to store inputs or results. Parts of the input are sent to public ATS hosts or the company site, as the steps below describe. Order: board-URL parsing (including personio:{account}, pinpoint:{subdomain}, gem:{vanity} and their public board URLs, no network) -> verified starter list -> the company's own website (only for a domain/URL input; robots.txt respected, <= 3 pages, private/internal IPs refused; Personio, Pinpoint and Gem hosts are not crawled) -> at most 6 GETs against the Greenhouse, Lever and Ashby APIs with slug guesses. Personio, Pinpoint and Gem are never probed and a careers-page link to them is ignored. Stops at the first hit. Nothing is cached or stored. Rate limits: max 2 parallel requests per host, Lever spaced 1 s apart, 15 s timeout per GET; ATS API network errors and HTTP 5xx are retried at most twice with backoff (0.5-1.6 s). Any HTTP 403/429 (or an HTML block page from an ATS API) stops that host for the session (kill switch, never retried, also for the other free
Parameterscompanyrequired
jobs_check_open
Re-check whether one job is still published (free)
WHAT: Re-check ONE job on the employer's ATS right now and report open or closed.
WHEN: Before applying, alerting or contacting about a specific job you got earlier (job_key or ats + slug + jobId), when you only need open or closed.
WHEN NOT: One job's full detail (jobs_get_job). Listing a board (jobs_get_board). Checking many jobs at once (jobs_search_companies with confirmOpen, paid).
BEHAVIOR: Runs on this Fairquery-hosted Worker (Cloudflare), not on the caller's machine; inputs leave the client. This Worker's code is designed not to store inputs or results. The job id and board slug are sent to the public ATS host in the requests below. Greenhouse, Lever: one GET to the documented per-job endpoint; HTTP 404 = closed. Ashby, Personio, Pinpoint and Gem have no per-job read here, so the documented board feed is fetched once and searched for the id (method "board_listing"). Personio is robots.txt then /xml. Pinpoint is robots.txt then /postings.json. Gem is GET /job_posts/ only. No apply URL is requested. "open" means currently published by the employer; it does not prove the role is still being filled.
COST: No APIFY_TOKEN, no billing.
RETURNS: One "open_check" row (job = the full "job" row when includeDescription=true and the job is open, else null), or a tool error: INVALID_INPUT, BOARD_NOT_FOUND, HOST_BLOCKED or NETWORK_ERROR (the last two retryable).
PARAMETERS: A malformed jobKey, or neither jobKey nor a complete ats + slug + jobId, returns INVALID_INPUT without a request. An Ashby, Personio, Pinpoint or Gem id costs one full board download; on Greenhouse and Lever a 404 triggers one extra board request so a closed job (status closed) is told apart from a missing board (BOARD_NOT_FOUND). includeDescription adds no request on Greenhouse and Lever and makes the Ashby or Personio board download include descriptions. Pinpoint and Gem description_text stay empty (the row links out). description_text is plain text, <= 20,000 chars, e-mails/phones removed, exactly as
ParametersatsslugjobIdjobKeyincludeDescription
jobs_get_job
Get one published job's full detail (free)
WHAT: Fetch the full detail of ONE job that is currently published on its official public ATS API (Greenhouse, Lever or Ashby), a Personio or Pinpoint feed, or a named Gem job board, normalized the same way as a board listing.
WHEN: You already have a job_key, or ats + slug + jobId, from jobs_get_board or a board link and need that single job's text, location, compensation and dates. On Gem the row links to jobs.gem.com and does not include the ad body.
WHEN NOT: Open or closed only (jobs_check_open). Every opening on a board (jobs_get_board). Jobs in a place across the starter list with no company name (jobs_search_by_location). Many companies, history or repost signals (jobs_search_companies, paid). SmartRecruiters, LinkedIn, Workday, Workable, Recruitee and Rippling are not supported and never contacted.
BEHAVIOR: Runs on this Fairquery-hosted Worker (Cloudflare), not on the caller's machine; inputs leave the client. This Worker's code is designed not to store inputs or results. The job id and board slug are sent to the public ATS host in the requests below. Greenhouse and Lever: one GET to the documented per-job endpoint (the description is in that response). Ashby, Personio, Pinpoint and Gem have no per-job read here: the documented board feed is fetched once and the id is looked up. Personio is robots.txt then /xml. Pinpoint is robots.txt then /postings.json. Gem is GET /job_posts/ only. Pinpoint and Gem description_text stay empty. No apply URL is requested. HTTP 404/410 on Greenhouse or Lever, when the board itself exists, or an id missing from an Ashby, Personio, Pinpoint or Gem board, is JOB_CLOSED (closed or unknown id) with no partial row. Nothing is stored. Any HTTP 403/429 stops that host for the session (kill switch, HOST_BLOCKED). Lever requests are spaced 1 s apart. Personio accounts share one lane, at least 1.5 s apart. Each Pinpoint subdomain is at least 1 s apart. Gem vanities share one lane, at least 1 s apart.
COST: No APIFY_TOKEN, no billing.
ParametersatsslugjobIdjobKey
jobs_list_seed_boards
List the verified starter boards (free, offline)
WHAT: List the bundled starter list of company job boards that Fairquery verified on their official ATS APIs (company, domain, ats, slug, verified_at, jobs_at_verification).
WHEN: To pick companies to scan, or to know which names jobs_find_board resolves instantly.
WHEN NOT: Live jobs on one board (jobs_get_board), a place search across this list (jobs_search_by_location), or companies not in the list (jobs_find_board). The list is a starting point, not a global index of employers.
BEHAVIOR: Runs on this Fairquery-hosted Worker (Cloudflare), not on the caller's machine; inputs leave the client. This Worker's code is designed not to store inputs or results. No further network call: it reads a static list compiled into this Worker. jobs_at_verification is a snapshot from verified_at and goes stale.
COST: No APIFY_TOKEN, no billing.
RETURNS: Paged "seed_board" rows in the fixed bundled order (original boards stay first, so earlier offsets stay put). 135 Greenhouse, Lever and Ashby boards.
PARAMETERS: ats narrows the list; omit it for the whole starter list (Greenhouse, Lever, Ashby). Personio, Pinpoint and Gem are not in the starter list (named accounts only). meta.by_ats always counts the whole list per ATS and ignores ats, so take paging totals from total. Feed ats + slug of any item straight into jobs_get_board.
EXAMPLE: {"ats":"lever"} -> Palantir, Spotify, Zoox, Ro, then more Lever boards.
Parametersatslimitoffset
jobs_search_by_location
Search the starter list by place and role (free, not every employer)
WHAT: Free search of the bundled starter list (135 public Greenhouse, Lever and Ashby boards). Not every employer and not every company. No company name. Live jobs from each board's official public API. Same normalized "job" rows as jobs_get_board. One call may cover only part of the list.
WHEN: The user asks for jobs by place and/or role and does not name a company. Call THIS tool immediately. Do not ask the user for a company. Do not call jobs_get_board or jobs_find_board first. Examples: "avionics jobs in Baltimore MD", "avionics jobs in Costa Mesa", "remote RN jobs in PA", "nursing jobs in Maryland". Put the place in locations (Baltimore, Baltimore MD, MD, Maryland, BWI, PA, Costa Mesa) or countries, or set remote to "only". Put a skill or role that may not be the job title in descriptionIncludes (avionics, nurse), not in titleIncludes.
WHEN NOT: The user already named one company or board (jobs_find_board, then jobs_get_board). They want history, closed jobs, reposts, or employers outside this starter list (jobs_search_companies, paid). This tool does not search all companies.
BEHAVIOR: Runs on this Fairquery-hosted Worker (Cloudflare), not on the caller's machine; inputs leave the client. This Worker's code is designed not to store inputs or results. Each starter-list board slug is sent to its public ATS host. Requires a place signal or it returns INVALID_INPUT and does not fetch: a non-empty locations list, a non-empty countries list, or remote "only". Reads starter boards with the same client, kill switch and rate limits as the other free tools (at most 2 requests in flight per host, Lever spaced 1 s apart, up to 4 boards at a time). A board GET that fails before any job is read (network error, timeout, or HTTP 5xx) is retried once after about 300 ms and that retry is named in meta.notes. HTTP 403 and 429 are not retried. A second failure is skipped and named in meta.notes. The retry is skipped when the CPU budget, the wall clock, or the request cap is alrea
ParameterslimitoffsetremotecountrieslocationstitleRegexboardCursorlongOpenDaystitleExcludestitleIncludespostedWithinDaysincludeDescription+1 more
jobs_search_companies
Search and monitor jobs across many companies (paid Apify Actor)
WHAT: Run the Fairquery Apify Actor fairquery/company-jobs-feed over many companies or boards: board discovery for Greenhouse, Lever and Ashby, a Personio, Pinpoint or Gem feed when you name it, search filters, per-board history (first_seen/last_seen, new/updated/closed, repost detection), optional per-job re-checks and descriptions.
WHEN: Monitoring a company list ("what is new since yesterday?"), searching the verified starter list, or anything that needs history, closed/repost signals or more than a few boards.
WHEN NOT: One board right now (jobs_get_board). A place or role search of the starter list with no company name and no history (jobs_search_by_location — call that first; do not ask for a company). One job's full detail (jobs_get_job), or one open/closed re-check (jobs_check_open).
BEHAVIOR: Read-only on job sites; requires APIFY_TOKEN. Called from this Fairquery-hosted Worker, which forwards your input and token to Apify and waits 20 s (APIFY_TIMEOUT if the run has not finished). The Actor runs in YOUR Apify account; history is kept in a named key-value store there. This Worker's code is designed not to store the input or token. Same politeness rules as the free jobs tools: documented ATS APIs only, Personio only at https://{account}.jobs.personio.de/xml after robots.txt, Pinpoint only at https://{subdomain}.pinpointhq.com/postings.json after robots.txt, Gem only at https://api.gem.com/job_board/v0/{vanity}/job_posts/ with no API key, 403/429 kill switch, robots.txt on careers pages. Personio, Pinpoint and Gem are not discovered. Pinpoint and Gem rows link out and do not copy the ad body. Output is that run's rows, not a public jobs directory.
COST: Paid, pay-per-event, billed to your Apify account: $0.99 per 1,000 jobs + $0.50 per 1,000 boards, plus optional $0.29 per 1,000 re-checks (confirmOpen) and $1.90 per 1,000 discovered companies; no start fee. Error, closed and merged rows are free. Example: 3 boards, 300 jobs = about $0.30.
RETURNS: Paged datas
ParameterslimitboardsoffsetremotemaxJobsonlyNewcompaniescountrieslocationsconfirmOpendepartmentsuseSeedList+6 more