MCP HeartbeatTHE MCP OBSERVATORY
Public workspace

Explore

Evidence for your next connection.

Independent measurements of remote MCP servers. Every observation has a timestamp.

Read-only probes

MCP server · Communication & messaging

Fairquery Agent Trust & Data Safety

PII/secret redaction, email checks, sanctions screening, OSV lookups and an MCP server pre-check.

Checks passed
13 / 22

1 failed · 8 not measured

Median response
128 ms

Median of successful probes over 7 days

30-day uptime
Not measured

Share of countable probes over 30 days, including daily rollups. Auth challenges are excluded.

Discovered tools
21

Tool definitions returned by this server

Independent monitoring

Health & checks

Status history

Responded

The server completed its last measured handshake. This is an observation, not a guarantee.

Last checked
Check summary by test group
Test areaPassedFailedUnmeasured
ConnectionCan a client connect and discover tools?
500
Reliability & speedDoes it respond consistently and quickly?
004
Access & authenticationWhat is required to use this server?
102
Tool qualityAre the tool definitions usable by an agent?
400
Publisher identityCan the publisher be traced to its source?
312

Unmeasured means there is not enough evidence to decide. How these checks work

Inspect individual checks 22 recorded

Core

  • Pass
    Reachable

    Latest probe returned HTTP 200 in 128 ms.

  • Pass
    Valid handshake

    protocolVersion 2025-11-25, serverInfo.name fairquery.

  • Pass
    Lists tools

    tools/list returned 21 tools.

  • Pass
    Current protocol

    Negotiated 2025-11-25. The bar is 2025-06-18 or newer.

  • Pass
    HTTPS

    The endpoint URL is https.

Performance

  • Not measured
    Fast (p50)

    Median latency 128 ms over 1 samples in 7 days. The bar is 1000 ms. Need at least 5 samples.

  • Not measured
    Consistent (p95)

    95th percentile 128 ms over 1 samples in 7 days. The bar is 3000 ms. Need at least 20 samples.

  • Not measured
    Reliable (uptime)

    1 of 1 attempts returned a tool list in 30 days (100%). The bar is 99%. Need at least 30 samples.

  • Not measured
    Stable tool list

    Fewer than two successful probes in 30 days, so tool-list stability is not measured.

Access

  • Pass
    Open access

    tools/list succeeded with no credential, and the record declares none.

  • Not measured
    Standard auth

    Auth is not required, so the OAuth metadata check does not apply.

  • Not measured
    Free tier cited

    No publisher quote has been checked.

Tools

  • Pass
    Tools described

    Every tool description is at least 20 characters.

  • Pass
    Valid input schemas

    Every inputSchema is a JSON Schema object.

  • Pass
    Parameters documented

    184 of 184 parameters have a description (100%). The bar is 80%.

  • Pass
    Safety hints

    Every tool sets readOnlyHint or destructiveHint.

Publisher

  • Pass
    Verified namespace

    Listed in the Official MCP Registry.

  • Pass
    Website matches publisher

    The website host matches the reverse-domain namespace.

  • Fail
    Source repo linked

    No repository URL is on file.

  • Not measured
    Repo owner matches

    This namespace is not an io.github login, so the owner comparison does not apply.

  • Pass
    Recently updated

    Updated 2026-10-26T23:26:48.302011Z, within 180 days.

  • Not measured
    Open-source licence

    No GitHub repository to ask about a licence.

Start using Fairquery Agent Trust & Data Safety

Connect to this server

Choose your client, copy the configuration, then enable the server in your client’s MCP settings.

Run this command in your terminal, then restart Claude Code.

Claude Code

claude mcp add --transport http fairquery-agent-trust-data-safety https://mcp.getfairquery.com/mcp

Capabilities

Tools 21

email_check_syntax

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":["someone@gmial.com"]} -> verdict "risky", reasons ["POSSIBLE_TYPO","DNS_NOT_CHECKED"], did_you_mean "someone@gmail.com".

Discovered
email_validate_deliverability

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 signups = defaults. checkSpfDmarc only adds has_spf / has_dmarc / dmarc_policy fields; it never changes the verdict or the price. limit/offset only page the returned rows: every call validates and bills the whole list again (also when only offset changes), so set limit (max 1000) to cover all rows instead of paging. EXAMPLE: {"emails":["john@stripe.com"]} -> verdict "valid", has_mx true, mail_provider "Google Workspace / Gmail".

Discovered
jobs_check_open

Indexed Jobs search is LIVE (paid, on your own Apify token): one call searches 8,800+ Greenhouse, Ashby and Lever company boards, with radius and salary filters, from a fresh daily index (not a live scrape of a few boards). Run it as the Apify Actor https://apify.com/fairquery/jobs-index-search or the MCP https://mcp.getfairquery.com/jobs-index/mcp (send your Apify token). New Apify accounts get a $5 starter credit. This free tool stays free and live-scans the 135-board starter list. 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 is offline here; this tool checks one job). 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 in jobs_get_board. EXAMPLE: {"jobKey":"greenhouse:stripe:8172503"} -> {"status":"open","method":"detail_endpoint"}.

Discovered
jobs_find_board

Indexed Jobs search is LIVE (paid, on your own Apify token): one call searches 8,800+ Greenhouse, Ashby and Lever company boards, with radius and salary filters, from a fresh daily index (not a live scrape of a few boards). Run it as the Apify Actor https://apify.com/fairquery/jobs-index-search or the MCP https://mcp.getfairquery.com/jobs-index/mcp (send your Apify token). New Apify accounts get a $5 starter credit. This free tool stays free and live-scans the 135-board starter list. 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 at once, paid indexed search is live (Apify Actor fairquery/jobs-index-search or https://mcp.getfairquery.com/jobs-index/mcp); jobs_search_companies is offline here (not billed). 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 tools): the call does not fail but adds a HOST_BLOCKED note to meta.notes, stops the careers-page step when the company site is blocked, and skips later slug probes on a stopped ATS host without sending them. COST: No APIFY_TOKEN and no billing; worst case about 4 website requests (robots.txt + 3 pages) and 6 ATS API GETs per call. RETURNS: "board" rows, or one NO_BOARD_FOUND error row. via (board_url | seed_list | careers_page | slug_probe) says how the board was found; confidence is "high" except for slug_probe hits ("medium": the slug exists but may belong to a different company with the same name, so check the jobs or pass the URL from the careers page). PARAMETERS: company accepts three forms with different behavior: a board URL (including a Personio, Pinpoint or Gem URL, or personio:account / pinpoint:subdomain / gem:vanity) is parsed with no network call; a domain or https URL enables the careers-page step; a plain name only uses the starter list and slug probes. Slug guesses for a name drop legal suffixes and "the" (Inc, LLC, Ltd, GmbH, Corp, Co, PLC, AG, SA, BV) and try the joined words, the hyphenated words and the first word; probes run Greenhouse, Lever, Ashby in that order (never Personio, Pinpoint or Gem) and the first hit wins, so an ambiguous name returns at most one medium-confidence board. A starter-list match can return several boards (all high). EXAMPLE: {"company":"ramp.com"} -> [{"ats":"ashby","slug":"ramp","via":"seed_list","confidence":"high"}].

Discovered
jobs_get_board

Indexed Jobs search is LIVE (paid, on your own Apify token): one call searches 8,800+ Greenhouse, Ashby and Lever company boards, with radius and salary filters, from a fresh daily index (not a live scrape of a few boards). Run it as the Apify Actor https://apify.com/fairquery/jobs-index-search or the MCP https://mcp.getfairquery.com/jobs-index/mcp (send your Apify token). New Apify accounts get a $5 starter credit. This free tool stays free and live-scans the 135-board starter list. 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 paid indexed search (Apify Actor fairquery/jobs-index-search or https://mcp.getfairquery.com/jobs-index/mcp, your own Apify token). jobs_search_companies is offline here and not billed. Use jobs_search_by_location for a place or role on the 135 starter boards. 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: one read of Gem's public job-board API (the job_posts list for the vanity you name; no sign-in, never submits applications); every vanity shares one lane, one at a time, at least 1 s apart. Pinpoint and Gem description_text stay empty (link out; the ad body is not copied). Gem job_url points at jobs.gem.com. Pinpoint job_url is the tenant listing link. Emails and phones are not kept from a Pinpoint posting. Nothing stored, no history: first_seen_at = now and change = null. Any HTTP 403/429 stops that host for the session (kill switch, HOST_BLOCKED error). A blocked Personio or Pinpoint host does not block other companies. A blocked Gem response stops api.gem.com for the session. Lever requests are spaced 1 s apart (its robots.txt Crawl-delay). COST: No APIFY_TOKEN, no billing. RETURNS: Paged "job" rows. compensation only when the ATS publishes it; posted_at is the ATS date or null (never guessed); age_basis says how age_days was derived. PARAMETERS: All filters are AND-ed; values inside one filter are OR-ed. titleIncludes/titleExcludes match whole words ("engineer" does not match "Engineering"). countries uses the ATS's structured country where present (Lever, Ashby) and a place-name list otherwise; rows without any country are dropped when countries is set. postedWithinDays drops rows with posted_at = null. Paging re-fetches the board, so pages from different calls can shift if the employer edits the board in between. EXAMPLE: {"ats":"ashby","slug":"ramp","titleIncludes":["engineer"],"remote":"only"} -> remote engineering roles at Ramp with salary ranges.

Discovered
jobs_get_job

Indexed Jobs search is LIVE (paid, on your own Apify token): one call searches 8,800+ Greenhouse, Ashby and Lever company boards, with radius and salary filters, from a fresh daily index (not a live scrape of a few boards). Run it as the Apify Actor https://apify.com/fairquery/jobs-index-search or the MCP https://mcp.getfairquery.com/jobs-index/mcp (send your Apify token). New Apify accounts get a $5 starter credit. This free tool stays free and live-scans the 135-board starter list. 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 at once (paid indexed search: Apify Actor fairquery/jobs-index-search or https://mcp.getfairquery.com/jobs-index/mcp; jobs_search_companies is offline here and not billed). 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. RETURNS: One "job" row, or a tool error: INVALID_INPUT, BOARD_NOT_FOUND, JOB_CLOSED, HOST_BLOCKED or NETWORK_ERROR (the last two retryable). A non-JSON body or other HTTP failure uses the ATS client code (ATS_BAD_RESPONSE, ATS_HTTP_ERROR). PARAMETERS: A malformed jobKey, or neither jobKey nor a complete ats + slug + jobId, returns INVALID_INPUT with no request. An Ashby or Personio id downloads the whole board with descriptions. A Pinpoint or Gem id downloads the board list and still leaves description_text empty. Greenhouse and Lever use the per-job endpoint; a 404 or 410 triggers one extra board request so JOB_CLOSED is told apart from a missing board (BOARD_NOT_FOUND). Where a description is included it is plain text, at most 20,000 characters, with e-mail addresses and phone numbers removed. EXAMPLE: {"jobKey":"greenhouse:stripe:8172503"} -> that Stripe job's row.

Discovered
jobs_list_seed_boards

Indexed Jobs search is LIVE (paid, on your own Apify token): one call searches 8,800+ Greenhouse, Ashby and Lever company boards, with radius and salary filters, from a fresh daily index (not a live scrape of a few boards). Run it as the Apify Actor https://apify.com/fairquery/jobs-index-search or the MCP https://mcp.getfairquery.com/jobs-index/mcp (send your Apify token). New Apify accounts get a $5 starter credit. This free tool stays free and live-scans the 135-board starter list. 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 (135 boards), not the paid indexed search (8,800+ boards, Apify Actor fairquery/jobs-index-search). 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.

Discovered
jobs_search_by_location

Indexed Jobs search is LIVE (paid, on your own Apify token): one call searches 8,800+ Greenhouse, Ashby and Lever company boards, with radius and salary filters, from a fresh daily index (not a live scrape of a few boards). Run it as the Apify Actor https://apify.com/fairquery/jobs-index-search or the MCP https://mcp.getfairquery.com/jobs-index/mcp (send your Apify token). New Apify accounts get a $5 starter credit. This free tool stays free and live-scans the 135-board starter list. 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 employers outside this starter list, radius or salary filters: paid indexed search (8,800+ boards, fresh daily index) is live as the Apify Actor fairquery/jobs-index-search or https://mcp.getfairquery.com/jobs-index/mcp (own Apify token). jobs_search_companies is offline here and does not run any paid Actor. This tool does not search all companies. The free limits stay 135 starter 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. 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 already spent. Greenhouse matches title and department on the lite list before any body request. A body is a second request to that same host only when a description keyword is still missing from the title and department, or includeDescription needs the text, and the lite list already has a job in the place. A Greenhouse board with more than 1000 jobs does not get a body request (the Anduril body is about 44 MB and does not fit the 128 MB isolate). Those boards are listed in meta.title_only_boards and return title and department matches only. Lever and Ashby descriptions are in the one list response. Each board is read in small slices, one job at a time. Description fields are not copied unless descriptionIncludes or includeDescription needs them. A text field longer than 20,000 characters is cut before matching and named in meta.notes. A board that is still too large is cut off and the scan continues. A missing board (BOARD_NOT_FOUND) is skipped. A board error is skipped and named in meta.notes. HOST_BLOCKED stops that host for the session; other hosts continue. The scan stops early on a 25 second wall clock, on the CPU work budget (12,000 ms estimated, a hard ceiling, 8,000 JSON characters per millisecond plus 0.08 ms per row built, because the hosted Worker clock does not advance during synchronous parsing; Paid Workers default to about 30 seconds of CPU and this soft-stop returns JSON before that; one call does not run unbounded), on a cap of 200 matched rows, or after 300 ATS requests (a hard ceiling: 135 starter boards take one lite request each, plus a Greenhouse body only when a description is still needed and the board has at most 1000 jobs, at most about 223 requests; Paid Workers allow 10,000 subrequests). It returns the jobs already matched (meta.partial true, meta.stop_reason "time_budget", "cpu_budget", "row_cap" or "subrequest_budget", meta.cost_usd 0). A scan error still returns that JSON (meta.stop_reason "error"); it does not throw a Server error and it does not invent jobs. Nothing is stored. offset pages rows inside this response. It does not continue the board walk. Pass boardCursor from meta.next_board_cursor, with the same place and keywords, to read boards this call did not start. next_board_cursor is null only when every board from the current board_cursor through the end was started, or no boards remain. Do not call again when it is null. A cpu_budget, subrequest_budget, time_budget, or row_cap stop before the end of the list sets it to the next unstarted index. A board error is skipped and named in meta.notes; it does not rewind the cursor behind boards this call already started. COST: No APIFY_TOKEN, no billing. meta.cost_usd is 0. RETURNS: Paged "job" rows. meta.notice (also meta.notes[0]) is the indexed search note: paid indexed search is live, covers 8,800+ boards with radius and salary filters from a fresh daily index, and runs as the Apify Actor https://apify.com/fairquery/jobs-index-search or the MCP https://mcp.getfairquery.com/jobs-index/mcp on your own Apify token. When meta.partial is true or the board walk is incomplete, meta.notice starts with how many of meta.boards_total boards this call finished. Also meta.boards_total, meta.boards_reached (boards this call started), meta.boards_scanned (boards that finished), meta.boards_ok, meta.boards_failed, meta.boards_skipped, meta.jobs_matched, meta.partial, meta.complete, meta.cut, meta.board_cursor, meta.next_board_cursor, meta.notes and meta.cost_usd. meta.stop_reason is set when partial is true. meta.title_only_boards lists Greenhouse boards whose body was skipped. meta.complete is true when this call started every board from board_cursor through the end and did not hit a budget. meta.next_board_cursor is the first starter index this call did not start, or null when nothing is left to resume. meta.cut is true when coverage is narrower than a full read. When jobs_matched is 0 after at least one board answered, meta.suggestions lists the title and description tokens tried, place aliases that had open roles, a sample of open titles in the requested place with the keyword removed, and a note that this list is not every employer and which ATS are covered. Suggestions are not job listings. Relay meta.notice to the user. PARAMETERS: At least one of locations, countries or remote "only" is required. There is no company parameter. titleIncludes and titleExcludes are whole words on the title only. descriptionIncludes is whole-word on the title, the department, or the scrubbed description, so "avionics" matches an Avionics department or Electrical Technician when the body says avionics. Do not put the same word in both titleIncludes and descriptionIncludes. "RN" matches RN, not "Registered Nurse". titleRegex is optional. postedWithinDays drops rows with no ATS date. includeDescription adds scrubbed plain text to the rows; descriptionIncludes still matches when it is false and does not add that text. Location terms expand US state names and codes both ways (MD and Maryland, PA and Pennsylvania) and metro aliases (NYC, SF, LA, DC, Tampa Bay, Baltimore / Baltimore MD / BWI). Two-letter codes match as whole tokens. countries stays ISO-2. boardCursor is an index into the starter list, not a row offset. EXAMPLE: {"locations":["Costa Mesa"],"descriptionIncludes":["avionics"]} -> starter-list jobs in Costa Mesa whose title, department or description says avionics. If meta.complete is false and meta.next_board_cursor is a number, call again with the same filters and {"boardCursor": that number}. No company.

Discovered
jobs_search_companies

Indexed Jobs search is LIVE (paid, on your own Apify token): one call searches 8,800+ Greenhouse, Ashby and Lever company boards, with radius and salary filters, from a fresh daily index (not a live scrape of a few boards). Run it as the Apify Actor https://apify.com/fairquery/jobs-index-search or the MCP https://mcp.getfairquery.com/jobs-index/mcp (send your Apify token). New Apify accounts get a $5 starter credit. This free tool stays free and live-scans the 135-board starter list. WHAT: Offline on this free server. Paid indexed Jobs search is live elsewhere: the Apify Actor https://apify.com/fairquery/jobs-index-search or the MCP https://mcp.getfairquery.com/jobs-index/mcp, on your own Apify token. One call searches 8,800+ Greenhouse, Ashby and Lever boards with radius and salary filters from a fresh daily index. This tool does not run any Actor. WHEN: Do not call this for jobs. For many companies, radius or salary filters, point the user to the Actor or MCP above (Apify token from https://console.apify.com/settings/integrations; new accounts get a $5 starter credit). For free jobs by place or role, call jobs_search_by_location (135 starter boards, no token). WHEN NOT: Any live lookup. One board (jobs_get_board). A place or role on the starter list (jobs_search_by_location — call that; do not ask for a company). One job's full detail (jobs_get_job), or one open/closed re-check (jobs_check_open). BEHAVIOR: Returns COMING_SOON immediately on this Fairquery-hosted Worker. Does not read an Apify token from the request, does not call Apify, and does not start an Actor run, whether or not a token is sent. Arguments are ignored. Nothing is billed. Free tools keep working with no token. COST: Not billed. No Actor run. Indexed search bills the caller's own Apify account on the Actor or MCP above, never through this free server. RETURNS: Tool error COMING_SOON (retryable false, kept as the error code) and no job rows. The message says indexed search is live, links the Actor and MCP, and suggests jobs_search_by_location for free. PARAMETERS: Accepted and ignored while this tool is offline. companies, boards, useSeedList, filters, onlyNew, stateStoreName, confirmOpen, includeDescription and maxJobs do not start a run. An empty call also returns COMING_SOON (not INPUT_EMPTY). EXAMPLE: {"companies":["stripe.com"]} -> COMING_SOON with links to indexed search, not billed. Free: {"locations":["Tampa"],"descriptionIncludes":["engineer"]} on jobs_search_by_location.

Discovered
mcp_server_precheck

WHAT: Pre-install check for one MCP server. Scans tool names (split on _ - . and camelCase), descriptions, parameter names/descriptions and schema enum/default/examples you pass for injection phrasing, concealed characters (tag characters, base64 and hex blobs are decoded and rescanned), hidden markup, cross-server references, shadowing of other tools in the same list (same sentence; plain ordering like "call X first" is not flagged), and exfil destinations (email/URL/public IP/paste site next to send/post/upload/copy/forward/BCC, or stealth wording + action + user data). Optional baseline compares SHA-256 fingerprints with a prior scan (rug pull). Optional sarif=true adds a SARIF 2.1.0 log. An MCPB manifest in toolsListJson also has its server.mcp_config command checked for download-and-pipe-to-shell, and its server.mcp_config / mcpServers env, headers, args and url checked for hardcoded secrets (same detectors as mcpConfig, masked). Also flags shell/exec tools and unrestricted file paths (OVERBROAD_PERMISSION), near-miss tool or package names (TYPOSQUAT), and with servers[] the private-data + untrusted-input + external-send combination across servers (TOXIC_FLOW). Injection and exfil phrasing is also matched in Spanish, French, German, Portuguese, Italian and Dutch. The same rules also run on prompts, resources and SKILL.md text you pass (skillMd shell blocks are checked for download-and-pipe-to-shell), and serverUrl fetches a remote server's tools/list for you. mcpConfig (a pasted mcp.json / claude_desktop_config.json / env block) is checked for hardcoded secrets and personal data with the pii_scan_text detectors (credential hygiene; values are masked, nothing is forwarded). Every result has meta.grade, an A-F letter for non-technical readers, labelled meta.grade_label "Static checks: A": it reflects deterministic pattern checks only; semantic analysis is not run. Limitation: this free tier does not detect instructions reworded to avoid known phrasing (paraphrased injection or exfiltration), so a clean grade is not proof of safety. Every finding has source (remote:<host> for what serverUrl fetched, pasted:<argument> for text you passed); meta.grades_by_source grades each source separately, the overall meta.grade is the worst across sources (all findings of the call together), and with serverUrl meta.remote.grade is the remote server's own grade. serverUrl is scanned alone: mixing it with pasted tools/toolsListJson/servers/prompts/resources/skillMd/mcpConfig returns INPUT_MIXED_SOURCES. WHEN: Before installing or enabling an MCP server, once you have a tools/list result to pass as tools or toolsListJson (or its https URL as serverUrl), or to check an MCP client config for hardcoded keys (mcpConfig). 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. serverUrl is opt-in and free: this Worker connects to that URL itself (with serverBearerToken as an Authorization header if given; the token is not stored, logged or echoed), so the remote server sees a request from Cloudflare, not from you (meta.shared_externally.server_url_contacted). 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. auditDependencies=true is opt-in: if toolsListJson carries a package name (MCPB manifest or package.json "name", not private), that name is sent to registry.npmjs.org (public GET, free, meta.shared_externally.package_name_to_npm_registry true); if toolsListJson is a package.json (or package-lock.json) document, its text is sent to the paid OSV Actor with your Apify token ($0.50 per 1,000 packages + $1.50 per 1,000 vulnerabilities found); without a token the audit row is APIFY_TOKEN_MISSING. A manifest is never read from disk. baseline and sarif are computed on this Worker (WebCrypto SHA-256); nothing is stored or sent anywhere. mcpConfig is scanned on this Worker only (no network call); secrets found are masked in evidence and never echoed. Free serverUrl is a one-off fetch of one public endpoint, soft rate-limited per Worker instance (10/min per host, 60/min overall; in-memory, not a durable or global quota). Bulk, scheduled and monitored fetching are not part of the free tier. RETURNS: Paged "finding" rows (rule, severity, tool, field, evidence). Evidence escapes hidden characters JS-style (\n, \u200B, \u{E0069}). Duplicate tool names are never dropped: every definition is scanned, meta.tools_scanned equals the number of tools received (meta.tools_input), and each duplicated name gets a high DUPLICATE_TOOL_NAME finding (shadowing risk). Other rules: PROMPT_INJECTION, HIDDEN_INSTRUCTION, SECRET_EXFILTRATION, CONCEALED_TEXT, ENCODED_INSTRUCTION (critical: a base64/hex blob decodes to an instruction), TOOL_SHADOWING (a description names another tool in the list with must/always/BCC/instead/before; high for hijack words or a destination), CROSS_SERVER_REFERENCE, MIXED_SCRIPT, SUSPICIOUS_PARAMETER, INSTALL_PIPE_TO_SHELL (field install_command; critical for curl|bash style, high for sh -c; field skill_md: critical for curl|bash in SKILL.md), EXFIL_DESTINATION (send/post/upload/copy/forward/BCC to a paste site, a fixed email/URL with user data/copy/stealth wording, or a raw public IP), COVERT_EXFILTRATION (stealth / hidden-from-the-user wording + an action on user data), OVERBROAD_PERMISSION (high: shell/exec-named tool with a free-form command/script parameter; medium: exec-style name alone or any/absolute-path file access; low: write/delete tool with an unrestricted path; sandbox wording lowers it), TYPOSQUAT (a tool name 1-2 typo edits from another tool in the list or a well-known MCP tool; high for look-alike characters or a near-miss popular npm package name, field package_name), TOXIC_FLOW (servers[] only: private-data reader + untrusted-content source + external sender; high when they span servers, field servers; message and evidence name the reader, untrusted and sender tools, first 8 of each), and with baseline: TOOL_CHANGED (high; list-hash-only baseline: medium, field tool_list), TOOL_ADDED (medium), TOOL_REMOVED (low), field definition. Every finding has owasp tags (OWASP MCP Top 10 2025 MCPxx and LLM Top 10 2025 LLMxx) and source: remote:<host> (serverUrl surface), pasted:tools, pasted:toolsListJson (incl. package, install_command and mcpServers env findings), pasted:servers, pasted:prompts, pasted:resources, pasted:skill_md, pasted:mcp_config or pasted:baseline (TOOL_CHANGED/ADDED/REMOVED); a finding that involves several inputs (duplicate name, typosquat pair, toxic flow) joins them with "+". meta.grades_by_source maps each source to {grade, grade_label, risk_level, finding_counts}; meta.grade / grade_label / risk_level are the worst across sources (computed over all findings together), and meta.grade_scope says so. With serverUrl, meta.remote.grade / grade_label / risk_level / finding_counts come from remote findings only. mcpServers / server.mcp_config inside toolsListJson: env, headers, args and url get the mcpConfig secret detectors (HARDCODED_SECRET / CONFIG_PII, masked; meta.install_config_scanned); anything that cannot be scanned is named in meta.notes as MCP_SERVERS_NOT_SCANNED, never skipped without a note. Prompt/resource/SKILL.md text that sends to a fixed email/URL is EXFIL_DESTINATION medium even without user-data wording. meta.tools_fingerprint (sha256 per tool + list_sha256) is always returned so you can pass it as baseline next time; meta.baseline reports matched/changed/added/removed; meta.sarif is present only when sarif=true. Schema values report field parameter_enum, parameter_default, parameter_examples, parameter_const, parameter_title or schema_default/schema_examples. If auditDependencies is true, one "dependency_audit" row: status no_manifest unless toolsListJson is a package.json/lockfile. meta.risk_level is none, low, medium, high, critical or not_assessed. meta.grade is A-F (A: nothing above low; B: worst medium; C: 1-2 high; D: 3+ high; F: any critical; null when not assessed), meta.grade_scale repeats this. meta.grade_label shows it as "Static checks: <letter>", meta.grade_basis is "static_checks" and meta.semantic_analysis is "not_run"; when a grade is present meta.notes includes PARAPHRASE_GAP (reworded instructions are not detected). mcpConfig findings: HARDCODED_SECRET (high for a known token format such as ghp_/sk-/AKIA/xox, medium for a generic key=value or a secret-named variable holding a literal; tool = server name from the config, field mcp_config_env, mcp_config_header, mcp_config_args, mcp_config_url, mcp_config_auth or mcp_config, parameter = key name, evidence masked) and CONFIG_PII (low: email, phone, card, IBAN, SSN in the config); meta.config_scanned {format, servers, values_scanned, hardcoded_secrets, pii_values, forwarded:false}. TYPOSQUAT severity: look-alike characters or swapped letters high, other single-letter edits low, 2 edits medium; abbreviation pairs (mail/email, msg/message, repo/repository, dir/directory) are not typos. Cross-server TOOL_SHADOWING names the other server and is one level higher than same-list (high -> critical). Prompt/resource/SKILL.md findings use tool = prompt/resource name or "SKILL.md" and field prompt_name, prompt_title, prompt_description, prompt_argument, resource_name, resource_title, resource_description, resource_text or skill_md; meta.extras_scanned counts them. With serverUrl, meta.remote reports host, server_name, protocol_version, tools/prompts/resources fetched and requests. meta.description_scanned is about the package-level description only (false = none present; tool descriptions are always scanned); meta.description_scanned_meaning repeats this. meta.shared_externally is the data-flow record for this call: tool_names_and_descriptions is always false (that text is not forwarded to npm or Apify, though this Worker receives it); package_name_to_npm_registry is true when the package name was sent to registry.npmjs.org; manifest_to_osv_actor is true when manifest text was sent to the OSV Actor; server_url_contacted is the host this Worker connected to for serverUrl (false otherwise). Errors: INPUT_EMPTY, INPUT_MIXED_SOURCES (serverUrl plus pasted content), INVALID_SERVER_URL, SERVER_URL_NOT_ALLOWED, SERVER_URL_RATE_LIMITED, SERVER_URL_AUTH, SERVER_URL_FETCH_FAILED, INVALID_JSON, INVALID_PACKAGE_NAME, PATH_NOT_ALLOWED, INPUT_TOO_LARGE, INVALID_BASELINE. 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: if toolsListJson carries a package name (MCPB manifest "name" or package.json "name", not private), this Worker sends that name only to registry.npmjs.org (public GET) for license and publish dates; if toolsListJson is a package.json or package-lock.json, this Worker sends that manifest text to the paid OSV Actor (Apify) using your token. Plain tools/list input with no package name makes no registry or OSV call. serverUrl: this Worker POSTs initialize, notifications/initialized and tools/list (plus prompts/list and resources/list metadata when the server advertises them; resources are not read) to that URL over MCP Streamable HTTP, JSON or SSE responses; https and public hostnames only (no IP literals, no internal or trailing-dot internal names, no cloud metadata names, no wildcard-DNS helpers such as nip.io/sslip.io; the host is resolved over DNS-over-HTTPS first and refused if any address is loopback, RFC1918, link-local/metadata 169.254.x, CGNAT, ULA or otherwise reserved; ports 80/443), soft rate limit per Worker instance (SERVER_URL_RATE_LIMITED), redirects not followed, 10 s per request, 12 requests max, then a best-effort DELETE of the session. It never calls a remote tool. meta.shared_externally.package_name_to_npm_registry and manifest_to_osv_actor report exactly which happened. PARAMETERS: Pass tools or toolsListJson (neither, and no path or packageName -> INPUT_EMPTY). tools: structured tools/list entries. toolsListJson: raw JSON of a tools/list result, an MCPB manifest or a tools array; invalid JSON -> INVALID_JSON. path and packageName always fail on this Worker (no disk): an invalid packageName is INVALID_PACKAGE_NAME, and any other path or packageName is PATH_NOT_ALLOWED. Nothing is read or downloaded. Use the npm server @fairquery/agent-trust-mcp for a path or packageName scan. Each field is scanned up to 20,000 characters and the raw total must be <= 500,000. auditDependencies defaults to false; true can make the registry.npmjs.org and paid OSV calls described in BEHAVIOR. minSeverity and includeDevDependencies are only forwarded to the OSV Actor. baseline: optional, a string OR a JSON object/array (JSON-parsing clients may pass the object as-is): the prior meta.tools_fingerprint object or its JSON text (per-tool detail), the 64-hex list_sha256 string or {"list_sha256":"..."} (list-level only), or a prior tools/list result / tools array (invalid -> INVALID_BASELINE). baselineTools: optional array alias (fingerprint tools [{name,sha256}] or a tools array). sarif: boolean, default false; sarif:true puts a SARIF 2.1.0 log in meta.sarif (format:"sarif" is accepted as an alias with a note). servers: optional [{name, tools}] (one entry per installed MCP server, up to 20; total tools still <= 400): every tool is scanned as usual with shadowing/duplicates checked across servers, each finding carries server, a name defined by several servers is DUPLICATE_TOOL_NAME medium, and TOXIC_FLOW is checked. prompts: optional prompts/list entries [{name, description, arguments:[{name, description}]}]. resources: optional resources/list entries [{uri, name, description}] plus optional text (resource content). skillMd: optional SKILL.md text (frontmatter + body, <= 500,000 chars). serverUrl: optional https URL of a remote MCP Streamable HTTP endpoint (e.g. https://example.com/mcp); scan it alone: serverUrl together with tools, toolsListJson, servers, prompts, resources, skillMd or mcpConfig returns INPUT_MIXED_SOURCES and nothing is sent (baseline and sarif are allowed). serverBearerToken: optional bearer token sent only to serverUrl. mcpConfig: optional text (<= 200,000 chars) of an MCP client config: JSON/JSONC with mcpServers, servers, context_servers or mcp.servers, a single server entry, or plain KEY=value / export KEY=value lines; env, headers, args, url and auth fields are scanned for hardcoded secrets (${env:X}, ${input:x}, $X and similar references are skipped). Any other parameter name is ignored and listed in meta.notes as "unknown parameter: <name>". limit/offset page the combined rows. EXAMPLE: {"tools":[{"name":"sum","description":"Add two numbers."}]} -> risk_level "none", shared_externally.tool_names_and_descriptions false. A poisoned description returns finding rows and a higher risk_level.

Discovered
osv_audit_dependencies

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"}

Discovered
osv_get_vulnerability

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.

Discovered
osv_query_packages

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",...].

Discovered
pii_guard_documents

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; with returnPlaceholderMap the map comes back as an encrypted sealed_map string when this deployment has a seal key) 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; with sealedMap it follows the same restore key rule as pii_restore_text (refusal -> RESTORE_KEY_REQUIRED, nothing billed); a clear-text placeholderMap alone is refused on deployments with a seal key (SEALED_MAP_REQUIRED, nothing billed); 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}

Discovered
pii_list_detectors

WHAT: Fortress Shield (agent I/O PII protection). 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, and fetching remote PDF/document URLs; http(s) URLs in text are detected locally; STREET_ADDRESS patterns run locally with detectAddresses), redaction styles, sealed-map support, 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). features.sealed_map.available says whether this deployment can seal placeholder maps. 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},...]}

Discovered
pii_redact_text

WHAT: Fortress Shield (agent I/O PII protection). Return sanitized copies of texts with every local PII/secret finding replaced: placeholder [EMAIL_k7q2m9xp4a] (random id per value), mask, or hash. For placeholders the originals come back only inside meta.sealed_map, an AES-256-GCM encrypted string that this Worker opens in pii_restore_text. The originals stay out of the model context. WHEN: Right before sending user data to an LLM/third party. Keep meta.sealed_map if you need to restore originals in the LLM answer later. WHEN NOT: For a findings report only use pii_scan_text. For unlabelled names (NER) or fetching PDFs and remote documents use pii_guard_documents (paid). http(s) URLs in text you already have are redacted here for free. COST: Free; no token. RETURNS: One "redacted_document" row per text with output_text, typed_placeholders_escaped, context_lowered, context_suppressed, below_threshold, context_report, field_paths (JSON input) and, with failClosed, blocked / block_reasons (output_text null); meta.audit, meta.secret_guidance, meta.compliance, meta.would_fail_closed; meta.sealed_map (placeholder style, "fqs2.…"; null plus a SEAL_KEY_NOT_CONFIGURED note when this deployment has no seal key) and meta.seal {algorithm, entries, expires_at, restore_bound, max_restores}. Errors: INPUT_TOO_LARGE, INVALID_PATTERN, INVALID_ARGUMENT, SEALED_MAP_INVALID, SEALED_MAP_EXPIRED, SEAL_KEY_NOT_CONFIGURED, RESTORE_KEY_REQUIRED / RESTORE_KEY_MISMATCH (priorSealedMap bound to another restore key). BEHAVIOR: Placeholder ids are random on every call unless you pass priorSealedMap; "hash" is random per call unless a hash key is set. The sealed_map is bound to the restore key header of this request (X-FQ-PII-Restore-Key, set by the operator in the client connection); without one, pii_restore_text reports counts only. 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, and case/format variants share it (JANE@ACME.COM and jane@acme.com; +1 415 555 0100 and (415) 555-0100). Placeholder-shaped text already in the input (a user typing "[EMAIL_1]") is itself replaced by a [TYPED_PLACEHOLDER_<id>] placeholder and restored verbatim, so it can never pull another value. priorSealedMap: the meta.sealed_map of an earlier call; values seen before keep their placeholder, new ones are added, and the returned sealed_map covers both (use it across turns and when paging). redactionStyle: "placeholder" is the only reversible style; "mask" keeps a few characters for human review; "hash" with hashKey (16-256 chars, your own key) gives the same output for the same value in every call (HMAC-SHA256, joinable), without hashKey the salt is random per call. sealTtlHours: how long the sealed_map opens (1-720, default 24). returnPlaceholderMap: deprecated and refused unless the request carries the restore key header; use sealed_map. maxRestores: restore cap for this sealed_map (default 3). entityTypes / allowList / allowDomains / allowPatterns / customDetectors / contextScoring / contextMode / entropyScan / defaultPhoneRegion: identical semantics to pii_scan_text. limit/offset page whole documents (one item per text, default 50 = all). EXAMPLE: {"texts":["Call +1 415 555 0100 or mail jane@acme.com"]} -> output_text "Call [PHONE_4hq8m2xk9c] or mail [EMAIL_t7c3pz2wqa]", meta.sealed_map "fqs2.…".

Discovered
pii_restore_text

WHAT: Fortress Shield (agent I/O PII protection). Put the original values back into texts (typically an LLM answer) that contain placeholders such as [EMAIL_k7q2m9xp4a], by opening meta.sealed_map from pii_redact_text on this Worker (or a legacy clear-text placeholder map). Numeric JSON sentinels are restored only in the redacted document they came from, matched by those bytes in any order. A different document is not rewritten. Slots for a document you did not pass are reported as JSON_NUMBER_DOC_MISMATCH. schema_range_preserved is false. WHEN: After an LLM or third party answered a prompt you sanitized with pii_redact_text (redactionStyle "placeholder"), right 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 restored, output_text, replacements, fuzzy_restored, unknown_placeholders and near_miss_placeholders. meta.restore_gate is RESTORE_KEY_OK, or RESTORE_KEY_REQUIRED / RESTORE_KEY_MISMATCH / RESTORE_LIMIT_REACHED, in which case nothing is substituted: restored is false, replacements 0, output_text is the input unchanged and sealed_replacements_withheld only counts them. restored is true only when at least one placeholder was actually replaced. Every row carries map_source ("sealed" | "plaintext"), verified (true only for an authenticated sealed map) and exact (no fuzzy, unknown or near-miss placeholders); meta.verification and meta.audit (counts) summarise them. A clear-text placeholderMap alone is refused on deployments with a seal key (meta.restore_gate SEALED_MAP_REQUIRED, nothing substituted, plaintext_replacements_refused counts). Further gate codes (counts only): TENANT_MISMATCH (map bound to another tenantId), USER_ONLY_RESTORE (restoreAudience "user" without the X-FQ-PII-User-Present header), APPS_RESTORE_REQUIRED (operator requires a user-facing MCP Apps / UI restore). meta.seal_ttl {expires_at, remaining_seconds}; meta.sealed_map_extended with extendTtlHours; meta.receipt with returnReceipt. Errors: INPUT_TOO_LARGE, MAP_MISSING, SEALED_MAP_INVALID (altered or from another deployment), SEALED_MAP_EXPIRED, SEAL_KEY_NOT_CONFIGURED. BEHAVIOR: Original values come back only when the request carries the same restore key header (X-FQ-PII-Restore-Key, configured by the operator in the MCP client connection, never a tool argument) that was present when the map was sealed, and at most maxRestores times per map; otherwise counts only. Holding the sealed map alone is not enough. 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 map is not forwarded. Milliseconds. Max 50 texts, 200,000 chars each, 500,000 total; map up to 10,000 entries. PARAMETERS: sealedMap: pass meta.sealed_map unchanged (preferred). placeholderMap: legacy clear-text map, honoured only when this deployment has no seal key (or the operator restore policy is "open"), and then marked verified false; if both are given, sealedMap is used alone and placeholderMap is ignored (never merged; PLAINTEXT_MAP_IGNORED note). Every key is replaced wherever it occurs exactly (longest first, one pass, so a restored value is never replaced again). fuzzyRestore (default true): a placeholder the LLM rewrote but whose random id is intact ("EMAIL_k7q2m9xp4a" without brackets, lower case, a space instead of _) is restored too and listed in fuzzy_restored. unknown_placeholders lists exact [TYPE_N] shapes the map does not contain; near_miss_placeholders lists mangled shapes ("EMAIL_3", "[Email_4]") that matched no key; both stay as they are. When restored is true 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_t7c3pz2wqa] today."],"sealedMap":"fqs2.…"} with the restore key header -> output_text "I will email jane@acme.com today.", replacements 1; without it -> restored false, sealed_replacements_withheld 1.

Discovered
pii_scan_text

WHAT: Fortress Shield (agent I/O PII protection). Detect PII (emails incl. "jane [at] acme [dot] com" and "jane at acme dot com" forms, phones, US SSNs/ITINs, Luhn-valid cards, mod-97 IBANs, UK NINOs, IPv4 and full or compressed IPv6, MAC addresses, labelled dates of birth / passports / driver's licences / MRNs / health-plan ids / ABA routing numbers, Canadian SIN, NPI/DEA/MBI, VIN, Bitcoin/Ethereum wallets, ES DNI/NIE, IT codice fiscale, FR NIR, IN Aadhaar/PAN, ZIP/postcodes in a residence or ZIP context) and credential-shaped strings (common provider token formats, signed web tokens, PEM key blocks incl. a header without its END line, user:pass in URLs, key=value assignments; full list from pii_list_detectors) in text, plus your own customDetectors. Text is normalized first (NFKC, zero-width characters removed, Cyrillic/Greek look-alike letters folded), so hidden characters do not split a match. Detection only: matches are masked in the output and nothing is sent anywhere. 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 unlabelled person names (NER), or to fetch PDFs and remote documents, use pii_guard_documents (paid). http(s) URLs in text you already have are detected here for free. 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 and, when a label raised it, context; raw values are never returned. meta.documents[] has context_lowered (matches kept at low confidence because of a negative context word), context_suppressed (matches left out with contextMode "drop") and typed_placeholders (placeholder-shaped text such as "[EMAIL_1]" already in the input), below_threshold and context_report (which context word lowered or skipped which type; no values). JSON input: findings carry json_path. meta.audit (counts only), meta.secret_guidance (provider + revoke URL per detected credential type), meta.compliance (HIPAA Safe Harbor identifiers seen). Errors: INPUT_TOO_LARGE, INVALID_PATTERN. 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). start/end are offsets in your ORIGINAL text. entityTypes: filters built-in findings after detection; names are case-insensitive, unknown names silently match nothing, NER-only types (PERSON, LOCATION) never match here and STREET_ADDRESS needs detectAddresses=true; customDetectors always run. allowList: whole matched value, case-insensitive; allowDomains: email domains incl. subdomains (allow "yourco.com" to exempt support@yourco.com); allowPatterns: regular expressions tested against the value. 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. EXAMPLE: {"texts":["Mail jane@acme.com, key AKIAIOSFODNN7EXAMPLE"]} -> 2 findings: EMAIL (masked "j***@a***.com"), AWS_ACCESS_KEY; risk_level "critical".

Discovered
sanctions_list_sources

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",...},...]}

Discovered
sanctions_screen_names

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 billed once, so use names for bare strings and queries when you have country/dateOfBirth/entityType or want your own id echoed. In queries, dateOfBirth removes listed individuals born more than 1 year apart, while country never removes matches (it only sets country_match); entityType "entity" covers organisations, vessels and aircraft. lists: omit to screen all five; a list that cannot be downloaded is reported in lists_unavailable instead of failing the run. minScore: a match is returned only if its 0-100 similarity is >= minScore; 85 balances recall and noise, 90-95 for large batches, 75-80 for transliterated names; it does not change the price. maxMatchesPerName caps matches[] only; match_count still reports all matches. limit/offset only page the returned rows: every call screens and bills all names again (also when only offset changes), so set limit (max 1000) to cover all rows instead of paging. EXAMPLE: {"queries":[{"name":"Banco Nacional de Cuba","entityType":"entity"}],"minScore":90} -> status potential_match (OFAC_SDN).

Discovered
trust_screen_lead

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. Identical emails across leads are validated and billed once. ref joins sanctions results back to the lead, so keep refs unique (default = the lead's 0-based index as a string). country and entityType apply to that lead's sanctions check only: entityType filters candidates, while country only annotates matches (never removes them). minScore: sanctions similarity threshold; default 88 here (stricter than the 85 of sanctions_screen_names) to keep block decisions low-noise; each name returns at most its top 3 matches. allowFreeProviders=false turns gmail.com-type addresses into email_verdict "risky", i.e. decision "review" (never "block"). Decision precedence: any sanctions potential_match or invalid email -> block; else risky email or an incomplete check -> review; else pass. limit/offset page the merged lead rows, but every call re-runs and re-bills both checks for all leads (also when only offset changes), so set limit (max 1000) to cover all leads; meta.summary counts all leads. EXAMPLE: {"leads":[{"ref":"L1","email":"cfo@acme.com","name":"Acme Trading LLC","country":"US"}]} -> {decision:"pass",email_verdict:"valid",sanctions_status:"no_match"}

Discovered

Recent measurements

Probe history

View status
Latest stored probes. Raw probe rows are kept for 14 days.
CheckedResultResponseTools
Connected128 ms21