Skip to content
Visa Atlas
DestinationsGuidesCompareCalculatorsDataUpdates
Find my route
Menu
DestinationsGuidesCompareCalculatorsDataUpdatesFind my route
Visa Atlas

A free, independent field guide to moving countries. Every figure links to its official government source.

Not legal advice. Visa Atlas is an encyclopedia, not an adviser. The authoritative source is always the government link on each page. For your specific case, consult a regulated professional.

Explore

All destinationsBest-of guidesCompare countriesRoutes by professionRoute comparisonsTopic guides

Plan

Find my routeProcessing timesGovernment feesCost to completeSettlement & citizenshipRoute deep-divesSalary thresholds

Trust

Editorial standardsReviewersOur methodologyCorrectionsOpen dataCitation packsCitation benchmarkSource benchmarkVisibility metricsFreshnessWidgetsAI agentsUse our dataFor journalists
© 2026 Visa AtlasReviewed continuously. Last sweep: 14 July 2026
  1. Home/
  2. API & data reference

Developer reference · 7 July 2026

API & data reference

Every figure on Visa Atlas — fees, cost-to-complete models, salary floors, processing times, policy changes, the Canada Express Entry draw history, country comparisons, citation packs, the AI citation benchmark and the source-transparency benchmark — is also available as plain JSON, free to reuse under CC BY 4.0. This page documents every endpoint, every field, and shows a real example for each. The machine-readable OpenAPI 3.1 contract is available at /api/openapi.json.

At a glance

Base URL
https://visaatlas.org/api/public
Format
JSON (UTF-8)
Auth
None — fully open
Method
GET; route finder also accepts POST
License
CC BY 4.0
Rate limits
None stated — static, be reasonable

Endpoints

  • Catalog /api/public
  • Indexable page manifest /api/public/indexable-pages
  • Public site search index /api/public/search-index
  • Visa routes /api/public/visas
  • Destinations /api/public/destinations
  • Policy updates /api/public/policy-updates
  • Policy claims /api/public/policy-claims
  • Citation packs /api/public/citation-packs
  • Verified answer capsules /api/public/answer-capsules
  • AI citation benchmark /api/public/citation-benchmark
  • AI retrieval task index /api/public/ai-retrieval-task-index
  • AI retrieval readiness scorecard /api/public/ai-retrieval-readiness
  • AI answer accuracy audit protocol /api/public/ai-answer-accuracy-audit
  • Source transparency benchmark /api/public/source-transparency-benchmark
  • SEO/GEO content opportunities /api/public/content-opportunities
  • Competitor query battlecards /api/public/competitor-query-battlecards
  • Battlecard search experiments /api/public/battlecard-search-experiments
  • SERP and AI answer-surface snapshot protocol /api/public/serp-answer-surface-snapshots
  • Quarterly market-share evidence summary /api/public/quarterly-market-share-summary
  • Publisher and AI-citation kits /api/public/publisher-citation-kits
  • Authority distribution plan /api/public/authority-distribution-plan
  • Embeddable widget catalog /api/public/widgets
  • External repository mirror manifest /api/public/external-repository-mirrors
  • Knowledge-graph entity seeding manifest /api/public/knowledge-graph-entities
  • Expert reviewer entity program /api/public/expert-reviewer-entities
  • reviewedBy schema rollout controls /api/public/reviewedby-schema-rollout
  • High-risk page review acquisition controls /api/public/high-risk-page-review-acquisition
  • P0 reviewed page refresh controls /api/public/p0-reviewed-page-refresh
  • Calculator verdict contexts /api/public/calculator-verdict-contexts
  • Route finder /api/public/route-finder
  • SEO/GEO visibility metrics /api/public/visibility-metrics
  • SEO/GEO traffic forecast /api/public/traffic-forecast
  • Technical SEO/GEO controls /api/public/technical-seo-controls
  • Topical authority internal-link map /api/public/topical-authority-map
  • SEO/GEO audit evidence pack /api/public/seo-geo-audit-evidence
  • SEO/GEO execution readiness scorecard /api/public/execution-readiness
  • SEO/GEO market-share capture plan /api/public/market-share-capture-plan
  • SEO/GEO production queue /api/public/seo-geo-production-queue
  • SEO/GEO page action map /api/public/seo-geo-page-action-map
  • Battlecard retrieval coverage matrix /api/public/battlecard-retrieval-coverage
  • SEO/GEO dominance gap ledger /api/public/seo-geo-dominance-gap-ledger
  • SEO/GEO measurement run queue /api/public/seo-geo-measurement-run-queue
  • SEO/GEO reviewer evidence bridge /api/public/seo-geo-reviewer-evidence-bridge
  • SEO/GEO external evidence bridge /api/public/seo-geo-external-evidence-bridge
  • SEO/GEO private measurement bridge /api/public/seo-geo-private-measurement-bridge
  • SEO/GEO release gate contract /api/public/seo-geo-release-gate
  • Search demand action map /api/public/search-demand-actions
  • Crawler and AI retrieval access audit /api/public/crawler-access
  • Source freshness /api/public/freshness
  • Processing-time planning reliability /api/public/processing-reliability
  • Skilled-migration planning accessibility /api/public/skilled-migration-accessibility
  • Country comparisons /api/public/country-comparisons
  • Fees /api/public/fees
  • Cost to complete /api/public/cost-to-complete
  • Salary thresholds /api/public/salary-thresholds
  • Processing times /api/public/processing-times
  • Canada Express Entry categories /api/public/express-entry-categories
  • Canada Express Entry draws /api/public/express-entry-draws
  • Rules and threshold fact changes /api/public/fact-changes
  • Monthly immigration figure changes /api/public/monthly-figure-changes

Conventions

  • Every response is JSON served over HTTPS as a static file — fast, cacheable, and stable between deploys.
  • Dates are ISO 8601 (YYYY-MM-DD).
  • Money is an exact figure in amountLocal with a separate ISO 4217 currency. We do not convert currencies; an approxUsd field, where present, is a rounded comparison figure only.
  • Destination keys are lowercase and not always ISO-3166 — we use uk (not gb). Treat them as opaque identifiers; the destinations endpoint lists them all.
  • Most records carry their own sourceUrl/sourceName and a lastChecked, lastVerified or lastReviewed date. Always defer to the linked official source.
  • No pagination — datasets are small and returned in full. Optional fields are simply absent when not applicable.

Catalog

GET /api/publicopen live

Returns object · 58 datasets described

A self-describing index of the public reference and figure datasets, plus a schema.org DataCatalog wrapper and Dataset block for each one (the same metadata search engines and dataset registries read). Start here to discover what is available programmatically.

Fields

FieldTypeDescription
datasets[]array<object>One entry per figure dataset.
datasets[].pathstringThe endpoint path, e.g. "/api/public/fees".
datasets[].titlestringHuman title of the dataset.
datasets[].descriptionstringWhat the dataset contains.
datasets[].recordCountnumberNumber of top-level records in that endpoint.
datasets[].dateModifiedstring (ISO date)Freshness date for the endpoint, derived from source review dates.
datasets[].categorystring"reference" for lookup tables or "figures" for numeric/source-derived datasets.
datasets[].humanPathstring?Best human-facing page for this dataset, where one exists.
datasets[].apiDocsPathstringAnchor in this API reference for fields and examples.
datasets[].keywords[]array<string>Dataset discovery keywords used in Dataset JSON-LD.
datasets[].licensestringAlways "CC BY 4.0".
datasets[].attributionstringThe credit to use: "Visa Atlas".
datasets[].primarySourceNotestringReminder that every figure links its official source.
catalogJsonldobjectschema.org DataCatalog object tying every public dataset to the canonical /data catalog.
jsonld[]array<object>A schema.org Dataset object per dataset (name, description, license, creator, distribution; the Express Entry entries also carry dates + sourceOrganization).

Example response

{
  "datasets": [
    {
      "path": "/api/public/fees",
      "title": "Visa and immigration fees",
      "description": "Government-published fee breakdowns by destination and visa route…",
      "recordCount": 37,
      "dateModified": "2026-06-01",
      "category": "figures",
      "humanPath": "/fees",
      "apiDocsPath": "/api#fees",
      "keywords": ["visa fees", "government fees", "immigration costs"],
      "license": "CC BY 4.0",
      "attribution": "Visa Atlas",
      "primarySourceNote": "Every figure links to its official government primary source…"
    }
    // …visas, destinations, policy-updates, salary-thresholds, processing-times, express-entry-draws
  ],
  "catalogJsonld": {
    "@context": "https://schema.org",
    "@type": "DataCatalog",
    "@id": "https://visaatlas.org/data#catalog",
    "name": "Visa Atlas public immigration data catalog",
    "url": "https://visaatlas.org/data",
    "dataset": [
      { "@type": "Dataset", "@id": "https://visaatlas.org/api/public/fees#dataset" }
    ]
  },
  "jsonld": [
    {
      "@context": "https://schema.org",
      "@type": "Dataset",
      "name": "Visa and immigration fees",
      "license": "https://creativecommons.org/licenses/by/4.0/",
      "url": "https://visaatlas.org/api/public/fees",
      "creator": { "@type": "Organization", "name": "Visa Atlas" }
    }
    // …
  ]
}

Indexable page manifest

GET /api/public/indexable-pagesopen live

Returns object · 7,379 URLs

Audit mirror of the XML sitemap. Use it to reconcile the public indexability surface by page cohort, priority, change frequency, freshness date and the public datasets that audit each cohort.

Fields

FieldTypeDescription
versionstring (ISO date)Manifest contract version.
datasetUrlstring (URL)Canonical JSON endpoint for this manifest.
sitemapUrlstring (URL)Canonical XML sitemap the rows mirror.
summary.totalPagesnumberNumber of URLs emitted by the sitemap builder.
summary.pagesWithLastModifiednumberRows carrying an explicit lastModified date.
summary.highPriorityPagesnumberRows with priority >= 0.8.
summary.cohorts[]array<object>Counts by page cohort, e.g. visa-route, country-comparison, research and open-data.
pages[]array<object>One row per sitemap URL.
pages[].urlstring (URL)Absolute canonical URL.
pages[].pathstringURL path for joins against route templates and crawl logs.
pages[].cohortstringIndexability cohort assigned from the path pattern.
pages[].changeFrequencystring?Sitemap changeFrequency value, where set.
pages[].prioritynumber?Sitemap priority value, where set.
pages[].lastModifiedstring?Sitemap lastModified date, normalized to YYYY-MM-DD.
pages[].sourceDatasets[]array<string>Public JSON datasets that best audit the page cohort.

Example response

{
  "name": "Visa Atlas indexable page manifest",
  "datasetUrl": "https://visaatlas.org/api/public/indexable-pages",
  "sitemapUrl": "https://visaatlas.org/sitemap.xml",
  "count": 7379,
  "summary": {
    "totalPages": 7379,
    "pagesWithLastModified": 7209,
    "highPriorityPages": 1934,
    "cohorts": [
      { "cohort": "country-comparison", "count": 3371 }
    ]
  },
  "pages": [
    {
      "url": "https://visaatlas.org/visas/uk/skilled-worker",
      "path": "/visas/uk/skilled-worker",
      "cohort": "visa-route",
      "changeFrequency": "weekly",
      "priority": 0.9,
      "lastModified": "2026-04-18",
      "sourceDatasets": ["/api/public/visas", "/api/public/destinations"]
    }
  ]
}
  • This feed proves indexability intent. It does not replace a live crawl, Search Console coverage export or ranking measurement.
  • Rows are generated from the same buildSitemapEntries() function used by /sitemap.xml, so drift between XML and JSON is auditable.

Public site search index

GET /api/public/search-indexopen live

Returns object · 1,986 entries

Compact title, description, URL and keyword map for searchable Visa Atlas pages. Use it when an agent, integration or internal tool needs to find the best destination, visa, calculator, data page, research report, policy update, route guide, ranking or best-of guide without scraping the HTML search page.

Fields

FieldTypeDescription
versionstring (ISO date)Search-index contract version.
datasetUrlstring (URL)Canonical JSON endpoint for this index.
humanUrlstring (URL)Human search page backed by the same index builder.
summary.byKindobjectCounts by searchable kind: Visa, Destination, Nationality, Route, Guide, Ranking, Calculator, Data, Research and Policy.
sourceDatasets[]array<string>Public datasets that audit or explain the indexed URL set.
items[]array<object>One searchable item per public page or page family target.
items[].idstringStable search-row identifier.
items[].kindstringSearchable item kind.
items[].titlestringHuman-readable title.
items[].descriptionstringShort summary used by search and agent retrieval.
items[].pathstringCanonical path on visaatlas.org.
items[].urlstring (URL)Absolute canonical URL.
items[].keywords[]array<string>Compact search and retrieval tokens.
items[].sourceDatasets[]array<string>Public datasets that best audit the row.

Example response

{
  "name": "Visa Atlas public site search index",
  "datasetUrl": "https://visaatlas.org/api/public/search-index",
  "humanUrl": "https://visaatlas.org/search",
  "count": 1986,
  "summary": {
    "byKind": {"Visa":1414,"Destination":233,"Nationality":42,"Route":17,"Guide":6,"Ranking":6,"Calculator":8,"Data":202,"Research":21,"Policy":37}
  },
  "items": [
    {
      "id": "visa-as-employment-based-residency-petition",
      "kind": "Visa",
      "title": "American Samoa (United States territory) - Employment-Based Residency Petition",
      "path": "/visas/american-samoa/employment-based-residency-petition",
      "sourceDatasets": ["/api/public/visas", "/api/public/destinations"]
    }
  ]
}
  • This is a retrieval and navigation index, not a Search Console export or ranking signal.
  • Use /api/public/indexable-pages when you need the complete sitemap-backed indexability manifest.

Visa routes

GET /api/public/visasopen live

Returns array<object> · 1414 routes

Every visa route we cover, as a flat list. Each entry is a summary card — the full eligibility, pathway and FAQ content lives on the route page linked via the destination + slug.

Fields

FieldTypeDescription
destinationstringDestination key (lowercase, e.g. "uk", "ca", "de").
slugstringRoute slug; combine with destination to build the page URL /visas/{destination}/{slug}.
namestringOfficial route name.
categorystringRoute family, e.g. "work-sponsored", "work-unsponsored", "study", "family", "investor", "digital-nomad".
summarystringOne-sentence description.
sponsorshipRequiredbooleanWhether an employer/sponsor is required.
leadsToSettlementbooleanWhether the route is a recognised pathway to permanent residence.
typicalDurationstringInitial grant length and extension/settlement note.
primarySourceobjectOfficial source: { label, url, authority, lastVerified }.
lastReviewedstring (ISO date)When we last reviewed this route.

Example response

[
  {
    "destination": "uk",
    "slug": "skilled-worker",
    "name": "Skilled Worker visa",
    "category": "work-sponsored",
    "summary": "Work visa for non-UK workers with a job offer from a Home Office–licensed sponsor…",
    "sponsorshipRequired": true,
    "leadsToSettlement": true,
    "typicalDuration": "Up to 5 years on initial grant, extendable; leads to settlement…",
    "primarySource": {
      "label": "GOV.UK — Skilled Worker visa",
      "url": "https://www.gov.uk/skilled-worker-visa",
      "authority": "UK Home Office",
      "lastVerified": "2026-04-18"
    },
    "lastReviewed": "2026-04-18"
  }
]

Destinations

GET /api/public/destinationsopen live

Returns array<object> · 233 destinations

The countries we cover, with their official immigration portal and the bodies that regulate immigration advice there.

Fields

FieldTypeDescription
isostringOur internal destination key, lowercase. Note these are not always ISO-3166 (we use "uk", not "gb").
slugstringURL slug for /visas/{slug} and related pages.
namestringLong official country name.
regionstringRegion grouping, e.g. "europe", "north-america", "asia-pacific", "middle-east".
flagstringFlag emoji.
govPortalstring (URL)The official government immigration portal.
regulators[]array<object>Advice regulators: { name, abbreviation, url, scope }.

Example response

[
  {
    "iso": "uk",
    "slug": "uk",
    "name": "United Kingdom of Great Britain and Northern Ireland",
    "region": "europe",
    "flag": "🇬🇧",
    "govPortal": "https://www.gov.uk/browse/visas-immigration",
    "regulators": [
      {
        "name": "Immigration Advice Authority",
        "abbreviation": "IAA",
        "url": "https://www.gov.uk/government/organisations/immigration-advice-authority",
        "scope": "Regulates non-solicitor immigration advisers in the UK…"
      }
    ]
  }
]

Policy updates

GET /api/public/policy-updatesopen live

Returns array<object> · 37 updates

Dated immigration policy changes with atomic claims, affected route slugs, status, severity and the primary government source behind each update.

Fields

FieldTypeDescription
idstringStable update ID.
titlestringHuman-readable headline.
datestring (ISO date)Announcement or publication date.
effectiveDatestring (ISO date)?Effective date when different from the announcement date.
destinationstringDestination key affected by the change.
summarystringOne-sentence summary.
claims[]array<object>Atomic factual claims: { statement }.
primarySourceobjectOfficial source: { label, url, authority, lastVerified }.
affectedVisas[]array<string>?Visa slugs touched by the update.
severitystringminor, material or significant.
statusstringannounced, consulting, scheduled or in-force.
lastReviewedstring (ISO date)Last editorial/source review date.

Example response

[
  {
    "id": "uk-2024-04-skilled-worker-salary-rise",
    "title": "UK raises Skilled Worker salary thresholds",
    "date": "2024-04-04",
    "effectiveDate": "2024-04-04",
    "destination": "uk",
    "summary": "The Home Office raised the Skilled Worker general salary threshold...",
    "claims": [{ "statement": "General salary threshold raised to GBP 38,700 for new Skilled Worker applications." }],
    "primarySource": {
      "label": "UK - Statement of Changes HC 590 (March 2024)",
      "url": "https://www.gov.uk/government/collections/immigration-rules-statement-of-changes",
      "authority": "UK Home Office",
      "lastVerified": "2026-06-01"
    },
    "affectedVisas": ["skilled-worker"],
    "severity": "significant",
    "status": "in-force",
    "lastReviewed": "2026-06-01"
  }
]

Policy claims

GET /api/public/policy-claimsopen live

Returns object · 115 claims

Claim-level feed for AI retrievers and auditors: each record is one atomic policy claim with a stable URL, parent update, affected routes and the supporting source behind the claim.

Fields

FieldTypeDescription
lastModifiedstring (ISO date)Most recent policy-claim review date in the feed.
countnumberNumber of claim records.
claims[]array<object>One atomic policy claim per row, newest updates first.
claims[].claimIdstringStable ID in the form {policyUpdateId}#claim-{n}.
claims[].claimUrlstringCanonical URL fragment for the visible claim card.
claims[].statementstringThe claim text, designed to be quoted with its source.
claims[].updateIdstringParent policy update ID.
claims[].updateTitlestringParent policy update title.
claims[].updateUrlstringCanonical parent policy update URL.
claims[].destinationIsostringDestination affected by the policy update.
claims[].destinationNamestringHuman-readable destination name.
claims[].datestring (ISO date)Announcement or publication date of the parent update.
claims[].effectiveDatestring (ISO date)?Effective date when known.
claims[].statusstringannounced, consulting, scheduled or in-force.
claims[].severitystringminor, material or significant.
claims[].affectedVisas[]array<object>Affected routes with slug, name and canonical URL.
claims[].sourceobjectSupporting source: { label, url, authority, lastVerified }.
claims[].lastReviewedstring (ISO date)Last editorial/source review date.

Example response

{
  "lastModified": "2026-06-27",
  "count": 115,
  "claims": [
    {
      "claimId": "uk-2025-07-skilled-worker-reforms#claim-1",
      "claimUrl": "https://visaatlas.org/policy-updates/uk-2025-07-skilled-worker-reforms#claim-1",
      "statement": "The Skilled Worker general salary threshold rose to GBP 41,700.",
      "updateId": "uk-2025-07-skilled-worker-reforms",
      "destinationIso": "uk",
      "destinationName": "United Kingdom of Great Britain and Northern Ireland",
      "date": "2025-07-22",
      "effectiveDate": "2025-07-22",
      "status": "in-force",
      "severity": "significant",
      "affectedVisas": [{ "slug": "skilled-worker", "name": "Skilled Worker visa", "url": "https://visaatlas.org/visas/uk/skilled-worker" }],
      "source": {
        "label": "GOV.UK - Statement of changes to the Immigration Rules: HC 997",
        "url": "https://www.gov.uk/government/publications/statement-of-changes-to-the-immigration-rules-hc-997-july-2025",
        "authority": "UK Home Office",
        "lastVerified": "2026-07-01"
      },
      "lastReviewed": "2026-07-01"
    }
  ]
}
  • Use claimUrl when citing a single policy fact; use updateUrl when citing the whole policy update.
  • The source object is the government source that supports the claim. Visa Atlas is the compiler, not the issuing authority.

Citation packs

GET /api/public/citation-packsopen live

Returns object · 162 packets

Compact, source-linked answer packets for AI retrievers, journalists, researchers and auditors. Each packet turns an existing verified cost model, calculator verdict context, Express Entry draw, best-guide, visa-route, page-level answer, fee answer, processing-time answer, salary-threshold answer, settlement answer, research report, policy claim or fact-change record into a citable answer with canonical page URL, dataset URL, source URLs, date modified, license and suggested citation.

Fields

FieldTypeDescription
lastModifiedstring (ISO date)Freshest date modified across all packets.
countnumberNumber of packets in the feed.
datasetUrlstring (URL)Canonical JSON endpoint URL for the citation-pack dataset.
licensestringAlways "CC BY 4.0".
attributionstringThe credit to use: "Visa Atlas".
legalNotestringReminder that the packet is compiled data, not legal advice.
packs[]array<object>Citation packets, grouped by kind in the human page.
packs[].idstringStable fragment ID for /citation-packs#{id}.
packs[].kindstringcost-to-complete, calculator-verdict, express-entry, best-guide, visa-route, page-answer, fee, processing-time, salary-threshold, settlement, research-report, policy-claim or fact-change.
packs[].answerstringShort answer designed to be quoted with its source chain.
packs[].canonicalPageUrlstring (URL)Human page or claim anchor that provides context.
packs[].datasetUrlstring (URL)Underlying source dataset behind the packet.
packs[].facts[]array<object>Structured facts: { label, value, note?, sourceUrls[] }.
packs[].sources[]array<object>Source records: { label, url, authority?, lastVerified? }.
packs[].suggestedCitationstringReady-to-copy citation for the packet.

Example response

{
  "lastModified": "2026-07-15",
  "count": 162,
  "datasetUrl": "https://visaatlas.org/api/public/citation-packs",
  "license": "CC BY 4.0",
  "attribution": "Visa Atlas",
  "packs": [
    {
      "id": "express-entry-latest-draw",
      "kind": "express-entry",
      "title": "Latest Canada Express Entry draw",
      "answer": "The latest tracked Canada Express Entry draw is round 426...",
      "url": "https://visaatlas.org/citation-packs#express-entry-latest-draw",
      "canonicalPageUrl": "https://visaatlas.org/research/canada-express-entry-draw-tracker",
      "datasetUrl": "https://visaatlas.org/api/public/express-entry-draws",
      "facts": [{ "label": "CRS cut-off", "value": "392", "sourceUrls": ["https://www.canada.ca/..."] }],
      "sources": [{ "label": "IRCC - Express Entry rounds of invitations", "authority": "Immigration, Refugees and Citizenship Canada" }],
      "suggestedCitation": "Visa Atlas, \"Latest Canada Express Entry draw\", ..."
    },
    {
      "id": "calculator-verdict-canada-crs",
      "kind": "calculator-verdict",
      "title": "Canada CRS calculator verdict context",
      "canonicalPageUrl": "https://visaatlas.org/calculators/canada-crs",
      "datasetUrl": "https://visaatlas.org/api/public/calculator-verdict-contexts"
    }
  ]
}
  • Use /citation-packs#{id} for a compact human citation anchor and canonicalPageUrl when more context is needed.
  • Calculator-verdict citation packs are derived from /api/public/calculator-verdict-contexts and should keep the linked official source URLs with the calculator interpretation.
  • Page-answer citation packs are derived from /api/public/answer-capsules and preserve the page-level verified answer as a citable packet.
  • Strategic fee, processing-time, salary-threshold, settlement and visa-route citation packs are derived from /api/public/answer-capsules for SEO/GEO target pages.
  • Citation packs are derived from existing verified datasets; do not treat them as a separate legal authority.

Verified answer capsules

GET /api/public/answer-capsulesopen live

Returns object · 292 capsules

Question-answer records extracted from rendered Visa Atlas verified-answer blocks. Use this endpoint when you need the concise answer layer attached to source URLs, canonical pages, dataset URLs, review dates, license and legal-scope notes.

Fields

FieldTypeDescription
versionstring (ISO date)Dataset version date.
namestringHuman dataset name.
descriptionstringWhat the answer-capsule feed contains.
datasetUrlstring (URL)Canonical JSON endpoint URL.
humanUrlstring (URL)Crawlable human index for the same records.
countnumberNumber of answer capsules.
lastModifiedstring (ISO date)Freshest source review date across all capsules.
licensestringAlways "CC BY 4.0".
attributionstringThe credit to use: "Visa Atlas".
legalNotestringReminder that capsules are compiled data, not legal advice.
methodology[]array<string>How the capsule feed is generated and limited.
summary.kinds[]array<object>Counts by capsule kind.
summary.sourceUrlCountnumberUnique source URL count.
summary.canonicalPageCountnumberUnique canonical page count.
capsules[]array<object>One source-linked short answer per rendered answer block.
capsules[].idstringStable fragment ID for /answer-capsules#{id}.
capsules[].kindstringfee, processing-time, salary-threshold, cost-to-complete, calculator-verdict, express-entry, settlement, timeline, best-guide, topic-cluster, visa-route, page-answer or research-report.
capsules[].questionstringThe question the answer block addresses.
capsules[].answerstringShort answer designed for quotation with source chain attached.
capsules[].pagePathstringSite-relative page path containing the answer block.
capsules[].canonicalPageUrlstring (URL)Absolute canonical page URL.
capsules[].datasetUrls[]array<string>Supporting public JSON datasets or source index pages.
capsules[].sourceUrls[]array<string>Government or authoritative source URLs supporting the answer.
capsules[].sources[]array<object>Source objects: { label, url, authority?, lastVerified }.
capsules[].dateModifiedstring (ISO date)Source review date for the capsule.
capsules[].renderedSelectorstringRendered-page marker, currently "[data-verified-answer]".
capsules[].suggestedCitationstringReady-to-copy citation for the capsule.

Example response

{
  "version": "2026-07-04",
  "name": "Verified answer capsules",
  "datasetUrl": "https://visaatlas.org/api/public/answer-capsules",
  "humanUrl": "https://visaatlas.org/answer-capsules",
  "count": 292,
  "lastModified": "2026-07-17",
  "summary": {
    "kinds": [{ "kind": "fee", "count": 37 }],
    "sourceUrlCount": 1109,
    "canonicalPageCount": 292
  },
  "capsules": [
    {
      "id": "fee-uk-skilled-worker",
      "kind": "fee",
      "question": "How much does the Skilled Worker visa cost in United Kingdom?",
      "answer": "The UK Skilled Worker visa costs around GBP 3,950...",
      "pagePath": "/fees/uk/skilled-worker",
      "canonicalPageUrl": "https://visaatlas.org/fees/uk/skilled-worker",
      "datasetUrls": ["https://visaatlas.org/api/public/fees"],
      "sourceUrls": ["https://www.gov.uk/skilled-worker-visa/how-much-it-costs"],
      "sources": [{ "label": "GOV.UK - Skilled Worker visa: how much it costs", "lastVerified": "2026-06-01" }],
      "dateModified": "2026-06-01",
      "renderedSelector": "[data-verified-answer]",
      "suggestedCitation": "Visa Atlas, \"How much does the Skilled Worker visa cost in United Kingdom?\", ..."
    }
  ]
}
  • Use /answer-capsules#{id} for the compact human anchor and canonicalPageUrl for the full page context.
  • Answer capsules are derived from existing source-linked pages and datasets; do not treat them as a separate legal authority.

AI citation benchmark

GET /api/public/citation-benchmarkopen live

Returns object · 48 benchmark questions; 7 accuracy answer-key prompts

Fixed high-intent skilled-migration question basket used by the offline citation-share monitor. Each question includes the user prompt, priority, topic, target Visa Atlas pages and source datasets expected to support the answer.

Fields

FieldTypeDescription
versionstring (ISO date)Benchmark version date.
namestringHuman benchmark name.
descriptionstringWhat the benchmark measures.
domainstringBrand domain the monitor detects in answer citations.
licensestringAlways "CC BY 4.0".
attributionstringThe credit to use: "Visa Atlas".
countnumberNumber of questions in the benchmark basket.
accuracyAnswerKeyobjectConservative machine-checkable answer key used by --grade mode.
accuracyAnswerKey.countnumberNumber of benchmark prompts with accuracy keys.
accuracyAnswerKey.methodology[]array<string>Limits on automated grading and required human review.
accuracyAnswerKey.keys[]array<object>One answer-key row per machine-gradable benchmark prompt.
accuracyAnswerKey.keys[].expectedFacts[]array<object>Accepted current facts and whether each fact is required for a pass.
accuracyAnswerKey.keys[].staleOrWrongClaims[]array<string>Known stale or wrong values that should fail the row.
questions[]array<object>One benchmark prompt per row.
questions[].idstringStable prompt ID used in monitor logs.
questions[].destinationstringCountry or route group the question targets.
questions[].topicstringIntent bucket, e.g. salary-threshold, cost-to-complete or settlement.
questions[].prioritystringBenchmark priority: high, medium or low.
questions[].questionstringExact prompt text sent to configured answer engines.
questions[].targetUrls[]array<string>Visa Atlas pages that should be cite-worthy for this prompt.
questions[].sourceDatasets[]array<string>Public JSON datasets that support the underlying facts.

Example response

{
  "version": "2026-07-02",
  "name": "Visa Atlas AI citation benchmark",
  "domain": "visaatlas.org",
  "license": "CC BY 4.0",
  "attribution": "Visa Atlas",
  "count": 48,
  "accuracyAnswerKey": {
    "version": "2026-07-02",
    "count": 7,
    "keys": [
      {
        "id": "de-blue-card-salary",
        "expectedFacts": [{ "label": "2026 general EU Blue Card threshold", "required": true }],
        "staleOrWrongClaims": ["EUR 48,300"]
      }
    ]
  },
  "questions": [
    {
      "id": "de-blue-card-salary",
      "destination": "Germany",
      "topic": "salary-threshold",
      "priority": "high",
      "question": "What is the Germany EU Blue Card minimum salary threshold for 2026?",
      "targetUrls": ["/salary-thresholds/germany", "/cost-to-complete/germany-eu-blue-card"],
      "sourceDatasets": ["/api/public/salary-thresholds", "/api/public/cost-to-complete"]
    }
  ]
}
  • The endpoint publishes benchmark prompts, target URLs and the conservative answer key; it does not store model responses or API keys.
  • Use npm run kpi:citation-share to run the benchmark locally against configured answer engines.
  • Use npm run kpi:citation-accuracy to run the same benchmark with conservative answer-key grading; partial or failed rows need human review.

AI retrieval task index

GET /api/public/ai-retrieval-task-indexopen live

Returns object · 48 retrieval tasks

Query-level retrieval contract derived from the fixed citation benchmark. Each task joins a high-intent immigration question to canonical pages, answer capsules, citation packs, calculator verdict contexts, SEO/GEO page actions, competitor battlecards, MCP tools, safe-answer rules and evidence gates.

Fields

FieldTypeDescription
versionstring (ISO date)Retrieval-index version date.
namestringHuman dataset name.
descriptionstringWhat the retrieval index covers.
licensestringAlways "CC BY 4.0".
attributionstringThe credit to use: "Visa Atlas".
datasetUrlstringCanonical JSON endpoint for the task index.
humanUrlstringCrawlable report page explaining the index.
sourceDatasets[]array<string>Public datasets used to derive and audit task rows.
methodology.sourceOfTruthstringHow rows are generated from the fixed citation benchmark.
methodology.joinRules[]array<string>Exact join rules for answer capsules, citation packs, calculator contexts, page actions and battlecards.
methodology.retrievalStandardstringHow an AI retriever should use the row before composing an answer.
methodology.privateEvidencePolicystringBoundary for raw AI transcripts, GSC queries, SERP screenshots, analytics, referral logs and reviewer evidence.
summary.taskCountnumberNumber of benchmark questions converted to retrieval tasks.
summary.rowsWithAnswerCapsulesnumberTask rows with joined answer capsules.
summary.rowsWithCitationPacksnumberTask rows with joined citation packs.
summary.rowsWithCalculatorContextsnumberTask rows with joined calculator verdict contexts.
summary.rowsWithPageActionsnumberTask rows with joined SEO/GEO page actions.
summary.rowsWithCompetitorBattlecardsnumberTask rows with joined competitor battlecards.
summary.publicMarketShareClaimAllowedbooleanAlways false until approved aggregate evidence exists.
rows[]array<object>One benchmark prompt plus its public retrieval assets.
rows[].idstringStable benchmark prompt ID.
rows[].questionstringHigh-intent immigration question.
rows[].benchmarkTargetUrls[]array<string>Canonical Visa Atlas pages expected to support the answer.
rows[].retrievalPages[]array<string>Union of benchmark targets and joined canonical pages.
rows[].mcpTools[]array<string>Read-only MCP tools relevant to this task.
rows[].retrievalOrder[]array<object>Recommended public retrieval sequence.
rows[].answerCapsules[]array<object>Matched short answer atoms, with source URLs and dates.
rows[].citationPacks[]array<object>Matched citation packets and compact facts.
rows[].calculatorContexts[]array<object>Matched calculator verdict context and caveats.
rows[].pageActions[]array<object>Matched production-control rows and claim gates.
rows[].competitorBattlecards[]array<object>Matched competitor battlecards, wedge and answer format.
rows[].safeAnswerRules[]array<string>Rules that stop unsupported legal, ranking, traffic or market-share claims.
rows[].evidenceGates[]array<string>Local checks and gates before outcome claims.

Example response

{
  "version": "2026-07-04",
  "name": "Visa Atlas AI retrieval task index",
  "datasetUrl": "/api/public/ai-retrieval-task-index",
  "humanUrl": "/research/ai-retrieval-task-index-2026",
  "summary": {
    "taskCount": 48,
    "rowsWithAnswerCapsules": 48,
    "rowsWithCitationPacks": 48,
    "rowsWithCalculatorContexts": 11,
    "publicMarketShareClaimAllowed": false
  },
  "rows": [
    {
      "id": "de-blue-card-salary",
      "question": "What is the Germany EU Blue Card minimum salary threshold for 2026?",
      "benchmarkTargetUrls": ["/salary-thresholds/germany","/cost-to-complete/germany-eu-blue-card","/routes/eu-blue-card-vs-chancenkarte-germany"],
      "mcpTools": ["list_ai_retrieval_tasks","list_answer_capsules","list_citation_packs","list_seo_geo_page_action_map","list_competitor_battlecards","list_seo_geo_dominance_gap_ledger"],
      "answerCapsules": ["cost-germany-eu-blue-card","page-route-eu-blue-card-vs-chancenkarte-germany","salary-germany"],
      "citationPacks": ["cost-germany-eu-blue-card","page-answer-page-route-eu-blue-card-vs-chancenkarte-germany","answer-capsule-salary-germany"],
      "safeAnswerRules": ["Use the latest matched answer capsule or citation pack first; preserve its official source URLs and dateModified/lastVerified fields.","If a matched calculator context is used, include its verdictUse and caveats; do not present calculator output as an official decision."]
    }
  ]
}
  • Use this endpoint when a crawler or AI agent starts with a user question and needs the exact Visa Atlas pages, atoms and tools to retrieve.
  • This endpoint is a retrieval and citation map, not proof of current rankings, traffic, citations, backlinks or market share.
  • Raw AI transcripts, Search Console data, SERP screenshots and analytics stay local unless separately reviewed and aggregated.

AI retrieval readiness scorecard

GET /api/public/ai-retrieval-readinessopen live

Returns object · 48 prompt readiness rows

Prompt-level gap scorecard derived from the AI retrieval task index. Each row ranks a benchmark question by answer capsule, citation pack, page action, battlecard, calculator context, MCP tool depth, safe-answer rule and evidence-gate coverage.

Fields

FieldTypeDescription
versionstring (ISO date)Readiness-scorecard version date.
namestringHuman dataset name.
descriptionstringWhat the readiness scorecard covers.
licensestringAlways "CC BY 4.0".
attributionstringThe credit to use: "Visa Atlas".
datasetUrlstringCanonical JSON endpoint for the scorecard.
humanUrlstringCrawlable report page explaining scoring and gap priorities.
sourceDatasets[]array<string>Public datasets used to derive prompt readiness rows.
methodology.sourceOfTruthstringHow rows are derived from the AI retrieval task index.
methodology.scoringModel[]array<string>Weights for answer capsules, citation packs, page actions, battlecards, calculator contexts, MCP tools and gates.
methodology.statusRules[]array<string>Score bands for retrieval-ready, nearly-ready, asset-gap and critical-gap rows.
methodology.privateEvidencePolicystringBoundary for raw AI transcripts, GSC queries, SERP screenshots, analytics, referral logs and reviewer evidence.
summary.taskCountnumberNumber of benchmark prompts scored.
summary.retrievalReadyCountnumberRows scoring at least 95.
summary.openGapCountnumberRows below retrieval-ready status.
summary.highPriorityOpenGapCountnumberHigh-priority benchmark prompts below retrieval-ready status.
summary.criticalGapCountnumberRows scoring below 60.
summary.rowsMissingAnswerCapsulesnumberRows without a joined verified answer capsule.
summary.rowsMissingCitationPacksnumberRows without a joined citation pack.
summary.rowsMissingPageActionsnumberRows without a joined SEO/GEO page action row.
summary.rowsMissingCompetitorBattlecardsnumberRows without a joined competitor battlecard.
summary.publicMarketShareClaimAllowedbooleanAlways false until approved aggregate evidence exists.
rows[]array<object>One ranked benchmark prompt readiness row.
rows[].gapRanknumberRank by status, prompt priority and score.
rows[].readinessStatusstringretrieval-ready, nearly-ready, asset-gap or critical-gap.
rows[].readinessScorenumberWeighted score from 0 to 100.
rows[].missingAssets[]array<string>Missing public retrieval asset classes.
rows[].nextActions[]array<string>Public asset work needed before rerunning measurement.
rows[].coverageobjectCounts of joined answer capsules, citation packs, page actions, battlecards, datasets, MCP tools and gates.
rows[].checks[]array<object>Per-check weight, pass/fail evidence and remediation.
rows[].mcpTools[]array<string>Read-only MCP tools relevant to the row.
rows[].evidenceGates[]array<string>Local checks and gates before outcome claims.

Example response

{
  "version": "2026-07-05",
  "name": "Visa Atlas AI retrieval readiness scorecard",
  "datasetUrl": "/api/public/ai-retrieval-readiness",
  "humanUrl": "/research/ai-retrieval-readiness-scorecard-2026",
  "summary": {
    "taskCount": 48,
    "retrievalReadyCount": 48,
    "openGapCount": 0,
    "criticalGapCount": 0,
    "rowsMissingAnswerCapsules": 0,
    "rowsMissingCitationPacks": 0,
    "rowsMissingCompetitorBattlecards": 0,
    "publicMarketShareClaimAllowed": false
  },
  "rows": [
    {
      "gapRank": 1,
      "id": "de-blue-card-salary",
      "readinessStatus": "retrieval-ready",
      "readinessScore": 100,
      "missingAssets": [],
      "nextActions": ["Keep answer capsules, citation packs, source URLs and page-action evidence fresh before rerunning citation-share measurement.","Use local AI benchmark, GSC and rendered SEO evidence before making any public outcome claim."]
    }
  ]
}
  • Use this endpoint after the AI retrieval task index when deciding which prompt rows need public answer, citation, page-action or battlecard work next.
  • This endpoint is a public asset-coverage scorecard, not proof of current rankings, traffic, citations, backlinks or market share.
  • Raw AI transcripts, Search Console data, SERP screenshots and analytics stay local unless separately reviewed and aggregated.

AI answer accuracy audit protocol

GET /api/public/ai-answer-accuracy-auditopen live

Returns object · 7 audit targets

Public protocol for grading high-risk AI immigration answers against source-backed Visa Atlas facts. It packages the conservative answer-key coverage, stale-claim traps, local commands, private-data rules and publication guardrails behind the AI accuracy audit franchise.

Fields

FieldTypeDescription
versionstring (ISO date)Protocol version.
datasetUrlstring (URL)Canonical JSON endpoint for the protocol.
humanUrlstring (URL)Crawlable research report explaining the protocol.
summary.benchmarkQuestionCountnumberTotal prompts in the public citation benchmark.
summary.answerKeyCountnumberPrompts with machine-checkable answer-key rows.
summary.requiredFactCountnumberRequired facts checked across the answer-key targets.
summary.staleClaimTrapCountnumberKnown stale or wrong values that should fail a machine grade.
methodology.gradingPolicystringConservative pass/partial/fail grading rule.
methodology.privateDataPolicystringWhich evidence remains local until reviewed.
methodology.publicationGuardrails[]array<string>Rules for publishing reviewed results.
methodology.commands[]array<string>Local commands for running the audit workflow.
targets[]array<object>One machine-gradable high-risk prompt per row.
targets[].questionstringBenchmark prompt.
targets[].requiredFacts[]array<object>Required current facts and accepted matching examples.
targets[].staleOrWrongClaims[]array<string>Known stale values or wrong claims.
targets[].sourceUrls[]array<string>Visa Atlas and external source URLs used by the answer key.

Example response

{
  "version": "2026-07-03",
  "name": "Visa Atlas AI answer accuracy audit protocol",
  "datasetUrl": "https://visaatlas.org/api/public/ai-answer-accuracy-audit",
  "humanUrl": "https://visaatlas.org/research/ai-answer-accuracy-audit-2026",
  "summary": {
    "benchmarkQuestionCount": 48,
    "answerKeyCount": 7,
    "requiredFactCount": 11,
    "staleClaimTrapCount": 31
  },
  "targets": [
    {
      "id": "de-blue-card-salary",
      "auditRisk": "current-figure",
      "requiredFacts": [
        { "label": "2026 general EU Blue Card threshold" }
      ],
      "staleOrWrongClaims": ["EUR 48,300"]
    }
  ]
}
  • This endpoint publishes the grading protocol and answer-key coverage, not live model accuracy results.
  • Raw model answers, API responses and reviewer notes stay local until separately reviewed and redacted.
  • Use npm run kpi:citation-accuracy for local grading and /api/public/citation-benchmark for the full benchmark basket.

Source transparency benchmark

GET /api/public/source-transparency-benchmarkopen live

Returns object · 7 sampled surfaces

Competitor/source-class benchmark comparing sampled public immigration-information surfaces against source transparency, freshness, open-data and AI-retrieval criteria. It is designed to make the Visa Atlas wedge auditable without overclaiming about full competitor sites.

Fields

FieldTypeDescription
versionstring (ISO date)Benchmark version and sample date.
namestringHuman benchmark name.
descriptionstringWhat the benchmark measures.
methodologystringSampling method and not-observed caveat.
recrawlPolicy.recheckSlaDaysnumberMaximum age for competitor public-surface samples before recrawl is required.
recrawlPolicy.claimBoundarystringNo-go boundary for stale competitor wedge or market-share claims.
licensestringAlways "CC BY 4.0".
attributionstringThe credit to use: "Visa Atlas".
countnumberNumber of sampled source surfaces.
summary.overdueSampleCountnumberCount of competitor samples past the recrawl SLA.
summary.publicMarketShareClaimAllowedbooleanAlways false for this planning benchmark.
criteria[]array<object>Transparency criteria used to score each sample.
criteria[].idstringStable criterion ID used in sample criteria maps.
criteria[].labelstringHuman criterion label.
criteria[].descriptionstringCriterion definition.
samples[]array<object>One sampled source surface per row.
samples[].idstringStable sample ID.
samples[].namestringSampled site or source-class name.
samples[].archetypestringCompetitor/source-class archetype.
samples[].websiteUrlstring (URL)Primary sampled URL.
samples[].checkedOnstring (ISO date)Date the public surface was sampled.
samples[].checkedAgeDaysnumberAge of the sample relative to the benchmark version date.
samples[].recrawlDueOnstring (ISO date)Latest acceptable recrawl date for the sample.
samples[].recrawlStatusstringfresh, due-soon or overdue.
samples[].strengths[]array<string>Observed strengths from the sampled public surface.
samples[].observedGaps[]array<string>Observed gaps against the benchmark criteria.
samples[].evidenceUrls[]array<string>Sampled evidence URLs.
samples[].criteriaobjectCriterion status map: yes, partial, not-observed or not-applicable.
samples[].scorenumberComputed score: yes=2, partial=1, otherwise 0.
samples[].maxScorenumberMaximum possible score for the criteria set.

Example response

{
  "version": "2026-07-04",
  "name": "Immigration source-transparency benchmark",
  "recrawlPolicy": {
    "recheckSlaDays": 45
  },
  "summary": {
    "overdueSampleCount": 0,
    "publicMarketShareClaimAllowed": false
  },
  "count": 7,
  "criteria": [
    {
      "id": "primary-source-proximity",
      "label": "Primary-source proximity",
      "description": "Rules, fees or thresholds visibly point readers back to the issuing government authority."
    }
  ],
  "samples": [
    {
      "id": "visaatlas",
      "name": "Visa Atlas",
      "archetype": "Open skilled-migration data layer",
      "checkedAgeDays": 0,
      "recrawlDueOn": "2026-08-18",
      "recrawlStatus": "fresh",
      "score": 16,
      "maxScore": 16,
      "criteria": {
        "open-json-data": "yes",
        "ai-retrieval-contract": "yes",
        "change-feed": "yes"
      }
    }
  ]
}
  • A not-observed status means the feature was not visible in the sampled public pages, not that it cannot exist elsewhere.
  • Competitor observations should be recrawled within the published SLA before being used for wedge, displacement or market-share claims.
  • Use the human research report for methodology, sample notes and the positioning implication.

SEO/GEO content opportunities

GET /api/public/content-opportunitiesopen live

Returns object · 28 opportunity rows

Auditable roadmap and prioritisation dataset tying Visa Atlas content pieces, page work and technical gates to the 500k/month planning model, source-transparency wedge and public evidence surfaces.

Fields

FieldTypeDescription
versionstring (ISO date)Opportunity-map version date.
namestringHuman dataset name.
descriptionstringWhat the opportunity map covers.
licensestringAlways "CC BY 4.0".
attributionstringThe credit to use: "Visa Atlas".
sourceDatasets[]array<string>Public datasets used to ground the roadmap rows.
methodology.planningTargetMonthlyVisitsnumberPlanning target from the visibility model; not a current traffic claim.
methodology.scoreFormulastringDirectional scoring formula for comparing rows.
methodology.caveats[]array<string>Limits on interpretation and required refresh cadence.
summary.statusCountsobjectCounts by shipped, local-workflow, next and planned status.
summary.executionBriefActionCountnumberNon-shipped rows ranked for next execution.
executionBriefobjectShip-next brief across content, page, technical and evidence work.
executionBrief.topActions[]array<object>Ranked non-shipped opportunities with content, page, technical and evidence moves.
executionBrief.noGoPolicystringOutcome-claim boundary for rankings, traffic, market share and AI-citation claims.
topPriorities[]array<object>Top-scored opportunity rows.
opportunities[]array<object>All roadmap rows, sorted by priority score.
opportunities[].idstringStable row ID used by the research-page fragment URL.
opportunities[].statusstringshipped, local-workflow, next or planned.
opportunities[].pageTargets[]array<string>Public pages or page families affected by the row.
opportunities[].technicalChanges[]array<string>Implementation surfaces or controls attached to the row.
opportunities[].competitorWedgestringObserved positioning gap the row exploits or defends.
opportunities[].sourceDatasets[]array<string>Machine-readable datasets supporting the row.
opportunities[].scoringobjecttrafficLeverage, competitorGap, defensibility, implementationEffort and computed priorityScore.

Example response

{
  "version": "2026-07-03",
  "name": "Visa Atlas SEO/GEO content opportunity map",
  "summary": {
    "count": 28,
    "nextCount": 1,
    "executionBriefActionCount": 13
  },
  "executionBrief": {
    "actionCount": 13,
    "topActionCount": 8,
    "topActions": [
      {
        "rank": 1,
        "opportunityId": "reviewed-page-evidence-publication",
        "status": "next"
      }
    ]
  },
  "topPriorities": [
    {
      "id": "open-data-front-door",
      "title": "Open immigration data front door and JSON catalog",
      "status": "shipped",
      "pageTargets": ["/data","/api"],
      "technicalChanges": ["Dataset/DataDownload JSON-LD","public dataset registry"],
      "sourceDatasets": ["/api/public/source-transparency-benchmark","/api/public/visibility-metrics"],
      "scoring": { "priorityScore": 28 }
    }
  ]
}
  • This endpoint is a planning and prioritisation dataset, not proof of current traffic or ranking outcomes.
  • Rows marked planned still require source verification, page-level QA and rendered SEO/GEO release gates before publication.
  • Use the human research report for methodology, caveats and the full opportunity table.

Competitor query battlecards

GET /api/public/competitor-query-battlecardsopen live

Returns object · 13 battlecards

Query-cluster battlecards tying high-intent SEO/GEO opportunities to sampled competitor archetypes, target pages, source datasets, wedge moves, answer formats, retrieval playbooks, strategic positioning rollups and measurement commands.

Fields

FieldTypeDescription
versionstring (ISO date)Battlecard dataset version date.
namestringHuman dataset name.
descriptionstringWhat the battlecard feed covers.
licensestringAlways "CC BY 4.0".
attributionstringThe credit to use: "Visa Atlas".
sourceDatasets[]array<string>Public datasets used to compile battlecard rows.
methodology.sourceOfTruthstringPublic datasets and benchmarks used to generate the rows.
methodology.caveats[]array<string>Limits on interpreting competitor pressure and query plans.
summaryobjectCounts for battlecards, high-priority rows, competitor samples and citation prompts.
summary.competitorRecrawlSlaDaysnumberMaximum age for sampled competitor observations before recrawl is required.
summary.overdueCompetitorSampleCountnumberCount of unique competitor samples past the recrawl SLA.
positioningobjectStrategic competitor wedge rollup derived from the battlecards and sampled archetype evidence.
positioning.wedgePillars[]array<object>Freshness, cost/threshold, deterministic-tool and AI retrieval/distribution pillars.
positioning.archetypeRollups[]array<object>Sampled competitor archetype strengths, gaps, evidence URLs and Visa Atlas wedge move.
positioning.archetypeRollups[].sampleEvidence[]array<object>Sample IDs, checked dates, recrawl metadata, websites and evidence URLs behind the archetype rollup.
positioning.capturePriorities[]array<object>Sequenced SEO/GEO sprints with page, technical and evidence work.
positioning.evidenceClaimBoundaries[]array<string>No-go boundaries that block unsupported ranking, traffic or market-share claims.
battlecards[]array<object>One production battlecard per high-intent query cluster.
battlecards[].queryCluster[]array<string>Representative user queries covered by the row.
battlecards[].competitorPressure[]array<string>Competitor source classes expected on the SERP or answer surface.
battlecards[].competitorArchetypes[]array<object>Sampled competitor benchmark rows with checked dates, recrawl metadata and public evidence URLs.
battlecards[].citationQuestionIds[]array<string>Fixed AI citation benchmark prompt IDs covered by this cluster.
battlecards[].targetPages[]array<string>Visa Atlas pages that should win or support the cluster.
battlecards[].sourceDatasets[]array<string>Datasets the page answer must cite or derive from.
battlecards[].retrievalPlaybookobjectAnswer-capsule, MCP, citation and off-site distribution surfaces for the cluster.
battlecards[].retrievalPlaybook.mcpToolstringBackward-compatible primary read-only MCP tool for the short answer.
battlecards[].retrievalPlaybook.mcpTools[]array<string>Read-only MCP tools to query for the cluster, including list_answer_capsules, list_citation_packs and list_calculator_verdict_contexts where relevant.
battlecards[].retrievalPlaybook.citationSurfaces[]array<string>Human, JSON and MCP surfaces that should carry the citable answer.
battlecards[].retrievalPlaybook.distributionSurfaces[]array<string>Publisher/repository distribution surfaces used to compound authority outside the site.
battlecards[].crawlPathobjectEntry points, target-page count and rendered audit used to prove crawl-ready target coverage.
battlecards[].crawlPath.entryPoints[]array<string>Crawlable pages and JSON feeds that expose or support the battlecard cluster.
battlecards[].crawlPath.indexabilityPolicystringCanonical/noindex rule the rendered audit enforces for target pages.
battlecards[].crawlPath.renderedAuditstringLocal rendered-artifact audit that checks target pages after production build.
battlecards[].technicalActions[]array<string>Implementation requirements for the cluster.
battlecards[].measurement.commands[]array<string>Local commands used to monitor the cluster.

Example response

{
  "version": "2026-07-05",
  "name": "Visa Atlas competitor query battlecards",
  "summary": {
    "count": 13,
    "highPriorityCount": 10,
    "competitorRecrawlSlaDays": 45,
    "overdueCompetitorSampleCount": 0,
    "wedgePillarCount": 4,
    "externalEvidenceUrlCount": 6,
    "publicMarketShareClaimAllowed": false
  },
  "positioning": {
    "strategicWedge": "Competitors are strong at authority, service funnels, single-country depth or broad list coverage; Visa Atlas can win the intersection of freshness, comparability, open data and machine-readable retrieval.",
    "wedgePillars": [{"id":"freshness-delta-control","battlecardIds":["germany-blue-card-salary-recognition","ireland-critical-skills-salary-cost"],"proofGate":"Freshness wins require passing freshness, rendered SEO, citation-share and GSC outcome evidence before any public improvement claim."}],
    "capturePriorities": [{"id":"freshness-first-answer-sprint","runOrder":1,"battlecardIds":["canada-express-entry-freshness","policy-change-freshness-control"]}]
  },
  "battlecards": [
    {
      "id": "germany-blue-card-salary-recognition",
      "title": "Germany EU Blue Card salary and recognition",
      "competitorPressure": ["government-source","law-advisory","broad-aggregator","ai-answer"],
      "competitorArchetypes": [{"sampleId":"fragomen","checkedOn":"2026-07-04","recrawlDueOn":"2026-08-18","recrawlStatus":"fresh"}],
      "targetPages": ["/salary-thresholds/germany","/cost-to-complete/germany-eu-blue-card","/routes/eu-blue-card-vs-chancenkarte-germany"],
      "sourceDatasets": ["/api/public/salary-thresholds","/api/public/cost-to-complete","/api/public/visas"],
      "retrievalPlaybook": {
        "mcpTool": "list_answer_capsules",
        "mcpTools": ["list_answer_capsules","list_citation_packs"],
        "citationSurfaces": ["/answer-capsules","/api/public/answer-capsules","/citation-packs"]
      },
      "crawlPath": {
        "targetPageCount": 8,
        "indexabilityPolicy": "Every battlecard target must render its absolute canonical URL and must not emit noindex before the cluster is treated as index-ready.",
        "renderedAudit": "npm run audit:rendered-seo"
      }
    }
  ]
}
  • This endpoint is production guidance for SEO/GEO clusters, not a ranking guarantee or a current traffic claim.
  • Competitor pressure is archetype-based and grounded in the sampled source-transparency benchmark.
  • Competitor observations past the recrawl SLA should be refreshed before they support wedge, displacement or market-share planning claims.
  • The positioning rollup is an execution thesis; market-share claims still require reviewed outcome evidence.
  • Use the human report for methodology, caveats and the full battlecard table.

Battlecard search experiments

GET /api/public/battlecard-search-experimentsopen live

Returns object · 13 experiment rows

Public experiment contract for turning competitor query battlecards into Search Console-measured title, snippet, answer-capsule and internal-link tests while keeping private GSC exports local.

Fields

FieldTypeDescription
versionstring (ISO date)Experiment dataset version date.
namestringHuman dataset name.
descriptionstringWhat the experiment feed covers.
licensestringAlways "CC BY 4.0".
attributionstringThe credit to use: "Visa Atlas".
sourceDatasets[]array<string>Public datasets used to derive experiment rows.
methodology.privateDataPolicystringHow private GSC exports must be handled.
methodology.caveats[]array<string>Limits on interpreting experiment templates and outcomes.
summaryobjectCounts for experiment rows, high-priority rows and source datasets.
experiments[]array<object>One experiment contract per battlecard query cluster.
experiments[].battlecardIdstringSource competitor query battlecard ID.
experiments[].experimentTypes[]array<string>title-snippet, answer-capsule, internal-linking and/or ai-citation.
experiments[].plannedChangesobjectTitle, answer-capsule, internal-link and structured-data changes to test.
experiments[].gscQueryRulesobjectLocal query matching thresholds for a supplied GSC export.
experiments[].measurement.commands[]array<string>Local commands for GSC mapping, reviewed aggregate outcomes, citation-share and rendered audits.
experiments[].auditTrail[]array<string>Audit notes and private-data handling requirements.

Example response

{
  "version": "2026-07-03",
  "name": "Visa Atlas battlecard search experiments",
  "summary": {
    "count": 13,
    "readyForGscExportCount": 13
  },
  "experiments": [
    {
      "id": "germany-blue-card-salary-recognition-gsc-experiment",
      "battlecardId": "germany-blue-card-salary-recognition",
      "experimentTypes": ["title-snippet","answer-capsule","internal-linking","ai-citation"],
      "targetPages": ["/salary-thresholds/germany","/cost-to-complete/germany-eu-blue-card","/routes/eu-blue-card-vs-chancenkarte-germany"],
      "gscQueryRules": {
        "includeAny": ["eu blue card","blue card germany","anabin","zab"],
        "minImpressions": 100
      }
    }
  ]
}
  • This endpoint publishes experiment templates and matching rules, not private Search Console exports or live performance rows.
  • Use npm run seo:gsc-battlecard-experiments -- gsc-queries.csv --json --period-start=YYYY-MM-DD --period-end=YYYY-MM-DD --property-label=gsc-domain-redacted --search-type=web locally to map scoped private GSC data to the public experiment IDs.
  • Use npm run seo:gsc-experiment-outcomes -- gsc-experiment-outcomes.jsonl --json locally before publishing any experiment win, loss, ship, iterate, revert or monitor claim.
  • Experiment rows are measurement guidance, not ranking, CTR, traffic or AI-citation guarantees.

SERP and AI answer-surface snapshot protocol

GET /api/public/serp-answer-surface-snapshotsopen live

Returns object · 13 protocol rows

Auditable protocol for capturing Google SERP features, competitor source classes and AI answer citations by battlecard query while keeping raw screenshots, transcripts and private reviewer notes local.

Fields

FieldTypeDescription
versionstring (ISO date)Protocol dataset version date.
namestringHuman dataset name.
descriptionstringWhat the snapshot protocol covers.
licensestringAlways "CC BY 4.0".
attributionstringThe credit to use: "Visa Atlas".
sourceDatasets[]array<string>Public datasets used to derive protocol rows.
methodology.privateDataPolicystringHow raw SERP screenshots, transcripts and reviewer notes must be handled.
methodology.caveats[]array<string>Limits on interpreting protocol rows and future snapshot summaries.
summaryobjectCounts for protocol rows, high-priority rows, channels and source datasets.
protocols[]array<object>One capture protocol per battlecard query cluster.
protocols[].battlecardIdstringSource competitor query battlecard ID.
protocols[].channels[]array<string>google-serp and ai-answer capture channels.
protocols[].captureFieldsobjectField list for Google SERP rows and AI answer rows.
protocols[].marketShareSignals[]array<string>Signals reviewers use to classify market-share evidence.
protocols[].redactionRules[]array<string>Rules for keeping raw evidence private or reviewed before publication.
protocols[].commands[]array<string>Local commands for summarising snapshots and linking them to GSC experiments.

Example response

{
  "version": "2026-07-02",
  "name": "Visa Atlas SERP and AI answer-surface snapshot protocol",
  "summary": {
    "count": 13,
    "channelCount": 2
  },
  "protocols": [
    {
      "id": "germany-blue-card-salary-recognition-surface-snapshot",
      "battlecardId": "germany-blue-card-salary-recognition",
      "channels": ["google-serp","ai-answer"],
      "captureFields": {
        "googleSerp": ["capturedAt","locale","device","query"],
        "aiAnswer": ["capturedAt","engine","query","battlecardId"]
      }
    }
  ]
}
  • This endpoint publishes capture protocol and redaction rules, not live SERP rankings or raw AI answer text.
  • Use npm run seo:surface-snapshots -- snapshots.jsonl --json locally to summarise user-supplied snapshot evidence.
  • The local summarizer rejects undated rows, incomplete Google SERP rows and incomplete AI answer rows before they can feed market-share rollups.
  • Protocol rows are measurement guidance, not ranking, traffic, citation or market-share guarantees.

Quarterly market-share evidence summary

GET /api/public/quarterly-market-share-summaryopen live

Returns object · 13 baseline rows

Q3 2026 baseline and local rollup contract for summarising reviewed SERP and AI answer-surface evidence by competitor query battlecard without publishing raw private evidence.

Fields

FieldTypeDescription
versionstring (ISO date)Summary dataset version date.
namestringHuman dataset name.
quarterstringQuarter or baseline period covered by the public rows.
licensestringAlways "CC BY 4.0".
attributionstringThe credit to use: "Visa Atlas".
sourceDatasets[]array<string>Public datasets used to derive the baseline.
methodology.privateDataPolicystringHow raw evidence must be handled before any public rollup.
methodology.rollupInputSchemaobjectRequired local summary and approval fields for future redacted rollups.
methodology.coverageRulesobjectBattlecard coverage rules that separate partial samples from complete quarterly market-share claims.
methodology.caveats[]array<string>Limits on interpreting baseline rows and future share summaries.
summary.currentMarketShareClaimstringExplicit statement that no approved live share is published in the baseline feed.
sourceClassPressureSummary[]array<object>Expected competitor source-class pressure counts by battlecard.
rows[]array<object>One baseline row per competitor query battlecard.
rows[].expectedCompetitorSourceClasses[]array<string>Source classes expected from the public battlecard.
rows[].approvedSnapshotEvidenceobjectApproved public snapshot counts; null/zero in the baseline feed.
rows[].nextEvidenceNeeded[]array<string>Evidence required before making a public market-share claim.
rows[].commands[]array<string>Local commands for snapshot and market-share summary workflows.

Example response

{
  "version": "2026-07-05",
  "name": "Visa Atlas quarterly market-share evidence summary",
  "summary": {
    "battlecardCount": 13,
    "approvedSnapshotCount": 0,
    "currentMarketShareClaim": "No approved live SERP/AI market-share percentage is published in this feed until reviewed redacted snapshots are supplied."
  },
  "rows": [
    {
      "id": "germany-blue-card-salary-recognition-market-share-baseline",
      "battlecardId": "germany-blue-card-salary-recognition",
      "expectedCompetitorSourceClasses": ["government-source","law-advisory","broad-aggregator","ai-answer"],
      "approvedSnapshotEvidence": {
        "approvedSnapshotCount": 0,
        "visaAtlasVisibilityRate": null
      }
    }
  ]
}
  • This endpoint publishes baseline rows and a local rollup contract, not live SERP rankings or private analytics.
  • Use npm run seo:market-share-summary -- surface-summary.json --json locally after reviewing snapshot summaries.
  • Approved public market-share rollups require approvedForPublication=true, reviewedAt, reviewedBy, per-battlecard firstCapturedAt/lastCapturedAt ranges and reconciled serpSnapshots/aiAnswerSnapshots counts; incomplete approval claims fail the local summary command.
  • Partial approved rollups must be labelled partial-battlecard-rollup with missing battlecards disclosed; complete-quarterly-market-share-rollup requires all baseline and high-priority battlecards.
  • Baseline rows are measurement guidance, not ranking, traffic, citation or market-share guarantees.

Publisher and AI-citation kits

GET /api/public/publisher-citation-kitsopen live

Returns object · 7 kits

Reusable citation and outreach kits for publishers, journalists, researchers and AI retrievers, with canonical URLs, source datasets, suggested attribution, proof assets and private evidence-log rules.

Fields

FieldTypeDescription
versionstring (ISO date)Citation-kit dataset version date.
namestringHuman dataset name.
licensestringAlways "CC BY 4.0".
attributionstringThe credit to use: "Visa Atlas".
sourceDatasets[]array<string>Public datasets used to compile the kit rows.
methodology.privateDataPolicystringHow outreach targets, contacts, replies and notes must be handled.
methodology.caveats[]array<string>Limits on interpreting citation kits and outreach evidence.
summary.localWorkflowCommandstringLocal command for summarising approved outreach evidence logs.
kits[]array<object>One reusable citation kit per high-leverage dataset or report.
kits[].audience[]array<string>Intended reuse audiences such as journalists, researchers or AI retrievers.
kits[].canonicalPageUrlstring (URL)Canonical human page to cite.
kits[].datasetUrlstring (URL)Machine-readable JSON endpoint to cite or retrieve.
kits[].reusableSnippets[]array<object>Short attribution-safe text snippets for reuse.
kits[].proofAssets[]array<object>Human pages, JSON endpoints, methodology pages or citation packs backing the kit.
kits[].outreachEvidenceLogFields[]array<string>Allowed local evidence-log fields for measuring outreach without exposing private contact data.
kits[].measurement.commands[]array<string>Local commands for citation-share, referrals, audits and evidence-log rollups.

Example response

{
  "version": "2026-07-03",
  "name": "Visa Atlas publisher and AI-citation kits",
  "summary": {
    "count": 7,
    "localWorkflowCommand": "npm run seo:publisher-citation-kits -- outreach-log.jsonl --json"
  },
  "kits": [
    {
      "id": "citation-packs-reuse-kit",
      "title": "Immigration citation packs reuse kit",
      "canonicalPageUrl": "https://visaatlas.org/citation-packs",
      "datasetUrl": "https://visaatlas.org/api/public/citation-packs",
      "reusableSnippets": [{"label":"AI retriever snippet","text":"Visa Atlas publishes 162 compact immigration citation packets with canonical URLs, source URLs, review dates and CC BY 4.0 attribution."}]
    }
  ]
}
  • This endpoint publishes reusable citation kits and evidence-log fields, not private publisher contacts or outreach notes.
  • Use npm run seo:publisher-citation-kits -- outreach-log.jsonl --json locally to summarise approved published citation evidence.
  • Approved public citation evidence requires status published plus publishedUrl, reviewedAt and reviewedBy.
  • Citation kits make reuse easier; they do not guarantee backlinks, rankings, traffic, citations or market share.

Authority distribution plan

GET /api/public/authority-distribution-planopen live

Returns object · 11 distribution channels

Auditable launch and distribution control plane for turning Visa Atlas open data, MCP tools, widgets and original research into off-site citations, links, dataset entities and AI retriever entry points.

Fields

FieldTypeDescription
versionstring (ISO date)Authority distribution plan version date.
namestringHuman dataset name.
licensestringAlways "CC BY 4.0".
attributionstringThe credit to use: "Visa Atlas".
datasetUrlstring (URL)Canonical machine-readable JSON endpoint.
humanUrlstring (URL)Canonical human methodology and launch-readiness report.
sourceDatasets[]array<string>Public datasets used to compile the channel rows.
methodology.localEvidenceCommandstringLocal command for summarising approved authority-distribution evidence logs.
methodology.privateDataPolicystringHow credentials, unpublished URLs, contacts and unreviewed launch outcomes stay local.
methodology.commands[]array<string>Local commands used to verify data, launch kits, repository mirrors, knowledge graph controls and crawler access.
summary.channelCountnumberCount of distribution channels in the plan.
summary.manualPublicationReadyCountnumberChannels ready for manual submission once account-side evidence is collected.
summary.localWorkflowCountnumberChannels that rely on local measurement, exports or private evidence review.
channels[]array<object>One distribution lane per platform family, launch surface or discovery workflow.
channels[].statusstringmanual-publication-ready, template-ready, local-workflow or evidence-required.
channels[].publicEntryPoints[]array<string>Canonical Visa Atlas pages or endpoints to use in the channel.
channels[].sourceDatasets[]array<string>Source datasets backing the launch channel.
channels[].actionChecklist[]array<string>Human review steps before publication or measurement.
channels[].launchCopyAssets[]array<string>Reusable launch copy elements that preserve attribution and source links.
channels[].evidenceToCollect[]array<string>Allowed local evidence fields for submission, publication, backlink, license and moderation proof.
channels[].successSignals[]array<string>Directional signals to measure after approved publication or workflow completion.

Example response

{
  "version": "2026-07-03",
  "name": "Visa Atlas authority distribution plan",
  "summary": {
    "channelCount": 11,
    "manualPublicationReadyCount": 2,
    "localWorkflowCount": 2
  },
  "channels": [
    {
      "id": "official-mcp-registry",
      "title": "Official MCP registry listing",
      "status": "manual-publication-ready",
      "publicEntryPoints": ["/mcp","/ai-agents","/api/openapi.json","/api/public/route-finder"],
      "sourceDatasets": ["/api/public/visibility-metrics","/api/public/crawler-access"]
    }
  ]
}
  • This endpoint publishes launch readiness, copy assets and evidence fields, not proof that a third-party platform has accepted or cited Visa Atlas.
  • Use npm run seo:authority-distribution -- authority-distribution-log.jsonl --json locally to summarise approved public distribution evidence.
  • Manual distribution must preserve canonical Visa Atlas URLs, CC BY 4.0 attribution and linked government source URLs.
  • Distribution planning does not guarantee backlinks, rankings, traffic, citations, market share or the 500k/month planning target.

Embeddable widget catalog

GET /api/public/widgetsopen live

Returns object · 32 widgets

Machine-readable catalog of approved Visa Atlas embed scripts for sourced immigration figures and calculators, with source trails, attribution rules and legal-scope guardrails for publishers and AI retrievers.

Fields

FieldTypeDescription
versionstring (ISO date)Widget catalog version date.
namestringHuman dataset name.
datasetUrlstring (URL)Canonical machine-readable JSON endpoint.
humanUrlstring (URL)Canonical human widget directory.
licensestringAlways "CC BY 4.0".
attributionstringThe credit to use: "Visa Atlas".
summary.countnumberApproved embed inventory count.
summary.badgeCountnumberLatest-figure and cost badge count.
summary.calculatorCountnumberInteractive calculator widget count.
embedRules[]array<string>Attribution, source-preservation and no-outcome-promise rules.
evidenceBoundary[]array<string>What this catalog proves and which publication/backlink evidence must stay local.
items[]array<object>One approved embed script per widget.
items[].kindstringlatest-figure-badge, cost-badge or calculator.
items[].scriptUrlstring (URL)Absolute embeddable script URL.
items[].embedCodestringCopy-ready script tag for publishers.
items[].humanUrlstring (URL)Canonical page linked by the rendered widget.
items[].sourceDatasets[]array<string>Public datasets supporting the widget.
items[].sourceUrls[]array<object>Official or source URLs used by the widget facts.
items[].lastReviewedstring (ISO date)Freshness date for the widget facts or model.
items[].targetAudience[]array<string>Publisher or retriever audiences the widget is designed for.
items[].allowedUse[]array<string>Permitted reuse patterns.
items[].prohibitedUse[]array<string>Attribution-removal, legal-advice and outcome-promise restrictions.
items[].requiredAttributionstringVisible attribution text that must stay with the widget.
items[].legalScopestringPlain-language legal-scope caveat.

Example response

{
  "version": "2026-07-04",
  "name": "Visa Atlas embeddable widget catalog",
  "summary": {
    "count": 32,
    "badgeCount": 31,
    "calculatorCount": 1
  },
  "items": [
    {
      "id": "express-entry-latest-draw-badge",
      "kind": "latest-figure-badge",
      "scriptUrl": "https://visaatlas.org/widgets/express-entry-latest.js",
      "humanUrl": "https://visaatlas.org/research/canada-express-entry-draw-tracker",
      "requiredAttribution": "Powered by Visa Atlas",
      "sourceDatasets": ["/api/public/express-entry-draws","/api/public/citation-packs"]
    }
  ]
}
  • This endpoint proves the approved public embed inventory, source trails and attribution rules.
  • It does not prove third-party publication, backlinks, rankings, AI citations, referral sessions or market share.
  • Publisher outreach logs and approved live-embed evidence stay local until reviewed for public reporting.
  • Run npm run audit:widgets and npm run audit:seo-geo before treating widget discovery as release-ready.

External repository mirror manifest

GET /api/public/external-repository-mirrorsopen live

Returns object · 6 mirror manifests

Repository-ready export manifests, metadata templates, DOI/accession checklists, canonical backlink requirements and local publication-evidence fields for mirroring original Visa Atlas datasets into external data repositories.

Fields

FieldTypeDescription
versionstring (ISO date)Mirror-manifest dataset version date.
namestringHuman dataset name.
licensestringAlways "CC BY 4.0".
attributionstringThe credit to use: "Visa Atlas".
sourceDatasets[]array<string>Public datasets used by the repository mirror plan.
methodology.localExportCommandstringOffline command that writes repository metadata templates under exports/.
methodology.localEvidenceCommandstringLocal command for summarising approved external repository evidence.
methodology.privateDataPolicystringHow account-side repository evidence and private reviewer notes must be handled.
summary.publicEndpointCountnumberCount of public API endpoints included in mirror readiness checks.
mirrors[]array<object>One external repository mirror lane per target platform.
mirrors[].repositoryMetadataobjectRepository title, description, license, keywords, canonical URL and citation metadata.
mirrors[].exportManifestobjectLocal package path, command and files needed for repository publication.
mirrors[].depositionChecklist[]array<string>Human review steps before account-side publication, DOI minting or accession claims.
mirrors[].canonicalBacklinkRequirements[]array<string>Required canonical Visa Atlas links and source-preservation rules for each mirror.
mirrors[].publicationEvidenceLogFields[]array<string>Allowed local evidence-log fields for approved external repository publication evidence.
mirrors[].validation.localCommands[]array<string>Local commands that verify package readiness before release.

Example response

{
  "version": "2026-07-03",
  "name": "Visa Atlas external data repository mirror manifest",
  "summary": {
    "count": 6,
    "publicEndpointCount": 39,
    "localExportCommand": "npm run export:repository-mirrors"
  },
  "mirrors": [
    {
      "id": "hugging-face-skilled-migration-data",
      "platform": "Hugging Face",
      "status": "export-ready",
      "canonicalPageUrl": "https://visaatlas.org/data",
      "repositoryMetadata": {
        "license": "CC BY 4.0",
        "canonicalUrl": "https://visaatlas.org/data"
      }
    }
  ]
}
  • This endpoint publishes mirror readiness and evidence-log fields, not account credentials, private reviewer notes or unapproved repository URLs.
  • Approved public repository evidence requires status published or refreshed plus repositoryUrl, reviewedAt, reviewedBy, canonicalBacklinkPresent, licensePresent and sourceUrlsPreserved.
  • Use npm run export:repository-mirrors locally to generate repository metadata templates under exports/repository-mirrors.
  • External mirrors can improve citation reach and AI retriever recall; they do not guarantee backlinks, rankings, traffic, citations or market share.

Knowledge-graph entity seeding manifest

GET /api/public/knowledge-graph-entitiesopen live

Returns object · 9 entity candidates

Auditable entity-seeding controls for source-backed Visa Atlas datasets, reports and identity nodes, with sameAs governance, approved external accession ingestion, JSON-LD export controls and local evidence-log rules.

Fields

FieldTypeDescription
versionstring (ISO date)Entity manifest version date.
namestringHuman dataset name.
licensestringAlways "CC BY 4.0".
attributionstringThe credit to use: "Visa Atlas".
sourceDatasets[]array<string>Public datasets used by the entity-seeding manifest.
methodology.localEvidenceCommandstringLocal command for summarising approved knowledge-graph evidence logs.
methodology.localExportCommandstringOffline command that writes reviewed JSON-LD fragments under exports/knowledge-graph.
methodology.privateDataPolicystringHow draft identifiers, reviewer notes and unapproved mappings stay local.
summary.existingPublicSameAsCountnumberCount of public sameAs URLs already present in the site identity model.
entities[]array<object>One candidate entity per organization, person, dataset or report node.
entities[].canonicalUrlstring (URL)Canonical Visa Atlas URL for the entity.
entities[].schemaNodeIdstring (URL or fragment)Stable JSON-LD node ID to use when exporting approved identifiers.
entities[].externalIdentifierTargets[]array<object>Allowed sameAs, DOI, accession or Wikidata identifier targets and evidence requirements.
entities[].schemaOutputs.allowedProperties[]array<string>Schema properties that may be emitted after review.
entities[].schemaOutputs.blockedProperties[]array<string>Schema properties or behaviours blocked until evidence is approved.
entities[].evidenceLogFields[]array<string>Allowed local evidence-log fields for identifier approval review.

Example response

{
  "version": "2026-07-02",
  "name": "Visa Atlas knowledge-graph entity seeding manifest",
  "summary": {
    "count": 9,
    "localEvidenceCommand": "npm run seo:knowledge-graph -- kg-entity-log.jsonl --json"
  },
  "entities": [
    {
      "id": "visaatlas-organization",
      "entityType": "Organization",
      "status": "manual-review",
      "canonicalUrl": "https://visaatlas.org/about",
      "externalIdentifierTargets": [{"kind":"sameAs","platform":"GitHub","relation":"sameAs","evidenceRequired":["Public organization or repository page","Canonical backlink to /data","License and publisher identity visible"],"publicWhenApproved":true,"caveat":"A GitHub mirror can identify the data publisher, but it must not be treated as the issuing authority for immigration facts."}]
    }
  ]
}
  • This endpoint publishes candidate entities and governance controls, not unreviewed Wikidata QIDs, DOI/accession values or sameAs URLs.
  • Use npm run seo:knowledge-graph -- kg-entity-log.jsonl --json locally to summarise approved identifier evidence.
  • Use npm run export:knowledge-graph -- kg-entity-log.jsonl locally to generate reviewed JSON-LD fragments under exports/knowledge-graph.
  • Approved JSON-LD identifier rows require status approved-for-jsonld plus externalUrl, identifierKind, identifierValue, relation, canonicalBacklinkPresent, sourceUrlPreserved, reviewedAt and reviewedBy.
  • Knowledge-graph seeding improves disambiguation controls; it does not guarantee backlinks, rankings, traffic, citations or market share.

Expert reviewer entity program

GET /api/public/expert-reviewer-entitiesopen live

Returns object · 7 reviewer entities and 6 review queue rows

Auditable reviewer disclosure model for YMYL immigration pages, including source-editor limits, regulated reviewer slots, reviewedBy schema governance, core-country review queues and local credential evidence logging.

Fields

FieldTypeDescription
versionstring (ISO date)Reviewer program version date.
namestringHuman dataset name.
licensestringAlways "CC BY 4.0".
attributionstringThe credit to use: "Visa Atlas".
sourceDatasets[]array<string>Public datasets and trust surfaces used by the reviewer program.
methodology.localEvidenceCommandstringLocal command for summarising credential and page-review evidence logs.
methodology.privateDataPolicystringHow private reviewer names, contact details and unapproved evidence stay local.
methodology.reviewedBySchemaGovernancestringRule for author/editor schema versus reviewedBy schema.
summary.reviewerRequiredCountnumberNumber of regulated reviewer slots still requiring evidence.
summary.p0QueueCountnumberHighest-priority review queue rows.
reviewerEntities[]array<object>Source editor and regulated reviewer slots.
reviewerEntities[].regulators[]array<object>Regulator or bar register rows from the destination registry.
reviewerEntities[].allowedSchemaProperties[]array<string>Schema properties that may be emitted for this identity class.
reviewerEntities[].blockedSchemaProperties[]array<string>Schema properties blocked until credential evidence is approved.
reviewerEntities[].evidenceLogFields[]array<string>Allowed local evidence-log fields for credential review.
reviewQueues[]array<object>High-risk YMYL page groups awaiting reviewer evidence.
reviewQueues[].pageTargets[]array<string>Human pages covered by the review queue row.
reviewQueues[].schemaGovernance.reviewedBySchemaAllowedbooleanWhether reviewedBy schema is currently allowed for the public queue row.
reviewQueues[].schemaGovernance.blockedUntilstringEvidence threshold before reviewedBy schema can be considered.

Example response

{
  "version": "2026-07-02",
  "name": "Visa Atlas expert reviewer entity program",
  "summary": {
    "reviewerEntityCount": 7,
    "queueCount": 6,
    "localEvidenceCommand": "npm run seo:expert-reviewers -- reviewer-evidence-log.jsonl --json"
  },
  "reviewerEntities": [
    {
      "id": "sam-parks-source-editor",
      "role": "source-editor",
      "status": "active-editor",
      "blockedSchemaProperties": ["Do not emit reviewedBy for legal or regulated review from the source-editor identity alone."]
    }
  ],
  "reviewQueues": [
    {
      "id": "uk-skilled-worker-yml-review",
      "priority": "p0",
      "schemaGovernance": {
        "reviewedBySchemaAllowed": false
      }
    }
  ]
}
  • This endpoint publishes reviewer governance and queue rows, not private reviewer contacts or unapproved credentials.
  • Use npm run seo:expert-reviewers -- reviewer-evidence-log.jsonl --json locally to summarise credential and page-review evidence.
  • Source-editor identity can support author/editor schema; reviewedBy schema for legal or regulated review stays blocked until approved evidence exists.

reviewedBy schema rollout controls

GET /api/public/reviewedby-schema-rolloutopen live

Returns object · 6 schema control rows

Auditable rollout controls for page-level reviewedBy JSON-LD fragments. This endpoint documents which high-risk page groups remain blocked and which local evidence fields are required before offline fragment export.

Fields

FieldTypeDescription
versionstring (ISO date)Rollout control version date.
namestringHuman dataset name.
licensestringAlways "CC BY 4.0".
attributionstringThe credit to use: "Visa Atlas".
sourceDatasets[]array<string>Public reviewer, visibility and source datasets used by the controls.
methodology.localEvidenceCommandstringLocal command for summarising credential and page-review evidence logs.
methodology.localExportCommandstringOffline command that writes reviewedBy JSON-LD fragments under exports/reviewedby-schema.
methodology.schemaFragmentPolicystringPolicy for WebPage reviewedBy JSON-LD fragment generation.
summary.blockedCountnumberNumber of controls blocked pending approved evidence.
summary.approvedByDefaultCountnumberAlways 0; public controls do not approve reviewedBy schema by default.
controls[]array<object>One schema control per high-risk reviewer queue row.
controls[].statusstringCurrent public status; expected value is "blocked-pending-evidence".
controls[].pageTargets[]array<string>Pages covered by the control row.
controls[].schemaGovernance.reviewedBySchemaAllowedbooleanWhether reviewedBy schema is currently allowed for the public control row.
controls[].requiredEvidenceFields[]array<string>Evidence fields required before export can emit a fragment.
controls[].localCommands[]array<string>Local commands for evidence summary and offline fragment export.

Example response

{
  "version": "2026-07-02",
  "name": "Visa Atlas reviewedBy schema rollout controls",
  "summary": {
    "controlCount": 6,
    "blockedCount": 6,
    "approvedByDefaultCount": 0,
    "localExportCommand": "npm run export:reviewedby-schema -- reviewer-evidence-log.jsonl"
  },
  "controls": [
    {
      "id": "uk-skilled-worker-yml-review-schema-control",
      "status": "blocked-pending-evidence",
      "schemaGovernance": {
        "reviewedBySchemaAllowed": false
      },
      "requiredEvidenceFields": ["evidenceRowId","reviewerEntityId","queueId","status"]
    }
  ]
}
  • This endpoint is a control surface, not a claim that reviewedBy schema is live on any page.
  • Use npm run seo:expert-reviewers -- reviewer-evidence-log.jsonl --json locally to summarise credential and page-review evidence.
  • Use npm run export:reviewedby-schema -- reviewer-evidence-log.jsonl locally to generate reviewedBy fragments under exports/reviewedby-schema for final page-level schema review.
  • The offline exporter ignores draft rows and exits non-zero when a row claims reviewedBy approval without every required public evidence field.
  • Schema controls reduce overclaiming risk; they do not guarantee rankings, traffic, citations or market share.

High-risk page review acquisition controls

GET /api/public/high-risk-page-review-acquisitionopen live

Returns object · 6 acquisition targets

Auditable acquisition controls for sourcing credentialed reviewers for high-risk YMYL immigration page queues. This endpoint documents target page groups, regulator targets, sourcing channels, vetting stages, disqualification rules and local-only evidence fields.

Fields

FieldTypeDescription
versionstring (ISO date)Acquisition control version date.
namestringHuman dataset name.
licensestringAlways "CC BY 4.0".
attributionstringThe credit to use: "Visa Atlas".
sourceDatasets[]array<string>Public reviewer, schema-rollout and visibility datasets used by the controls.
methodology.localEvidenceCommandstringLocal command for summarising reviewer acquisition evidence logs.
methodology.privateDataPolicystringHow candidate names, contacts, terms and screening notes stay local.
methodology.reviewerIndependencePolicystringIndependence, referral and advisor-language controls for reviewer sourcing.
summary.p0TargetCountnumberHighest-priority acquisition target count.
summary.acquiredReviewerCountnumberAlways 0 in the public control feed until approved handoff evidence is separately published.
summary.schemaHandoffReadyCountnumberAlways 0 in the public control feed; handoffs stay local until reviewed.
summary.privateLeadCountPublishednumberAlways 0; private candidate leads are not published.
targets[]array<object>One acquisition target per awaiting credentialed-review queue row.
targets[].regulatorTargets[]array<object>Public regulator/register targets for credential screening.
targets[].sourcingChannels[]array<string>Allowed sourcing channels.
targets[].vettingStages[]array<string>Required screening stages before handoff.
targets[].disqualificationRules[]array<string>Conditions that block reviewer use.
targets[].requiredLocalEvidenceFields[]array<string>Local evidence fields required before handoff.
targets[].schemaHandoff.reviewedBySchemaAllowedbooleanWhether the acquisition target can hand off to reviewedBy schema by default.

Example response

{
  "version": "2026-07-02",
  "name": "Visa Atlas high-risk page review acquisition controls",
  "summary": {
    "targetCount": 6,
    "p0TargetCount": 3,
    "acquiredReviewerCount": 0,
    "schemaHandoffReadyCount": 0,
    "privateLeadCountPublished": 0
  },
  "targets": [
    {
      "id": "uk-skilled-worker-yml-review-review-acquisition",
      "status": "sourcing-required",
      "schemaHandoff": {
        "reviewedBySchemaAllowed": false
      },
      "requiredLocalEvidenceFields": ["evidenceRowId","queueId","reviewerEntityId","status"]
    }
  ]
}
  • This endpoint is a sourcing and vetting control surface, not a claim that reviewers have already completed page reviews.
  • Use npm run seo:review-acquisition -- reviewer-acquisition-log.jsonl --json locally to summarise candidate sourcing and handoff readiness.
  • Candidate leads, contact details, screening notes, conflicts and engagement terms stay local.
  • Reviewer acquisition controls do not guarantee rankings, traffic, citations or market share.

P0 reviewed page refresh controls

GET /api/public/p0-reviewed-page-refreshopen live

Returns object · 3 P0 refresh targets

Auditable publication gates for refreshing P0 YMYL pages after reviewer handoff evidence. This endpoint documents page targets, prerequisite controls, local-only evidence fields, content-diff requirements, source-freshness rechecks and reviewedBy schema publication gates.

Fields

FieldTypeDescription
versionstring (ISO date)Page refresh control version date.
namestringHuman dataset name.
licensestringAlways "CC BY 4.0".
attributionstringThe credit to use: "Visa Atlas".
sourceDatasets[]array<string>Public reviewer, acquisition, schema-rollout and visibility datasets used by the controls.
methodology.localEvidenceCommandstringLocal command for summarising reviewed page refresh evidence logs.
methodology.privateDataPolicystringHow reviewer notes, draft diffs, contacts and rejected evidence stay local.
methodology.publicationPolicystringPublication criteria before a P0 page refresh can move from local evidence to public templates.
summary.blockedCountnumberNumber of targets blocked pending reviewer handoff.
summary.readyForPublicationCountnumberAlways 0 in the public control feed until approved local evidence is separately published.
summary.reviewedBySchemaAllowedCountnumberAlways 0; reviewedBy schema stays blocked by default.
targets[]array<object>One page refresh control per P0 reviewer queue row.
targets[].prerequisiteControls[]array<object>Public acquisition, reviewedBy schema and reviewer-entity controls that must pass first.
targets[].requiredLocalEvidenceFields[]array<string>Local evidence fields required before a page refresh can be publication-ready.
targets[].publicationGate.pageRefreshAllowedbooleanWhether a public page refresh is currently allowed by default.
targets[].publicationGate.reviewedBySchemaAllowedbooleanWhether reviewedBy schema publication is currently allowed by default.
targets[].pageUpdatePolicy[]array<string>Rules for content diffs, source freshness, disclosure blocks and schema fragment review.

Example response

{
  "version": "2026-07-02",
  "name": "Visa Atlas P0 reviewed page refresh controls",
  "summary": {
    "targetCount": 3,
    "blockedCount": 3,
    "readyForPublicationCount": 0,
    "reviewedBySchemaAllowedCount": 0
  },
  "targets": [
    {
      "id": "uk-skilled-worker-yml-review-page-refresh-control",
      "status": "blocked-pending-handoff",
      "publicationGate": {
        "pageRefreshAllowed": false,
        "reviewedBySchemaAllowed": false
      },
      "requiredLocalEvidenceFields": ["evidenceRowId","queueId","reviewerEntityId","reviewerName"]
    }
  ]
}
  • This endpoint is a publication-gate control surface, not a claim that P0 page reviews or refreshes are complete.
  • Use npm run seo:p0-page-refresh -- p0-reviewed-page-refresh-log.jsonl --json locally to summarise handoff, content-diff, source-freshness and schema-fragment readiness.
  • Reviewer notes, private comments, draft diffs, contacts, engagement terms and rejected evidence stay local.
  • Page refresh controls do not guarantee rankings, traffic, citations or market share.

Calculator verdict contexts

GET /api/public/calculator-verdict-contextsopen live

Returns object · 10 calculator contexts

Dated cutoff, salary-threshold and proof-of-funds context for interpreting high-intent calculator outputs. This feed binds calculator verdict copy to source-backed figures rather than leaving users with a bare score.

Fields

FieldTypeDescription
versionstring (ISO date)Dataset version date, derived from the freshest underlying source.
namestringHuman dataset name.
descriptionstringWhat the calculator verdict context feed covers.
licensestringAlways "CC BY 4.0".
attributionstringThe credit to use: "Visa Atlas".
countnumberNumber of calculator contexts.
sourceDatasets[]array<string>Public datasets used by the context rows.
methodology.purposestringWhy the context layer exists.
methodology.caveats[]array<string>Limits on interpreting scores and pass/fail results.
contexts[]array<object>One calculator context per high-intent calculator.
contexts[].idstringStable calculator context ID.
contexts[].calculatorPathstringHuman calculator page that renders the same context.
contexts[].lastVerifiedstring (ISO date)Freshest verification date among the underlying sources.
contexts[].summarystringCurrent cutoff, salary-threshold or proof-of-funds summary.
contexts[].verdictUsestringHow to use the context with a calculator result.
contexts[].signals[]array<object>Dated facts such as latest CRS draw, salary floor or blocked-account amount.
contexts[].signals[].valuestringDisplay value for the signal.
contexts[].signals[].sourceUrlstring?Primary source URL for the signal where available.
contexts[].sources[]array<object>Underlying source list with labels, URLs, authorities and verification dates.
contexts[].caveats[]array<string>Calculator-specific caveats and limits.

Example response

{
  "version": "2026-07-15",
  "name": "Visa Atlas calculator verdict contexts",
  "count": 10,
  "contexts": [
    {
      "id": "canada-crs",
      "calculatorPath": "/calculators/canada-crs",
      "lastVerified": "2026-07-15",
      "signals": [
        {
          "label": "Latest tracked draw",
          "value": "Round 426: CRS 392",
          "sourceUrl": "https://www.canada.ca/en/immigration-refugees-citizenship/services/immigrate-canada/express-entry/submit-profile/rounds-invitations.html"
        }
      ]
    }
  ]
}
  • Use this feed when presenting calculator results outside the site, so a score or pass/fail result carries the current cutoff or threshold context.
  • The endpoint does not replace government decision makers and does not predict future invitations or case outcomes.

Route finder

GET /api/public/route-finderopen live

Returns object · 3 example matches; POST responses return up to 12 ranked routes

Agent-facing deterministic route matching over indexable Visa Atlas routes. POST a profile and receive ranked candidate routes with reasons, canonical pages, official source URLs, review dates and legal-scope caveats.

Fields

FieldTypeDescription
versionstring (ISO date)Route-finder contract version.
methodstringPOST for profile matching; GET returns this contract and an example response.
legalNotestringExplicit informational-only and not-legal-advice caveat.
methodology[]array<string>Deterministic scoring limits and provenance rules.
sourceDatasets[]array<string>Public datasets backing route facts and source trails.
input.professionSlugstring?Optional profession taxonomy slug such as software-engineer or nurse.
input.nationalityIsostring?Optional nationality ISO code used for bilateral or nationality-gated route checks.
input.targetDestinations[]array<object>?Normalized public indexable destination filters.
input.sponsorshipAvailableyes | no | unsure?Whether the user has employer or sponsor backing.
input.needsSettlementboolean?Whether permanent residence or settlement matters.
input.hasHigherEducationboolean?Whether the user has higher-education evidence.
input.hasLanguageB2boolean?Whether the user has B2-level language evidence.
input.capitalBandstring?Coarse capital band for investor and entrepreneur scoring.
input.ageBandstring?Broad age band used for youth-mobility and points-route scoring.
input.salaryBandstring?Broad salary band used only as a planning signal.
input.dependantsnumber?Number of dependants, clamped by the request schema to 0-10.
input.routeIntentstring?Primary intent such as work, study, remote-work or invest.
warnings[]array<string>Unknown profession, nationality or destination inputs that were ignored.
results[]array<object>Ranked route candidates.
results[].scorenumberDeterministic score for ordering; not an official eligibility score.
results[].reasons[]array<string>Human-readable score reasons.
results[].canonicalUrlstringCanonical Visa Atlas route page.
results[].routeobjectDestination, route slug, name, category, sponsorship, settlement, summary and last-reviewed date.
results[].sources[]array<object>Official route sources with labels, URLs, authorities and verification dates.
results[].sourceUrls[]array<string>Deduplicated official source URLs.

Example response

POST https://visaatlas.org/api/public/route-finder
{
  "professionSlug": "software-engineer",
  "nationalityIso": "in",
  "targetDestinations": [
    "uk",
    "germany",
    "canada"
  ],
  "sponsorshipAvailable": "yes",
  "needsSettlement": true,
  "hasHigherEducation": true,
  "hasLanguageB2": true,
  "ageBand": "30-44",
  "salaryBand": "60k-90k",
  "dependants": 1,
  "routeIntent": "work",
  "limit": 3
}

{
  "version": "2026-07-03",
  "name": "Visa Atlas route finder",
  "legalNote": "Informational route matching only, not legal advice or an eligibility decision. Confirm the returned route against the linked government source and, where needed, a qualified immigration adviser.",
  "returned": 3,
  "results": [
    {
      "rank": 1,
      "score": 88,
      "canonicalUrl": "https://visaatlas.org/visas/germany/eu-blue-card",
      "route": {
        "destinationName": "Federal Republic of Germany",
        "visaName": "EU Blue Card (Germany)",
        "lastReviewed": "2026-07-08"
      },
      "sourceUrls": ["https://www.make-it-in-germany.com/en/visa-residence/types/eu-blue-card","https://www.auswaertiges-amt.de/en/visa-service/buergerservice/faq/02a-what-is-the-blue-card/606754"]
    }
  ]
}
  • This is an API/tool contract, not a static downloadable dataset, so it is documented here and on /ai-agents rather than listed as a Dataset in /api/public.
  • Scores are ordering hints from deterministic site data and do not replace route eligibility rules or government decisions.
  • GET /api/public/route-finder returns the contract and example; POST returns a profile-specific response.

SEO/GEO visibility metrics

GET /api/public/visibility-metricsopen live

Returns object · 9 metrics across 5 cohorts

Public measurement contract separating Google organic growth, AI citation share, crawler access, source freshness, open-data discoverability, index quality, rendered SEO gates and competitor-wedge proof. It defines evidence surfaces and commands without exposing private analytics.

Fields

FieldTypeDescription
versionstring (ISO date)Contract version date.
namestringHuman contract name.
descriptionstringWhat the measurement contract covers.
licensestringAlways "CC BY 4.0".
attributionstringThe credit to use: "Visa Atlas".
trafficModelobjectPlanning target and range; not a current traffic claim.
countnumberNumber of KPI definitions.
cohortCountnumberNumber of page cohorts tracked.
metrics[]array<object>One visibility metric per row.
metrics[].idstringStable metric ID.
metrics[].labelstringHuman metric label.
metrics[].categorystringseo, geo, trust or technical.
metrics[].statusstringinstrumented, partially-instrumented or roadmap.
metrics[].targetstringMeasurement target or control objective.
metrics[].whyItMattersstringReason this KPI matters for SEO/GEO dominance.
metrics[].evidenceSurfaces[]array<string>Public pages/endpoints supporting the KPI.
metrics[].commands[]array<string>Local commands that produce or audit the metric where available.
metrics[].cadencestringRecommended measurement cadence.
metrics[].caveats[]array<string>Limits and interpretation notes.
cohorts[]array<object>Page cohorts used for reporting and audit grouping.
cohorts[].representativePaths[]array<string>Representative paths for the cohort.
cohorts[].primaryKpis[]array<string>Metric IDs most relevant to the cohort.

Example response

{
  "version": "2026-07-03",
  "name": "Visa Atlas SEO/GEO visibility measurement contract",
  "trafficModel": {
    "planningTargetMonthlyVisits": 500000,
    "planningWindow": "24 months",
    "note": "This is a planning model, not a current traffic claim."
  },
  "count": 9,
  "cohortCount": 5,
  "metrics": [
    {
      "id": "ai-citation-share",
      "category": "geo",
      "status": "instrumented",
      "target": "At least 40% of fixed benchmark answers cite visaatlas.org.",
      "evidenceSurfaces": ["/citation-benchmark", "/api/public/citation-benchmark"],
      "commands": ["npm run kpi:citation-share"]
    }
  ]
}
  • The traffic model is a planning target, not a statement of current sessions or pageviews.
  • Private analytics remain private; this endpoint publishes the methodology and public evidence surfaces.

SEO/GEO traffic forecast

GET /api/public/traffic-forecastopen live

Returns object · 5 forecast cohorts

Falsifiable cohort-level planning model for the Visa Atlas 500k/month SEO/GEO target, tying each traffic range to assumptions, evidence surfaces, measurement commands, dependencies and kill gates.

Fields

FieldTypeDescription
versionstring (ISO date)Forecast model version date.
namestringHuman forecast name.
descriptionstringWhat the forecast model covers.
licensestringAlways "CC BY 4.0".
attributionstringThe credit to use: "Visa Atlas".
sourceDatasets[]array<string>Public datasets used to ground the cohort assumptions.
methodology.planningTargetMonthlyVisitsnumberThe 500k/month planning target; not current traffic.
methodology.planningWindowstringPlanning horizon inherited from the visibility model.
methodology.overlapPolicystringHow cohort ranges are interpreted without double-counting authority lift.
methodology.currentTrafficClaimstringExplicit statement that this forecast publishes no current traffic, ranking, CTR, citation or market-share claim.
methodology.privateEvidencePolicystringHow private sessions, Search Console rows, referrers and experiment outcomes are kept local unless reviewed and aggregated.
methodology.caveats[]array<string>Limits on interpreting the forecast and triggers for rebasing it.
summary.lowMonthlyVisitsnumberLow end of the portfolio planning range.
summary.highMonthlyVisitsnumberHigh end of the portfolio planning range.
summary.planningTargetMonthlyVisitsnumberTarget monthly visits used by the model.
summary.targetWithinRangebooleanWhether the target sits inside the modeled low/high range.
cohorts[]array<object>Forecast rows by traffic cohort.
cohorts[].targetMonthlyVisitsobjectLow/high monthly visit planning range for the cohort.
cohorts[].assumptions[]array<string>Assumptions that must remain true for the cohort range to hold.
cohorts[].evidenceSurfaces[]array<string>Public pages and endpoints that ground or audit the cohort.
cohorts[].measurementCommands[]array<string>Local commands used to measure, audit or rebase the cohort.
cohorts[].dependencies[]array<string>Operational dependencies that constrain expansion.
cohorts[].falsificationGates[]array<string>Kill gates that force rebasing or pausing work.

Example response

{
  "version": "2026-07-03",
  "name": "Visa Atlas SEO/GEO traffic forecast model",
  "sourceDatasets": ["/api/public/visibility-metrics","/api/public/content-opportunities","/api/public/competitor-query-battlecards"],
  "methodology": {
    "planningTargetMonthlyVisits": 500000,
    "planningWindow": "24 months",
    "currentTrafficClaim": "No current traffic, ranking, CTR, AI-citation or market-share claim is published by this forecast."
  },
  "summary": {
    "lowMonthlyVisits": 390000,
    "highMonthlyVisits": 600000,
    "planningTargetMonthlyVisits": 500000,
    "targetWithinRange": true
  },
  "cohorts": [
    {
      "id": "calculators-tools",
      "targetMonthlyVisits": {"low":90000,"high":140000},
      "assumptions": ["High-intent calculator pages retain click demand because users need personal inputs, dated thresholds and route-specific caveats.","Each flagship calculator keeps visible source provenance, deterministic logic and no approval prediction."],
      "measurementCommands": ["npm run audit:calculator-provenance","npm run audit:calculator-verdict-contexts"],
      "falsificationGates": ["If flagship calculator/tool pages stay below 0.5% CTR at stable rank after the first reviewed GSC experiment window, rebase the cohort target."]
    }
  ]
}
  • This endpoint is a planning model, not proof of current traffic, rankings, CTR, AI citations or market share.
  • Rebase the ranges from reviewed GSC cohorts, AI-citation share, bot-log and authority-distribution evidence rather than from unreviewed anecdotes.
  • Private analytics remain local unless converted into separately reviewed aggregate evidence.

Technical SEO/GEO controls

GET /api/public/technical-seo-controlsopen live

Returns object · 9 technical controls

Audit-ready control matrix for the technical SEO/GEO execution behind Visa Atlas: rendering, indexability, schema, API discovery, AI retrieval, freshness, performance and private-evidence boundaries.

Fields

FieldTypeDescription
versionstring (ISO date)Control-matrix version date.
namestringHuman dataset name.
descriptionstringWhat the control matrix covers.
licensestringAlways "CC BY 4.0".
attributionstringThe credit to use: "Visa Atlas".
sourceDatasets[]array<string>Public datasets and contracts used to ground the controls.
methodology.sourceOfTruthstringHow the matrix consolidates existing audits and rendered checks.
methodology.cadencestringWhen source, rendered, liveness and private-evidence controls should run.
methodology.versionInputsobjectVersion dates for the source contracts used by the matrix.
methodology.privateEvidencePolicystringBoundary for analytics, GSC, server logs, snapshots, outreach and reviewer notes.
methodology.caveats[]array<string>Limits on interpreting controls as outcome claims.
summary.controlCountnumberNumber of technical controls.
summary.criticalCountnumberNumber of release-blocking critical controls.
summary.commandCountnumberUnique local evidence commands referenced by the matrix.
controls[]array<object>One technical SEO/GEO control per row.
controls[].categorystringrendering, indexability, structured-data, open-data, ai-retrieval, freshness, performance or evidence-governance.
controls[].severitystringcritical or high.
controls[].auditObjectivestringWhat the control is intended to prove.
controls[].requiredSurfaces[]array<string>Public pages, endpoints or local files that must expose the control.
controls[].evidenceCommands[]array<string>Local commands used to prove the control.
controls[].passCriteria[]array<string>Conditions that must hold for the control to pass.
controls[].failureResponse[]array<string>Required response when the control fails.
controls[].privateEvidenceBoundarystringWhat evidence stays local unless reviewed and aggregated.

Example response

{
  "version": "2026-07-04",
  "name": "Visa Atlas technical SEO/GEO control matrix",
  "summary": {
    "controlCount": 9,
    "criticalCount": 6,
    "commandCount": 27
  },
  "controls": [
    {
      "id": "release-gate-chain",
      "category": "evidence-governance",
      "severity": "critical",
      "requiredSurfaces": ["/api/public/visibility-metrics","/visibility-metrics","scripts/seo-geo-release-gate.mjs"],
      "evidenceCommands": ["npm run audit:seo-geo","npm run audit:release-gate","npm run audit:execution-readiness"],
      "passCriteria": ["TypeScript compiles with no emit.","Source/template SEO/GEO audits pass before build."]
    }
  ]
}
  • This endpoint is a technical control matrix, not proof of rankings, traffic, citations, backlinks or market share.
  • Failed critical controls block release or expansion until corrected.
  • Private evidence remains local unless converted into separately reviewed aggregate evidence.

Topical authority internal-link map

GET /api/public/topical-authority-mapopen live

Returns object · 7 topical clusters

Audit-ready hub-and-spoke map for Visa Atlas SEO/GEO crawl paths, tying each topical authority cluster to its canonical hub, supporting pages, source datasets, internal-link rules, crawl entry points and evidence commands.

Fields

FieldTypeDescription
versionstring (ISO date)Map version date.
namestringHuman dataset name.
descriptionstringWhat the topical authority map covers.
licensestringAlways "CC BY 4.0".
attributionstringThe credit to use: "Visa Atlas".
sourceDatasets[]array<string>Public datasets and contracts used to ground the map.
methodology.sourceOfTruthstringHow clusters are derived from public crawl and evidence surfaces.
methodology.cadencestringWhen to re-check the map.
methodology.versionInputsobjectVersion dates for the source contracts used by the map.
methodology.privateEvidencePolicystringBoundary for analytics, GSC, server logs, snapshots and profile data.
methodology.caveats[]array<string>Limits on interpreting crawl-path controls as outcome claims.
summary.clusterCountnumberNumber of topical authority clusters.
summary.criticalClusterCountnumberNumber of critical clusters.
summary.uniquePageCountnumberUnique public pages and endpoints in the map.
summary.sourceDatasetCountnumberUnique source datasets referenced by cluster rows.
summary.commandCountnumberUnique local evidence commands referenced by cluster rows.
clusters[]array<object>One topical authority cluster per row.
clusters[].primaryHubstringCanonical hub page for the cluster.
clusters[].supportingPages[]array<string>Crawlable pages and endpoints supporting the hub.
clusters[].sourceDatasets[]array<string>JSON feeds grounding the cluster.
clusters[].targetQueries[]array<string>Representative query patterns the cluster serves.
clusters[].internalLinkRules[]array<string>Rules for hub, spoke and sibling links.
clusters[].anchorTextPatterns[]array<string>Descriptive anchor patterns to use in templates and reports.
clusters[].crawlEntryPoints[]array<string>Human pages, JSON feeds and LLM indexes that expose the cluster.
clusters[].evidenceCommands[]array<string>Local commands used to prove crawl-path coverage.
clusters[].successSignals[]array<string>Observable implementation signals for the cluster.
clusters[].failureResponse[]array<string>Required response when crawl-path coverage breaks.
clusters[].privateEvidenceBoundarystringWhat evidence stays local unless reviewed and aggregated.

Example response

{
  "version": "2026-07-04",
  "name": "Visa Atlas topical authority and internal-link map",
  "summary": {
    "clusterCount": 7,
    "criticalClusterCount": 4,
    "uniquePageCount": 69,
    "commandCount": 21
  },
  "clusters": [
    {
      "id": "open-data-ai-retrieval",
      "primaryHub": "/data",
      "supportingPages": ["/api/public","/api","/ai-agents"],
      "sourceDatasets": ["/api/public/visibility-metrics","/api/public/technical-seo-controls","/api/public/indexable-pages"],
      "evidenceCommands": ["npm run audit:data-front-door","npm run audit:openapi","npm run audit:mcp"]
    }
  ]
}
  • This endpoint is a crawl-path and internal-link control map, not proof of rankings, traffic, citations, backlinks or market share.
  • Use it with /api/public/indexable-pages and /api/public/search-index to inspect whether target pages are discoverable.
  • Private evidence remains local unless converted into separately reviewed aggregate evidence.

SEO/GEO audit evidence pack

GET /api/public/seo-geo-audit-evidenceopen live

Returns object · 12 evidence rows

Big-4-style evidence pack mapping the Visa Atlas SEO/GEO dominance plan to public controls, local evidence workflows, remaining external evidence needs, pass criteria, failure responses and private-data boundaries.

Fields

FieldTypeDescription
versionstring (ISO date)Evidence-pack version date.
namestringHuman dataset name.
descriptionstringWhat the evidence pack covers.
licensestringAlways "CC BY 4.0".
attributionstringThe credit to use: "Visa Atlas".
sourceDatasets[]array<string>Public datasets and contracts used to ground the evidence rows.
methodology.sourceOfTruthstringHow rows consolidate public controls, local commands and private-evidence policies.
methodology.completionStandardstringWhy the pack proves control readiness but not the 500k/month outcome.
methodology.signoffRules[]array<string>Rules for public-control, local-workflow and external-evidence rows.
methodology.versionInputsobjectVersion dates for source contracts used by the pack.
methodology.privateEvidencePolicystringBoundary for analytics, GSC, server logs, AI transcripts, outreach and reviewer evidence.
methodology.caveats[]array<string>Limits on interpreting controls as outcome claims.
summary.rowCountnumberNumber of evidence rows.
summary.statusCountsobjectEvidence rows grouped by proved-public-control, local-workflow and external-evidence-needed.
summary.publicEvidenceCountnumberUnique public evidence URLs referenced by rows.
summary.sourceDatasetCountnumberUnique source datasets referenced by rows.
summary.commandCountnumberUnique local evidence commands referenced by rows.
summary.externalEvidenceNeededCountnumberRows that still need external or private reviewed evidence before claims can be made.
summary.evidenceIntakeWorkflowCountnumberReviewed aggregate evidence intake workflows.
evidenceIntakeobjectManifest of reviewed aggregate evidence files, proof commands and claim gates.
evidenceIntake.workflows[]array<object>One intake workflow per local proof artifact.
evidenceIntake.workflows[].inputArtifactstringReviewed aggregate file expected by the proof command.
evidenceIntake.workflows[].requiredApprovalFields[]array<string>Approval fields required before the artifact can support a claim.
evidenceIntake.workflows[].forbiddenRawFields[]array<string>Raw private fields that must not appear in reviewed aggregate files.
evidenceIntake.workflows[].downstreamGatestringClaim or proof gate the workflow feeds.
rows[]array<object>One audit evidence row per SEO/GEO domain.
rows[].domainstringstrategy, source-quality, technical-seo, ai-retrieval, content, competitor, measurement, authority, ymyl-trust or governance.
rows[].statusstringproved-public-control, local-workflow or external-evidence-needed.
rows[].auditQuestionstringQuestion the row is designed to answer.
rows[].publicEvidence[]array<string>Public pages and endpoints a reviewer can inspect.
rows[].sourceDatasets[]array<string>Public JSON feeds grounding the row.
rows[].localCommands[]array<string>Local commands used to prove the row.
rows[].requiredPrivateEvidence[]array<string>Evidence that must stay local until reviewed and aggregated.
rows[].passCriteria[]array<string>Conditions required for the row to pass.
rows[].failureResponse[]array<string>Required response when the row fails.
rows[].privateEvidenceBoundarystringExplicit private-data boundary for the row.

Example response

{
  "version": "2026-07-05",
  "name": "Visa Atlas SEO/GEO audit evidence pack",
  "summary": {
    "rowCount": 12,
    "statusCounts": {"proved-public-control":6,"local-workflow":3,"external-evidence-needed":3},
    "externalEvidenceNeededCount": 3,
    "commandCount": 69,
    "evidenceIntakeWorkflowCount": 9
  },
  "evidenceIntake": {
    "workflowCount": 9,
    "workflows": [
      {
        "id": "production-ticket-evidence",
        "inputArtifact": "seo-geo-ticket-evidence.jsonl",
        "proofCommand": "npm run seo:ticket-evidence -- seo-geo-ticket-evidence.jsonl --json"
      }
    ]
  },
  "rows": [
    {
      "id": "strategy-and-traffic-model",
      "status": "proved-public-control",
      "publicEvidence": ["/research/seo-geo-traffic-forecast-2026","/api/public/traffic-forecast","/visibility-metrics"],
      "localCommands": ["npm run audit:traffic-forecast","npm run audit:visibility-metrics"],
      "privateEvidenceBoundary": "Actual sessions, Search Console rows, AI-citation runs and referrer exports stay local unless reviewed and aggregated."
    }
  ]
}
  • This endpoint is an audit evidence matrix, not proof of current traffic, rankings, citations, backlinks or market share.
  • External-evidence-needed rows cannot be used as outcome claims until reviewed private or external evidence is approved.
  • The 500k/month objective remains unproven until reviewed analytics, Search Console, AI-citation and market-share evidence prove it.

SEO/GEO execution readiness scorecard

GET /api/public/execution-readinessopen live

Returns object · 5 readiness cohorts

Cohort-level execution scorecard tying the Visa Atlas 500k/month SEO/GEO plan to content pieces, page changes, technical gates, competitor wedges, private evidence needs, no-go conditions and pass criteria.

Fields

FieldTypeDescription
versionstring (ISO date)Scorecard version date.
namestringHuman dataset name.
descriptionstringWhat the scorecard covers.
licensestringAlways "CC BY 4.0".
attributionstringThe credit to use: "Visa Atlas".
sourceDatasets[]array<string>Public datasets and contracts used to compile readiness rows.
methodology.planningTargetMonthlyVisitsnumberThe 500k/month planning target; not current traffic.
methodology.sourceOfTruthstringPublic contracts used as the source of truth.
methodology.completionStandardstringWhy the scorecard proves readiness but not outcome success.
methodology.privateEvidencePolicystringBoundary for analytics, GSC, AI outputs, SERP screenshots, logs and outreach records.
methodology.versionInputsobjectVersion dates for source contracts used by the scorecard.
summary.cohortCountnumberNumber of forecast cohorts covered.
summary.statusCountsobjectReadiness rows grouped by control-ready, controlled-build and external-evidence-needed.
summary.lowMonthlyVisitsnumberLow end of the cohort planning range.
summary.highMonthlyVisitsnumberHigh end of the cohort planning range.
summary.commandCountnumberUnique local commands required across rows.
summary.externalEvidenceNeededCountnumberCohorts where external or private reviewed evidence gates outcome claims.
rows[]array<object>One readiness row per traffic forecast cohort.
rows[].statusstringcontrol-ready, controlled-build or external-evidence-needed.
rows[].targetMonthlyVisitsobjectLow/high planning range from the traffic forecast.
rows[].launchDecisionstringOperational decision for scaling or gating the cohort.
rows[].contentPiecesNeeded[]array<string>Content pieces or evidence assets required for the cohort.
rows[].pageChangesNeeded[]array<string>Page-level changes required before scale.
rows[].technicalChangesNeeded[]array<string>Technical gates or implementation changes required.
rows[].competitorWedgestringHow the cohort should beat sampled competitor source classes.
rows[].relatedOpportunityIds[]array<string>Content opportunity rows connected to the cohort.
rows[].relatedBattlecardIds[]array<string>Competitor battlecards connected to the cohort.
rows[].relatedSearchDemandActionIds[]array<string>Search-demand action rules connected to the cohort.
rows[].requiredLocalCommands[]array<string>Local commands required for readiness and measurement.
rows[].requiredPrivateEvidence[]array<string>Private or external evidence required before outcome claims.
rows[].noGoConditions[]array<string>Conditions that block scale, publication or outcome claims.
rows[].passCriteria[]array<string>Conditions required for the cohort to pass review.
rows[].privateEvidenceBoundarystringWhat evidence stays local unless reviewed and aggregated.

Example response

{
  "version": "2026-07-04",
  "name": "Visa Atlas SEO/GEO execution readiness scorecard",
  "summary": {
    "cohortCount": 5,
    "statusCounts": {"control-ready":3,"controlled-build":1,"external-evidence-needed":1},
    "lowMonthlyVisits": 390000,
    "highMonthlyVisits": 600000,
    "commandCount": 28
  },
  "rows": [
    {
      "id": "calculators-tools",
      "status": "control-ready",
      "targetMonthlyVisits": {"low":90000,"high":140000},
      "relatedOpportunityIds": ["calculator-verdict-history","uk-total-migration-cost-builder","germany-recognition-decision-tree"],
      "relatedBattlecardIds": ["uk-skilled-worker-cost-salary","canada-express-entry-freshness","germany-blue-card-salary-recognition"],
      "noGoConditions": ["If flagship calculator/tool pages stay below 0.5% CTR at stable rank after the first reviewed GSC experiment window, rebase the cohort target.","If calculator audits fail or source freshness goes red, freeze new calculator launches until provenance is restored."]
    }
  ]
}
  • This endpoint is a readiness scorecard, not proof of current traffic, rankings, citations, backlinks or market share.
  • Control-ready rows still require reviewed GSC, AI-citation, analytics or external evidence before outcome claims.
  • Use it with /api/public/search-demand-actions when deciding whether to edit, route, noindex or measure a cohort.

SEO/GEO market-share capture plan

GET /api/public/market-share-capture-planopen live

Returns object · 13 battlecard capture rows

Battlecard-level execution plan tying competitor wedges to content pieces, page changes, technical changes, evidence commands, private evidence needs, market-share claim gates and no-go conditions.

Fields

FieldTypeDescription
versionstring (ISO date)Capture-plan version date.
namestringHuman dataset name.
descriptionstringWhat the capture plan covers.
licensestringAlways "CC BY 4.0".
attributionstringThe credit to use: "Visa Atlas".
sourceDatasets[]array<string>Public contracts used to compile the capture rows.
methodology.planningTargetMonthlyVisitsnumberThe 500k/month planning target; not current traffic.
methodology.sourceOfTruthstringPublic battlecard, readiness and market-share contracts used as inputs.
methodology.completionStandardstringWhy the plan proves an execution sequence but not outcome success.
methodology.privateEvidencePolicystringBoundary for analytics, GSC, SERP, AI-answer and reviewer evidence.
methodology.bigFourAuditControls[]array<string>Audit controls that make the plan reviewable.
summary.battlecardCountnumberNumber of battlecard capture rows.
summary.readyToExecuteCountnumberRows where public control surfaces exist for execution.
summary.evidenceGatedCountnumberRows that need reviewed evidence before public progress claims.
summary.targetPageCountnumberUnique target pages across capture rows.
summary.targetPageReferenceCountnumberTarget page references across all capture rows, including duplicates and fragments.
summary.sitemapBackedTargetPageCountnumberTarget references whose base path is present in the indexable-page manifest.
summary.fragmentTargetPageCountnumberTarget references that resolve to a fragment on a sitemap-backed base page.
summary.missingTargetPageCountnumberTarget references whose base path is not present in the indexable-page manifest.
summary.queryCountnumberUnique battlecard queries covered.
summary.productionTicketCountnumberContent, page, technical and evidence tickets generated from the capture rows.
summary.productionTicketCountsobjectProduction ticket counts by workstream.
summary.publicMarketShareClaimAllowedbooleanAlways false until approved aggregate evidence exists.
rows[]array<object>One capture row per competitor battlecard.
rows[].runOrdernumberExecution order for the capture sequence.
rows[].sprintstringExecution sprint: answer-control, page-depth, authority-distribution or evidence-rollup.
rows[].statusstringready-to-execute or evidence-gated.
rows[].battlecardIdstringSource competitor battlecard ID.
rows[].competitorSourceClasses[]array<string>Competitor classes the row is designed to displace.
rows[].competitorDisplacementWedgestringWhy Visa Atlas can beat the sampled competitor class.
rows[].targetPageCoverage[]array<object>Sitemap/indexable-page reconciliation for each target page.
rows[].targetPageCoverage[].statusstringsitemap-backed, fragment-on-sitemap-page or missing.
rows[].targetPageCoverage[].sourceDatasets[]array<string>Indexable-page source datasets attached to the target base path.
rows[].contentPieces[]array<string>Content pieces required for the row.
rows[].pageChanges[]array<string>Target page changes required.
rows[].technicalChanges[]array<string>Technical implementation or audit changes required.
rows[].evidenceCommands[]array<string>Local commands used to gather or verify evidence.
rows[].marketShareClaimGatestringEvidence gate before market-share claims.
rows[].noGoConditions[]array<string>Conditions that block publication, scale or outcome claims.
rows[].privateEvidenceBoundarystringWhat evidence stays local unless reviewed and aggregated.
rows[].productionTickets[]array<object>Ticketable content, page, technical and evidence work derived from the row.
rows[].productionTickets[].ownerFunctionstringEditorial, Growth, Engineering or Data/research owner function.
rows[].productionTickets[].evidenceGatestringGate that must pass before the ticket can support progress claims.
rows[].productionTickets[].definitionOfDonestringAudit-ready done condition for the ticket.

Example response

{
  "version": "2026-07-04",
  "name": "Visa Atlas SEO/GEO market-share capture plan",
  "summary": {
    "battlecardCount": 13,
    "readyToExecuteCount": 11,
    "evidenceGatedCount": 2,
    "targetPageCount": 118,
    "targetPageReferenceCount": 124,
    "sitemapBackedTargetPageCount": 124,
    "missingTargetPageCount": 0,
    "productionTicketCount": 52,
    "publicMarketShareClaimAllowed": false
  },
  "rows": [
    {
      "id": "uk-skilled-worker-cost-salary-capture-plan",
      "runOrder": 1,
      "status": "ready-to-execute",
      "battlecardId": "uk-skilled-worker-cost-salary",
      "contentPieces": ["Battlecard answer shape: Table answer: application fee, IHS, maintenance/proof-of-funds, salary floor, ILR timing, source dates and calculator links.","Single first-answer block separating application fee, IHS, maintenance, salary floor and settlement timing."],
      "pageChanges": ["Tighten /calculators/uk-total-migration-cost, /cost-to-complete/uk-skilled-worker and /salary-thresholds/uk around the same short answer.","Add above-the-fold links from UK Skilled Worker route pages to the total-cost builder, fee page and salary page."],
      "targetPageCoverage": [{"targetPage":"/salary-thresholds/uk","basePath":"/salary-thresholds/uk","status":"sitemap-backed","cohort":"salary-threshold","indexableUrl":"https://visaatlas.org/salary-thresholds/uk","sourceDatasets":["/api/public/salary-thresholds"]},{"targetPage":"/visas/uk/skilled-worker","basePath":"/visas/uk/skilled-worker","status":"sitemap-backed","cohort":"visa-route","indexableUrl":"https://visaatlas.org/visas/uk/skilled-worker","sourceDatasets":["/api/public/visas","/api/public/destinations"]}],
      "marketShareClaimGate": "Blocked until an approved redacted snapshot rollup supplies dated counts, approvedForPublication=true, reviewedAt and reviewedBy.",
      "productionTickets": [{"battlecardId":"uk-skilled-worker-cost-salary","status":"ready-to-execute","targetPages":["/salary-thresholds/uk","/visas/uk/skilled-worker","/calculators/uk-skilled-worker","/cost-to-complete/uk-skilled-worker","/fees/uk/skilled-worker","/calculators/visa-fees","/cost-to-complete/uk-health-and-care-worker","/fees/uk/health-and-care-worker","/visas/uk/health-and-care-worker","/calculators/uk-ilr","/settlement/uk"],"sourceDatasets":["/api/public/competitor-query-battlecards","/api/public/battlecard-search-experiments","/api/public/search-demand-actions","/api/public/execution-readiness","/api/public/content-opportunities","/api/public/quarterly-market-share-summary","/api/public/serp-answer-surface-snapshots","/api/public/traffic-forecast","/api/public/technical-seo-controls","/api/public/visibility-metrics","/api/public/salary-thresholds","/api/public/policy-claims","/api/public/cost-to-complete","/api/public/fees","/api/public/visas","/api/public/source-transparency-benchmark","/api/public/citation-benchmark","/api/public/answer-capsules","/api/public/citation-packs","/api/public/calculator-verdict-contexts","/api/public/publisher-citation-kits","/api/public/external-repository-mirrors"],"id":"uk-skilled-worker-cost-salary-content-production","runOrder":11,"workstream":"content","ownerFunction":"Editorial","title":"UK Skilled Worker cost, IHS and salary floors capture plan: content production","task":"Battlecard answer shape: Table answer: application fee, IHS, maintenance/proof-of-funds, salary floor, ILR timing, source dates and calculator links. Single first-answer block separating application fee, IHS, maintenance, salary floor and settlement timing. Worked family-cost example that distinguishes money paid away from refundable or show-only funds. Citation-pack row for the UK Skilled Worker cost and salary answer used by AI retrievers.","dependencies":["/research/competitor-query-battlecards-2026#uk-skilled-worker-cost-salary","/research/seo-geo-content-opportunity-map-2026#uk-total-migration-cost-builder","/research/seo-geo-content-opportunity-map-2026#cost-to-complete-route-models","/research/seo-geo-content-opportunity-map-2026#verified-answer-capsule-index","/research/seo-geo-content-opportunity-map-2026#calculator-verdict-history","/research/seo-geo-content-opportunity-map-2026#high-risk-page-review-acquisition","/research/seo-geo-content-opportunity-map-2026#reviewedby-schema-rollout","/research/seo-geo-content-opportunity-map-2026#p0-reviewed-page-refresh-sprint","/research/seo-geo-content-opportunity-map-2026#reviewed-page-evidence-publication"],"localCommands":["npm run audit:content-opportunities","npm run audit:answer-capsules","npm run audit:rendered-seo"],"evidenceGate":"All short-answer, methodology, caveat and citation-pack copy must render in static HTML with source dates before release.","noGoCondition":"Do not merge IHS-exempt and non-exempt routes into one cost claim.","definitionOfDone":"Target pages expose the answer shape, source-backed facts, caveats, citation surfaces and internal links required by the battlecard."},{"battlecardId":"uk-skilled-worker-cost-salary","status":"ready-to-execute","targetPages":["/salary-thresholds/uk","/visas/uk/skilled-worker","/calculators/uk-skilled-worker","/cost-to-complete/uk-skilled-worker","/fees/uk/skilled-worker","/calculators/visa-fees","/cost-to-complete/uk-health-and-care-worker","/fees/uk/health-and-care-worker","/visas/uk/health-and-care-worker","/calculators/uk-ilr","/settlement/uk"],"sourceDatasets":["/api/public/competitor-query-battlecards","/api/public/battlecard-search-experiments","/api/public/search-demand-actions","/api/public/execution-readiness","/api/public/content-opportunities","/api/public/quarterly-market-share-summary","/api/public/serp-answer-surface-snapshots","/api/public/traffic-forecast","/api/public/technical-seo-controls","/api/public/visibility-metrics","/api/public/salary-thresholds","/api/public/policy-claims","/api/public/cost-to-complete","/api/public/fees","/api/public/visas","/api/public/source-transparency-benchmark","/api/public/citation-benchmark","/api/public/answer-capsules","/api/public/citation-packs","/api/public/calculator-verdict-contexts","/api/public/publisher-citation-kits","/api/public/external-repository-mirrors"],"id":"uk-skilled-worker-cost-salary-page-production","runOrder":12,"workstream":"page","ownerFunction":"Growth","title":"UK Skilled Worker cost, IHS and salary floors capture plan: page and crawl-path production","task":"Tighten /calculators/uk-total-migration-cost, /cost-to-complete/uk-skilled-worker and /salary-thresholds/uk around the same short answer. Add above-the-fold links from UK Skilled Worker route pages to the total-cost builder, fee page and salary page. Keep Health and Care Worker IHS exemption context visible where the query intent would otherwise collapse routes. Add or verify contextual internal link to /salary-thresholds/uk. Add or verify contextual internal link to /visas/uk/skilled-worker. Add or verify contextual internal link to /calculators/uk-skilled-worker. Add or verify contextual internal link to /cost-to-complete/uk-skilled-worker. Add or verify contextual internal link to /fees/uk/skilled-worker. Add or verify contextual internal link to /calculators/visa-fees.","dependencies":["/research/market-share-capture-plan-2026#uk-skilled-worker-cost-salary-capture-plan","/research/seo-geo-execution-readiness-scorecard-2026#calculators-tools","/research/seo-geo-execution-readiness-scorecard-2026#data-reference"],"localCommands":["npm run audit:topical-authority-map","npm run audit:indexable-page-manifest","npm run audit:longtail-provenance"],"evidenceGate":"Canonical target pages, internal links, indexability intent and crawl-path entry points must be visible in sitemap-backed rendered artifacts.","noGoCondition":"Do not publish a cost winner claim without source-linked current figures.","definitionOfDone":"Target pages are linked from the correct hubs, sitemap/indexable-page intent is coherent, and unsupported variants remain excluded."}]
    }
  ]
}
  • This endpoint is an execution sequence, not proof of current rankings, traffic, citations, backlinks or market share.
  • Every market-share claim remains blocked until approved redacted snapshot rollups and reviewed private evidence exist.
  • Use it with competitor battlecards, execution readiness and search-demand actions when deciding which page work to run next.

SEO/GEO production queue

GET /api/public/seo-geo-production-queueopen live

Returns object · 52 production tickets

Flat ticket queue derived from the market-share capture plan. Use it when an editor, engineer, growth owner or AI agent needs the next executable content, page, technical or evidence task without traversing nested battlecard rows.

Fields

FieldTypeDescription
versionstring (ISO date)Production-queue version date inherited from the capture plan.
namestringHuman dataset name.
descriptionstringWhat the queue covers.
licensestringAlways "CC BY 4.0".
attributionstringThe credit to use: "Visa Atlas".
datasetUrlstringCanonical JSON endpoint for the queue.
humanUrlstringCrawlable report page for the queue.
sourceDatasets[]array<string>Public contracts used to derive and audit the queue.
methodology.sourceOfTruthstringHow tickets are derived from /api/public/market-share-capture-plan.
methodology.completionStandardstringWhy ticket completion does not prove rankings, traffic, citations, backlinks, market share or 500k/month outcomes.
methodology.privateEvidencePolicystringBoundary for raw analytics, GSC, SERP, AI-answer and reviewer evidence.
summary.ticketCountnumberNumber of flat production tickets.
summary.readyToExecuteCountnumberTickets where public control surfaces exist for execution.
summary.evidenceGatedCountnumberTickets blocked by reviewed evidence needs before public progress claims.
summary.workstreamCountsobjectTicket counts by content, page, technical and evidence workstream.
summary.ownerFunctionCountsobjectTicket counts by Editorial, Growth, Engineering and Data/research owner.
summary.publicMarketShareClaimAllowedbooleanAlways false until approved aggregate evidence exists.
tickets[]array<object>One flat production ticket per content/page/technical/evidence task.
tickets[].parentRowIdstringSource market-share capture-plan row ID.
tickets[].parentTitlestringSource market-share capture-plan row title.
tickets[].battlecardIdstringSource competitor battlecard ID.
tickets[].workstreamstringcontent, page, technical or evidence.
tickets[].ownerFunctionstringEditorial, Growth, Engineering or Data/research.
tickets[].targetPages[]array<string>Pages the ticket touches.
tickets[].taskstringHuman production task.
tickets[].dependencies[]array<string>Prerequisites before the ticket can be treated as done.
tickets[].localCommands[]array<string>Local evidence commands for verification.
tickets[].sourceDatasets[]array<string>Public datasets that audit the ticket.
tickets[].evidenceGatestringGate that must pass before the ticket can support progress claims.
tickets[].noGoConditionstringCondition that blocks publication, scale or outcome claims.
tickets[].definitionOfDonestringAudit-ready done condition for the ticket.
tickets[].marketShareClaimGatestringParent battlecard claim gate before market-share statements.
tickets[].privateEvidenceBoundarystringWhat evidence stays local unless reviewed and aggregated.

Example response

{
  "version": "2026-07-04",
  "name": "Visa Atlas SEO/GEO production queue",
  "summary": {
    "ticketCount": 52,
    "workstreamCounts": {"content":13,"page":13,"technical":13,"evidence":13},
    "ownerFunctionCounts": {"Editorial":13,"Engineering":13,"Data/research":13,"Growth":13},
    "publicMarketShareClaimAllowed": false
  },
  "tickets": [
    {
      "id": "uk-skilled-worker-cost-salary-content-production",
      "parentRowId": "uk-skilled-worker-cost-salary-capture-plan",
      "battlecardId": "uk-skilled-worker-cost-salary",
      "workstream": "content",
      "ownerFunction": "Editorial",
      "targetPages": ["/salary-thresholds/uk","/visas/uk/skilled-worker","/calculators/uk-skilled-worker"],
      "evidenceGate": "All short-answer, methodology, caveat and citation-pack copy must render in static HTML with source dates before release.",
      "definitionOfDone": "Target pages expose the answer shape, source-backed facts, caveats, citation surfaces and internal links required by the battlecard."
    }
  ]
}
  • This endpoint is a production queue, not proof of current rankings, traffic, citations, backlinks or market share.
  • Every ticket keeps parent battlecard context so AI agents can cite the source row and its private-evidence boundary.
  • Use it with /api/public/market-share-capture-plan when deciding which ticket to execute next.

SEO/GEO page action map

GET /api/public/seo-geo-page-action-mapopen live

Returns object · 118 target URLs

Page-level join table derived from the production queue. Use it when an agent or auditor needs to know which target URL connects to which production tickets, battlecards, SERP/AI handoff briefs, search-demand actions, answer capsules, citation packs, calculator contexts, source datasets, commands and evidence gates.

Fields

FieldTypeDescription
versionstring (ISO date)Page-action-map version date inherited from the production queue.
namestringHuman dataset name.
descriptionstringWhat the map covers.
licensestringAlways "CC BY 4.0".
attributionstringThe credit to use: "Visa Atlas".
datasetUrlstringCanonical JSON endpoint for the page action map.
humanUrlstringCrawlable report page for the map.
sourceDatasets[]array<string>Public contracts used to derive and audit the map.
methodology.sourceOfTruthstringHow rows are derived from /api/public/seo-geo-production-queue and related datasets.
methodology.joinRules[]array<string>Exact join rules for tickets, answer capsules, citation packs, calculator contexts and search-demand actions.
methodology.completionStandardstringWhy page-action coverage does not prove rankings, traffic, citations, backlinks, market share or 500k/month outcomes.
methodology.privateEvidencePolicystringBoundary for raw analytics, GSC, SERP, AI-answer and reviewer evidence.
summary.pageCountnumberNumber of target URLs in the map.
summary.productionTicketReferenceCountnumberTotal production-ticket references across page rows.
summary.rowsWithAnswerCapsulesnumberTarget URL rows joined to answer capsules.
summary.rowsWithCitationPacksnumberTarget URL rows joined to citation packs.
summary.rowsWithCalculatorContextsnumberTarget URL rows joined to calculator verdict contexts.
summary.rowsWithSerpAiHandoffsnumberTarget URL rows with generated SERP/AI handoff briefs.
summary.rowsNeedingAnswerSurfacenumberTarget URL rows that still need an answer capsule, citation pack or calculator context before they are answer-ready.
summary.publicMarketShareClaimAllowedbooleanAlways false until approved aggregate evidence exists.
rows[]array<object>One target URL with retrieval joins and production-control gates.
rows[].pathstringTarget URL path, including fragment when relevant.
rows[].basePathstringTarget URL without fragment.
rows[].coverageStatusstringsitemap-backed, fragment-on-sitemap-page or missing.
rows[].battlecardIds[]array<string>Competitor battlecards connected to the page.
rows[].productionTickets[]array<object>Content, page, technical and evidence tickets for the page.
rows[].searchDemandActions[]array<object>Search-demand action rules inherited from related tickets.
rows[].serpAiHandoffobjectSERP title/meta/first-answer and AI retrieval handoff brief generated from the page battlecards and retrieval joins.
rows[].serpAiHandoff.titleSnippetRulestringPage-specific rule for leading the title, meta description and first visible answer.
rows[].serpAiHandoff.answerSurfaceStatusstringanswer-capsule, citation-pack, calculator-context or needs-page-answer.
rows[].serpAiHandoff.retrievalSurfaceUrls[]array<string>Canonical target, answer, citation and calculator surfaces available to retrievers.
rows[].serpAiHandoff.noGoBoundarystringPublication or outcome-claim blocker for the handoff.
rows[].answerCapsules[]array<object>Verified answer capsules joined to the page.
rows[].citationPacks[]array<object>Citation packs joined by canonical page or citation-pack fragment.
rows[].calculatorContexts[]array<object>Calculator verdict contexts joined by calculatorPath.
rows[].localCommands[]array<string>Local evidence commands for the page row.
rows[].evidenceGates[]array<string>Gates that must pass before the page can support progress claims.
rows[].noGoConditions[]array<string>Conditions that block publication, scale or outcome claims.
rows[].definitionsOfDone[]array<string>Audit-ready done conditions for linked tickets.
rows[].marketShareClaimGates[]array<string>Claim gates inherited from parent battlecards.

Example response

{
  "version": "2026-07-04",
  "name": "Visa Atlas SEO/GEO page action map",
  "summary": {
    "pageCount": 118,
    "productionTicketReferenceCount": 496,
    "rowsWithAnswerCapsules": 115,
    "rowsWithCalculatorContexts": 9,
    "rowsWithSerpAiHandoffs": 118,
    "rowsNeedingAnswerSurface": 0,
    "publicMarketShareClaimAllowed": false
  },
  "rows": [
    {
      "path": "/salary-thresholds/uk",
      "battlecardIds": ["uk-skilled-worker-cost-salary"],
      "serpAiHandoff": {"primaryIntent":"cost","queryCluster":["UK Skilled Worker visa cost including IHS","UK Skilled Worker minimum salary 2026","Health and Care Worker IHS exemption"],"titleSnippetRule":"Lead the title, meta description and first visible answer with the cost answer for \"UK Skilled Worker visa cost including IHS\", then show the source date and canonical dataset link before broader guidance.","firstAnswerSource":"answer-capsule:salary-uk - What salary do you need for a skilled-work visa in United Kingdom?","answerSurfaceStatus":"answer-capsule","retrievalSurfaceUrls":["/salary-thresholds/uk","https://visaatlas.org/answer-capsules#salary-uk","https://visaatlas.org/salary-thresholds/uk","/api/public/answer-capsules","https://visaatlas.org/citation-packs#answer-capsule-salary-uk","/api/public/citation-packs"],"competitorWedge":"Separate money paid away from money shown, then connect the route cost, salary floor, IHS exemption and ILR timing in one source-backed answer path.","auditGate":"Run rendered SEO, answer-capsule/citation-pack or calculator-context audits, then require reviewed GSC or AI-citation evidence before claiming displacement.","noGoBoundary":"Do not claim rankings, traffic, AI citation share or market-share gains from this handoff without approved aggregate evidence."},
      "productionTickets": [{"id":"uk-skilled-worker-cost-salary-content-production","title":"UK Skilled Worker cost, IHS and salary floors capture plan: content production","battlecardId":"uk-skilled-worker-cost-salary","parentRowId":"uk-skilled-worker-cost-salary-capture-plan","workstream":"content","ownerFunction":"Editorial","status":"ready-to-execute","runOrder":11,"priority":"high","task":"Battlecard answer shape: Table answer: application fee, IHS, maintenance/proof-of-funds, salary floor, ILR timing, source dates and calculator links. Single first-answer block separating application fee, IHS, maintenance, salary floor and settlement timing. Worked family-cost example that distinguishes money paid away from refundable or show-only funds. Citation-pack row for the UK Skilled Worker cost and salary answer used by AI retrievers.","evidenceGate":"All short-answer, methodology, caveat and citation-pack copy must render in static HTML with source dates before release.","noGoCondition":"Do not merge IHS-exempt and non-exempt routes into one cost claim.","definitionOfDone":"Target pages expose the answer shape, source-backed facts, caveats, citation surfaces and internal links required by the battlecard."},{"id":"uk-skilled-worker-cost-salary-page-production","title":"UK Skilled Worker cost, IHS and salary floors capture plan: page and crawl-path production","battlecardId":"uk-skilled-worker-cost-salary","parentRowId":"uk-skilled-worker-cost-salary-capture-plan","workstream":"page","ownerFunction":"Growth","status":"ready-to-execute","runOrder":12,"priority":"high","task":"Tighten /calculators/uk-total-migration-cost, /cost-to-complete/uk-skilled-worker and /salary-thresholds/uk around the same short answer. Add above-the-fold links from UK Skilled Worker route pages to the total-cost builder, fee page and salary page. Keep Health and Care Worker IHS exemption context visible where the query intent would otherwise collapse routes. Add or verify contextual internal link to /salary-thresholds/uk. Add or verify contextual internal link to /visas/uk/skilled-worker. Add or verify contextual internal link to /calculators/uk-skilled-worker. Add or verify contextual internal link to /cost-to-complete/uk-skilled-worker. Add or verify contextual internal link to /fees/uk/skilled-worker. Add or verify contextual internal link to /calculators/visa-fees.","evidenceGate":"Canonical target pages, internal links, indexability intent and crawl-path entry points must be visible in sitemap-backed rendered artifacts.","noGoCondition":"Do not publish a cost winner claim without source-linked current figures.","definitionOfDone":"Target pages are linked from the correct hubs, sitemap/indexable-page intent is coherent, and unsupported variants remain excluded."}],
      "answerCapsules": ["salary-uk"],
      "localCommands": ["npm run audit:content-opportunities","npm run audit:answer-capsules"]
    }
  ]
}
  • This endpoint is relationship metadata, not proof of current rankings, traffic, citations, backlinks or market share.
  • Rows without answer capsules can still be valid when the related workstream is page, technical or evidence.
  • Use it with /api/public/seo-geo-production-queue when selecting the next target URL to edit or audit.

Battlecard retrieval coverage matrix

GET /api/public/battlecard-retrieval-coverageopen live

Returns object · 13 battlecard rows

Battlecard-level SEO/GEO coverage matrix joining competitor query clusters to target pages, page-action rows, answer surfaces, citation packs, AI retrieval prompts, experiments, snapshot protocols, quarterly baselines and evidence gates. It reconciles public retrieval readiness without claiming rankings, traffic, AI citations or market share.

Fields

FieldTypeDescription
versionstring (ISO date)Coverage-matrix version date.
namestringHuman dataset name.
descriptionstringWhat the matrix covers.
licensestringAlways "CC BY 4.0".
attributionstringThe credit to use: "Visa Atlas".
datasetUrlstringCanonical JSON endpoint for the matrix.
humanUrlstringCrawlable report page explaining the join and scoring rules.
sourceDatasets[]array<string>Public datasets used to derive and audit the matrix.
methodology.sourceOfTruthstringHow battlecards join to page actions, AI prompts and measurement contracts.
methodology.joinRules[]array<string>Exact battlecardId, page-action and task-index join rules.
methodology.scoringModel[]array<string>Weights for page-action, citation-pack, answer-surface, AI-task, measurement and claim-gate checks.
methodology.privateEvidencePolicystringBoundary for analytics, Search Console, SERP, AI-answer and reviewer evidence.
summary.battlecardCountnumberNumber of competitor battlecards covered.
summary.publicRetrievalReadyCountnumberRows with complete public retrieval coverage and no external-evidence status.
summary.externalEvidenceNeededCountnumberRows with complete retrieval assets but external or aggregate evidence still required.
summary.assetGapCountnumberRows below the retrieval coverage threshold.
summary.pageActionRowsWithCitationPacksnumberPage-action rows joined to citation packs.
summary.openAiRetrievalGapCountnumberAI retrieval readiness rows below retrieval-ready.
summary.publicMarketShareClaimAllowedbooleanAlways false until approved aggregate evidence exists.
rows[]array<object>One coverage row per competitor query battlecard.
rows[].battlecardIdstringSource competitor query battlecard ID.
rows[].coverageStatusstringpublic-retrieval-ready, external-evidence-needed or asset-gap.
rows[].coverageScorenumberWeighted public retrieval coverage score from 0 to 100.
rows[].retrievalSurfaceIdsobjectJoined answer capsule, citation pack, calculator context and MCP tool IDs.
rows[].measurementSurfaceIdsobjectJoined experiment, snapshot protocol and quarterly baseline IDs.
rows[].coverageobjectCounts for target pages, page actions, answer/citation/calculator joins, AI prompts, tickets, actions, datasets and commands.
rows[].checks[]array<object>Weighted pass/fail checks and remediation.
rows[].nextActions[]array<string>What must happen next before measurement or outcome claims.
rows[].privateEvidenceBoundarystringWhat evidence stays local unless reviewed and aggregated.

Example response

{
  "version": "2026-07-06",
  "name": "Visa Atlas battlecard retrieval coverage matrix",
  "datasetUrl": "/api/public/battlecard-retrieval-coverage",
  "humanUrl": "/research/battlecard-retrieval-coverage-matrix-2026",
  "summary": {
    "battlecardCount": 13,
    "publicRetrievalReadyCount": 11,
    "externalEvidenceNeededCount": 2,
    "assetGapCount": 0,
    "pageActionRowsWithCitationPacks": 118,
    "openAiRetrievalGapCount": 0,
    "publicMarketShareClaimAllowed": false
  },
  "rows": [
    {
      "battlecardId": "germany-blue-card-salary-recognition",
      "coverageStatus": "public-retrieval-ready",
      "coverageScore": 100,
      "coverage": {"targetPageCount":8,"pageActionRowCount":8,"readyToExecutePageCount":8,"evidenceGatedPageCount":0,"pagesWithAnswerCapsules":8,"pagesWithCitationPacks":8,"pagesWithCalculatorContexts":1,"pagesWithSerpAiHandoffs":8,"pagesNeedingAnswerSurface":0,"aiRetrievalTaskCount":3,"highPriorityAiRetrievalTaskCount":3,"retrievalReadyTaskCount":3,"openAiRetrievalGapCount":0,"productionTicketCount":44,"searchDemandActionCount":6,"citationQuestionCount":3,"sourceDatasetCount":37,"commandCount":27},
      "measurementSurfaceIds": {"experimentIds":["germany-blue-card-salary-recognition-gsc-experiment"],"snapshotProtocolIds":["germany-blue-card-salary-recognition-surface-snapshot"],"quarterlyBaselineIds":["germany-blue-card-salary-recognition-market-share-baseline"]}
    }
  ]
}
  • Use this endpoint after /api/public/seo-geo-page-action-map when deciding whether a whole battlecard cluster is retrieval-ready.
  • Rows marked external-evidence-needed have public retrieval assets but still require approved external or aggregate evidence before outcome claims.
  • This endpoint does not prove rankings, traffic, backlinks, AI citation share, market share or the 500k/month planning target.

SEO/GEO dominance gap ledger

GET /api/public/seo-geo-dominance-gap-ledgeropen live

Returns object · 13 battlecard rows

Battlecard-level blocker ledger joining public retrieval coverage, content pieces, page changes, technical work, competitor pressure, reviewer queues, authority distribution and outcome-proof gates for the 500k/month SEO/GEO plan.

Fields

FieldTypeDescription
versionstring (ISO date)Ledger version date.
namestringHuman dataset name.
descriptionstringWhat the ledger covers.
licensestringAlways "CC BY 4.0".
attributionstringThe credit to use: "Visa Atlas".
datasetUrlstringCanonical JSON endpoint for the ledger.
humanUrlstringCrawlable report page explaining joins, blockers and evidence limits.
sourceDatasets[]array<string>Public datasets used to derive and audit the ledger.
methodology.joinRules[]array<string>Battlecard, reviewer, authority and outcome-proof join rules.
methodology.blockerModel[]array<string>Meaning of each dominance gap status.
summary.readyForPrivateMeasurementCountnumberRows whose public controls are ready for private measurement workflows.
summary.reviewerEvidenceNeededCountnumberRows joined to high-risk reviewer queues.
summary.externalEvidenceNeededCountnumberRows blocked by external or approved aggregate evidence.
summary.approvedSnapshotCountnumberApproved live SERP/AI market-share snapshots currently published.
summary.publicTrafficOutcomeClaimAllowedbooleanAlways false until reviewed outcome proof exists.
summary.publicMarketShareClaimAllowedbooleanAlways false until approved market-share proof exists.
rows[]array<object>One blocker row per competitor query battlecard.
rows[].dominanceGapStatusstringready-for-private-measurement, reviewer-evidence-needed, external-evidence-needed or public-asset-gap.
rows[].contentPiecesNeeded[]array<string>Battlecard-level content pieces required by the capture plan.
rows[].pageChangesNeeded[]array<string>Page and crawl-path changes required by the capture plan.
rows[].technicalChangesNeeded[]array<string>Technical changes and audit gates required by the battlecard.
rows[].reviewerQueues[]array<object>Joined reviewer queues for high-risk YMYL page targets.
rows[].outcomeProofNeeded[]array<string>Evidence required before traffic, market-share or 500k/month claims.
rows[].noGoBoundaries[]array<string>Claims that must remain blocked without reviewed evidence.

Example response

{
  "version": "2026-07-06",
  "name": "Visa Atlas SEO/GEO dominance gap ledger",
  "datasetUrl": "/api/public/seo-geo-dominance-gap-ledger",
  "humanUrl": "/research/seo-geo-dominance-gap-ledger-2026",
  "summary": {
    "battlecardCount": 13,
    "readyForPrivateMeasurementCount": 3,
    "reviewerEvidenceNeededCount": 8,
    "externalEvidenceNeededCount": 2,
    "approvedSnapshotCount": 0,
    "publicTrafficOutcomeClaimAllowed": false,
    "publicMarketShareClaimAllowed": false
  },
  "rows": [
    {
      "battlecardId": "uk-skilled-worker-cost-salary",
      "dominanceGapStatus": "reviewer-evidence-needed",
      "publicRetrievalCoverage": {"coverageScore":100,"pageActionRowCount":11,"aiRetrievalTaskCount":4,"openAiRetrievalGapCount":0,"experimentCount":1,"snapshotProtocolCount":1,"quarterlyBaselineCount":1},
      "reviewerQueues": [{"id":"uk-skilled-worker-yml-review","title":"UK Skilled Worker eligibility, salary and total-cost review","priority":"p0","status":"awaiting-credentialed-review","pageTargets":["/visas/uk/skilled-worker","/calculators/uk-skilled-worker","/calculators/uk-total-migration-cost","/cost-to-complete/uk-skilled-worker"]}]
    }
  ]
}
  • Use this endpoint after retrieval coverage when deciding which blocker prevents a battlecard from supporting dominance claims.
  • ready-for-private-measurement is not an outcome claim; it means the public controls are ready for private GSC, SERP, AI and analytics evidence workflows.
  • This endpoint does not prove rankings, traffic, AI citations, backlinks, market share or the 500k/month target.

SEO/GEO measurement run queue

GET /api/public/seo-geo-measurement-run-queueopen live

Returns object · 13 measurement runs

Battlecard-level measurement run queue that turns dominance blockers into private GSC, SERP/AI, reviewer, authority, AI-visibility, market-share and traffic-outcome evidence runs without publishing raw private evidence.

Fields

FieldTypeDescription
versionstring (ISO date)Queue version date.
namestringHuman dataset name.
descriptionstringWhat the queue covers.
licensestringAlways "CC BY 4.0".
attributionstringThe credit to use: "Visa Atlas".
datasetUrlstringCanonical JSON endpoint for the queue.
humanUrlstringCrawlable report page explaining run classes and evidence limits.
sourceDatasets[]array<string>Public datasets used to derive and audit the queue.
methodology.runOrderRules[]array<string>How public controls, reviewer proof, external evidence and final gates are ordered.
methodology.publicationGates[]array<string>Commands and approval flags required before public outcome claims.
summary.runCountnumberNumber of battlecard measurement runs.
summary.runNowPhaseCountnumberRunnable phases before blocker resolution.
summary.finalOutcomeGateCountnumberFinal AI visibility and traffic outcome gates.
summary.priorityActionCountnumberRunnable private-evidence actions after excluding public-control and final outcome gates.
summary.publicTrafficOutcomeClaimAllowedbooleanAlways false until reviewed traffic proof exists.
summary.publicMarketShareClaimAllowedbooleanAlways false until approved market-share proof exists.
priorityBriefobjectRanked next-action brief for private-evidence execution.
priorityBrief.topActions[]array<object>Top runnable reviewer, authority, GSC, SERP/AI and market-share actions.
priorityBrief.topActions[].commands[]array<string>Local commands to run for the action.
priorityBrief.noGoPolicystringWhy priority actions do not permit public outcome claims.
rows[]array<object>One measurement run per competitor query battlecard.
rows[].measurementStatusstringready-for-private-measurement, reviewer-evidence-blocked, external-evidence-blocked or public-asset-blocked.
rows[].firstRunnablePhaseIds[]array<string>Phase IDs that can run before resolving the current blocker.
rows[].blockedBy[]array<string>Current blocker labels, if any.
rows[].phases[]array<object>Public-control, reviewer, authority, GSC, SERP/AI, market-share, AI visibility and traffic proof phases.
rows[].phases[].runClassstringrun-now, run-after-reviewer-evidence, run-after-external-evidence, run-after-public-assets or final-outcome-gate.
rows[].localCommands[]array<string>Local commands needed to collect, review or audit evidence.
rows[].privateEvidenceBoundarystringWhat raw evidence stays local unless reviewed, redacted and aggregated.

Example response

{
  "version": "2026-07-06",
  "name": "Visa Atlas SEO/GEO measurement run queue",
  "datasetUrl": "/api/public/seo-geo-measurement-run-queue",
  "humanUrl": "/research/seo-geo-measurement-run-queue-2026",
  "summary": {
    "runCount": 13,
    "runNowPhaseCount": 39,
    "reviewerEvidenceBlockedCount": 8,
    "externalEvidenceBlockedCount": 2,
    "finalOutcomeGateCount": 26,
    "priorityActionCount": 26,
    "publicTrafficOutcomeClaimAllowed": false,
    "publicMarketShareClaimAllowed": false
  },
  "priorityBrief": {
    "actionCount": 26,
    "topActionCount": 12,
    "topActions": [
      {
        "rank": 1,
        "battlecardId": "uk-skilled-worker-cost-salary",
        "phaseId": "reviewer-proof",
        "runClass": "run-now"
      }
    ]
  },
  "rows": [
    {
      "battlecardId": "uk-skilled-worker-cost-salary",
      "measurementStatus": "reviewer-evidence-blocked",
      "firstRunnablePhaseIds": ["public-control-check","reviewer-proof"],
      "blockedBy": ["reviewer queue: uk-skilled-worker-yml-review"]
    }
  ]
}
  • Use this endpoint after the dominance gap ledger when deciding which private measurement or proof workflow to run next.
  • Run-now phases can still be blocked from public outcome claims until the final approval gates pass.
  • This endpoint does not prove rankings, traffic, AI citations, backlinks, reviewer trust, market share or the 500k/month target.

SEO/GEO reviewer evidence bridge

GET /api/public/seo-geo-reviewer-evidence-bridgeopen live

Returns object · 6 reviewer queues and 8 reviewer-blocked battlecards

Public bridge from reviewer-blocked SEO/GEO battlecards to high-risk reviewer queues, acquisition controls, reviewedBy schema gates, P0 page-refresh controls and local reviewer-proof commands.

Fields

FieldTypeDescription
versionstring (ISO date)Bridge version date.
namestringHuman dataset name.
descriptionstringWhat the bridge covers.
licensestringAlways "CC BY 4.0".
attributionstringThe credit to use: "Visa Atlas".
datasetUrlstringCanonical JSON endpoint for the bridge.
humanUrlstringCrawlable report page explaining reviewer-evidence routing.
sourceDatasets[]array<string>Public controls used to derive and audit the bridge.
methodology.joinRules[]array<string>How battlecards, queues, controls and pages are joined.
methodology.publicationGates[]array<string>Reviewer acquisition, reviewedBy, P0 refresh and proof gates.
methodology.noGoPolicystringWhy the bridge does not permit outcome or trust claims.
summary.reviewerBlockedBattlecardCountnumberReviewer-blocked SEO/GEO battlecards.
summary.reviewerQueueCountnumberReviewer queues blocking those battlecards.
summary.p0ReviewerQueueCountnumberP0 reviewer queues with page-refresh controls.
summary.publicReviewerTrustClaimAllowedbooleanAlways false until reviewed proof exists.
summary.publicReviewedBySchemaClaimAllowedbooleanAlways false until reviewedBy evidence and page-level schema review exist.
summary.publicTrafficOutcomeClaimAllowedbooleanAlways false until reviewed traffic proof exists.
summary.publicMarketShareClaimAllowedbooleanAlways false until approved market-share proof exists.
reviewerQueues[]array<object>One bridge row per reviewer queue that blocks SEO/GEO battlecards.
reviewerQueues[].publicationGate.publicReviewerTrustClaimAllowedbooleanWhether a public reviewer-trust claim is allowed for the queue.
reviewerQueues[].publicationGate.publicReviewedBySchemaClaimAllowedbooleanWhether reviewedBy schema is allowed for the queue.
reviewerQueues[].requiredLocalEvidenceFields[]array<string>Evidence fields required before reviewer handoff, schema export or page refresh.
reviewerQueues[].localCommands[]array<string>Local reviewer acquisition, reviewedBy export, P0 refresh and reviewer-proof commands.
battlecards[]array<object>Reviewer-blocked battlecard rows with queue IDs, runnable phases and no-go conditions.
battlecards[].measurementStatusstringExpected reviewer-evidence-blocked until reviewer evidence exists.
pageHandoffs[]array<object>Target URL to reviewer queue and battlecard joins.
pageHandoffs[].p0ReviewStatusSurfacebooleanWhether the page is covered by the P0 review-status surface.

Example response

{
  "version": "2026-07-07",
  "name": "Visa Atlas SEO/GEO reviewer evidence bridge",
  "datasetUrl": "/api/public/seo-geo-reviewer-evidence-bridge",
  "humanUrl": "/research/seo-geo-reviewer-evidence-bridge-2026",
  "summary": {
    "reviewerBlockedBattlecardCount": 8,
    "reviewerQueueCount": 6,
    "p0ReviewerQueueCount": 3,
    "publicReviewerTrustClaimAllowed": false,
    "publicReviewedBySchemaClaimAllowed": false,
    "publicTrafficOutcomeClaimAllowed": false,
    "publicMarketShareClaimAllowed": false
  },
  "reviewerQueues": [
    {
      "id": "uk-skilled-worker-yml-review-reviewer-evidence-bridge",
      "status": "blocked-pending-reviewer-evidence",
      "battlecardIds": ["uk-skilled-worker-cost-salary"],
      "publicationGate": {
        "publicReviewerTrustClaimAllowed": false,
        "publicReviewedBySchemaClaimAllowed": false
      }
    }
  ],
  "pageHandoffs": [
    {
      "path": "/visas/uk/skilled-worker",
      "p0ReviewStatusSurface": true
    }
  ]
}
  • Use this endpoint after the measurement run queue when a battlecard is reviewer-evidence-blocked.
  • The bridge joins public controls and local command requirements; it is not evidence that reviewer trust or reviewedBy schema has been approved.
  • Raw reviewer notes, private contacts, credential screenshots, Search Console exports, screenshots, transcripts and analytics stay local unless reviewed, redacted and aggregated.

SEO/GEO external evidence bridge

GET /api/public/seo-geo-external-evidence-bridgeopen live

Returns object · 2 external-evidence battlecards and 6 authority channels

Public bridge from external-evidence-blocked SEO/GEO battlecards to authority distribution channels, GSC/SERP/AI evidence workflows, market-share baselines, traffic proof gates and local proof commands.

Fields

FieldTypeDescription
versionstring (ISO date)Bridge version date.
namestringHuman dataset name.
descriptionstringWhat the bridge covers.
licensestringAlways "CC BY 4.0".
attributionstringThe credit to use: "Visa Atlas".
datasetUrlstringCanonical JSON endpoint for the bridge.
humanUrlstringCrawlable report page explaining external-evidence routing.
sourceDatasets[]array<string>Public controls used to derive and audit the bridge.
methodology.joinRules[]array<string>How battlecards, evidence runs, authority channels, baselines and pages are joined.
methodology.publicationGates[]array<string>Authority, market-share, AI-visibility and traffic proof gates.
methodology.noGoPolicystringWhy the bridge does not permit outcome or authority claims.
summary.externalEvidenceBattlecardCountnumberExternal-evidence-blocked SEO/GEO battlecards.
summary.authorityChannelCountnumberAuthority distribution channels tied to the blocked rows.
summary.approvedSnapshotCountnumberApproved market-share snapshots currently published; expected 0 until reviewed rollups exist.
summary.publicAuthorityClaimAllowedbooleanAlways false until reviewed authority proof exists.
summary.publicMarketShareClaimAllowedbooleanAlways false until approved market-share proof exists.
summary.publicAiVisibilityClaimAllowedbooleanAlways false until approved AI visibility proof exists.
summary.publicTrafficOutcomeClaimAllowedbooleanAlways false until reviewed traffic proof exists.
authorityChannels[]array<object>One bridge row per authority channel needed by the external-evidence battlecards.
authorityChannels[].publicationGate.publicAuthorityClaimAllowedbooleanWhether a public authority claim is allowed for the channel.
battlecards[]array<object>External-evidence-blocked battlecard rows with runnable phases and no-go conditions.
battlecards[].measurementStatusstringExpected external-evidence-blocked until reviewed evidence exists.
battlecards[].runNowPhaseIds[]array<string>Authority, GSC and SERP/AI phases that can run before outcome claims.
battlecards[].publicationGate.publicExternalEvidenceClaimAllowedbooleanWhether a public external-evidence claim is allowed for the row.
pageHandoffs[]array<object>Target URL to external-evidence battlecard joins.

Example response

{
  "version": "2026-07-07",
  "name": "Visa Atlas SEO/GEO external evidence bridge",
  "datasetUrl": "/api/public/seo-geo-external-evidence-bridge",
  "humanUrl": "/research/seo-geo-external-evidence-bridge-2026",
  "summary": {
    "externalEvidenceBattlecardCount": 2,
    "authorityChannelCount": 6,
    "approvedSnapshotCount": 0,
    "publicAuthorityClaimAllowed": false,
    "publicMarketShareClaimAllowed": false,
    "publicAiVisibilityClaimAllowed": false,
    "publicTrafficOutcomeClaimAllowed": false
  },
  "battlecards": [
    {
      "id": "digital-nomad-europe-costs-external-evidence-bridge",
      "status": "blocked-pending-external-evidence",
      "battlecardId": "digital-nomad-europe-costs",
      "runNowPhaseIds": ["public-control-check","authority-proof","gsc-experiment","serp-ai-snapshot"]
    }
  ],
  "authorityChannels": [
    {
      "id": "official-mcp-registry-external-evidence-bridge",
      "status": "manual-publication-ready",
      "publicationGate": {
        "publicAuthorityClaimAllowed": false,
        "publicBacklinkClaimAllowed": false
      }
    }
  ]
}
  • Use this endpoint after the measurement run queue when a battlecard is external-evidence-blocked.
  • The bridge joins public controls and local command requirements; it is not evidence that authority, backlinks, market share, AI visibility or traffic have been approved.
  • Raw analytics, Search Console exports, private listing URLs, SERP screenshots, AI transcripts and unapproved rollups stay local unless reviewed, redacted and aggregated.

SEO/GEO private measurement bridge

GET /api/public/seo-geo-private-measurement-bridgeopen live

Returns object · 3 ready battlecards and 21 measurement phase rows

Public bridge from ready-for-private-measurement SEO/GEO battlecards to run-now GSC, SERP/AI, authority, market-share, AI-visibility and traffic proof workflows without exposing raw private evidence.

Fields

FieldTypeDescription
versionstring (ISO date)Bridge version date.
namestringHuman dataset name.
descriptionstringWhat the bridge covers.
licensestringAlways "CC BY 4.0".
attributionstringThe credit to use: "Visa Atlas".
datasetUrlstringCanonical JSON endpoint for the bridge.
humanUrlstringCrawlable report page explaining private-measurement routing.
sourceDatasets[]array<string>Public controls used to derive and audit the bridge.
methodology.joinRules[]array<string>How battlecards, phase runs, experiments, baselines and pages are joined.
methodology.publicationGates[]array<string>GSC, SERP/AI, market-share, AI-visibility and traffic proof gates.
methodology.noGoPolicystringWhy the bridge does not permit public outcome claims.
summary.readyForPrivateMeasurementBattlecardCountnumberBattlecards ready for private measurement.
summary.runNowPhaseCountnumberRun-now private measurement phases.
summary.finalOutcomeGateCountnumberFinal AI visibility and traffic proof gates.
summary.approvedSnapshotCountnumberApproved market-share snapshots currently published; expected 0 until reviewed rollups exist.
summary.publicRankingClaimAllowedbooleanAlways false until reviewed evidence and public claim gates pass.
summary.publicMarketShareClaimAllowedbooleanAlways false until approved market-share proof exists.
summary.publicAiVisibilityClaimAllowedbooleanAlways false until approved AI visibility proof exists.
summary.publicTrafficOutcomeClaimAllowedbooleanAlways false until reviewed traffic proof exists.
summary.public500kMonthClaimAllowedbooleanAlways false until reviewed traffic proof approves the target.
battlecards[]array<object>Ready battlecard rows with phase IDs, experiment IDs, snapshot IDs and no-go conditions.
battlecards[].measurementStatusstringExpected ready-for-private-measurement.
battlecards[].runNowPhaseIds[]array<string>Public-control, authority, GSC, SERP/AI and quarterly rollup phases.
battlecards[].finalOutcomePhaseIds[]array<string>AI visibility and traffic outcome proof gates.
battlecards[].publicationGate.publicRankingClaimAllowedbooleanWhether a public ranking claim is allowed for the row.
phaseRuns[]array<object>One row per run-now or final-outcome phase copied from the measurement queue.
phaseRuns[].publicationGate.publicPhaseOutcomeClaimAllowedbooleanWhether the phase permits a public outcome claim.
pageHandoffs[]array<object>Target URL to ready battlecard and phase joins.

Example response

{
  "version": "2026-07-07",
  "name": "Visa Atlas SEO/GEO private measurement bridge",
  "datasetUrl": "/api/public/seo-geo-private-measurement-bridge",
  "humanUrl": "/research/seo-geo-private-measurement-bridge-2026",
  "summary": {
    "readyForPrivateMeasurementBattlecardCount": 3,
    "runNowPhaseCount": 15,
    "finalOutcomeGateCount": 6,
    "approvedSnapshotCount": 0,
    "publicRankingClaimAllowed": false,
    "publicMarketShareClaimAllowed": false,
    "publicAiVisibilityClaimAllowed": false,
    "publicTrafficOutcomeClaimAllowed": false,
    "public500kMonthClaimAllowed": false
  },
  "battlecards": [
    {
      "id": "uk-global-talent-eligibility-private-measurement-bridge",
      "status": "ready-for-private-measurement",
      "battlecardId": "uk-global-talent-eligibility",
      "runNowPhaseIds": ["public-control-check","authority-proof","gsc-experiment","serp-ai-snapshot","quarterly-market-share-rollup"]
    }
  ],
  "phaseRuns": [
    {
      "id": "uk-global-talent-eligibility-public-control-check-private-measurement-bridge",
      "phaseId": "public-control-check",
      "runClass": "run-now",
      "publicationGate": {
        "publicPhaseOutcomeClaimAllowed": false,
        "publicAggregatePublicationAllowed": false
      }
    }
  ]
}
  • Use this endpoint after the measurement run queue when a battlecard is ready-for-private-measurement.
  • The bridge joins public controls and local command requirements; it is not evidence that ranking, AI visibility, market share or traffic outcomes have been approved.
  • Raw analytics, Search Console exports, SERP screenshots, AI transcripts, authority account evidence and unapproved rollups stay local unless reviewed, redacted and aggregated.

SEO/GEO release gate contract

GET /api/public/seo-geo-release-gateopen live

Returns object · 8 gate checks

Audit-ready release gate for shipping Visa Atlas SEO/GEO changes: compile, source audits, freshness, optional liveness, production build, rendered crawler output, evidence proof checks and outcome-claim boundaries.

Fields

FieldTypeDescription
versionstring (ISO date)Release-gate contract version date.
namestringHuman dataset name.
descriptionstringWhat the release gate covers.
licensestringAlways "CC BY 4.0".
attributionstringThe credit to use: "Visa Atlas".
datasetUrlstringCanonical JSON endpoint for the release-gate contract.
humanUrlstringCrawlable report page explaining the gate checks.
runnerPathstringLocal release-gate runner script.
docsPathstringLocal release-gate documentation.
sourceDatasets[]array<string>Public controls and evidence datasets that support the gate.
methodology.defaultCommandstringOffline deterministic release-gate command.
methodology.releaseSignoffCommandstringRelease sign-off command including network liveness.
methodology.privateEvidencePolicystringWhich raw private evidence stays local.
methodology.noGoPolicystringDeploy and public outcome-claim no-go conditions.
summary.stepCountnumberNumber of release-gate checks.
summary.requiredStepCountnumberRequired offline checks.
summary.optionalNetworkStepCountnumberOptional network sign-off checks.
summary.blocksPublicOutcomeClaimsbooleanWhether the gate blocks public outcome claims without proof.
summary.planningTargetMonthlyVisitsnumber500k/month planning target context, not current traffic proof.
steps[]array<object>One release-gate check per row.
steps[].stepClassstringcompile, source-audit, freshness, network-liveness, build, rendered-audit, claim-boundary or evidence-proof.
steps[].statusstringrequired or optional-network.
steps[].commandstringLocal command used by or related to the release gate.
steps[].sourceSurfaces[]array<string>Files, routes, artifacts or datasets checked by the step.
steps[].proves[]array<string>What the gate proves when it passes.
steps[].failureBlocks[]array<string>What must not ship or be claimed when the step fails.
steps[].privateEvidenceBoundarystringWhich raw evidence stays local for the step.

Example response

{
  "version": "2026-07-07",
  "name": "Visa Atlas SEO/GEO release gate contract",
  "datasetUrl": "/api/public/seo-geo-release-gate",
  "humanUrl": "/research/seo-geo-release-gate-contract-2026",
  "summary": {
    "stepCount": 8,
    "requiredStepCount": 7,
    "optionalNetworkStepCount": 1,
    "blocksPublicOutcomeClaims": true,
    "planningTargetMonthlyVisits": 500000
  },
  "steps": [
    {
      "id": "typescript-compile",
      "label": "TypeScript app/runtime compile",
      "status": "required",
      "command": "npm run typecheck"
    }
  ]
}
  • Use this endpoint before deployment sign-off to inspect exactly what the SEO/GEO release gate proves and blocks.
  • Run npm run audit:seo-geo locally for deterministic release checks; add -- --include-liveness for source-refresh or release sign-off requiring live government-source probes.
  • This endpoint publishes deploy governance, not proof of rankings, traffic, backlinks, AI citations, market share or the 500k/month planning target.

Search demand action map

GET /api/public/search-demand-actionsopen live

Returns object · 7 action rules

Audit-ready decision matrix for turning local GSC, SERP and AI answer-surface evidence into content, page and technical SEO/GEO actions without publishing private query data.

Fields

FieldTypeDescription
versionstring (ISO date)Action-map version date.
namestringHuman dataset name.
descriptionstringWhat the action map covers.
licensestringAlways "CC BY 4.0".
attributionstringThe credit to use: "Visa Atlas".
sourceDatasets[]array<string>Public datasets and contracts used by the action rules.
methodology.sourceOfTruthstringHow action rules are derived from GSC opportunity types, battlecards, snapshot protocols and technical controls.
methodology.privateDataPolicystringBoundary for GSC exports, query strings, clicks, impressions, SERP screenshots and AI transcripts.
methodology.completionStandardstringWhy the map proves decision workflow but not ranking, traffic or 500k/month outcomes.
methodology.versionInputsobjectVersion dates for source contracts used by the map.
summary.actionCountnumberNumber of action rules.
summary.criticalCountnumberNumber of critical action gates.
summary.commandCountnumberUnique local evidence commands referenced by the map.
summary.relatedExperimentCountnumberBattlecard search experiments covered by action rules.
summary.noCreateRuleCountnumberNumber of explicit anti-thin-page/no-create rules.
actions[]array<object>One search-demand action rule per row.
actions[].actionTypestringtitle-snippet-answer-refresh, internal-link-authority-push, source-backed-depth-section, canonical-routing-no-create, serp-ai-market-share-escalation, freshness-stale-claim-refresh or experiment-outcome-publication-gate.
actions[].triggerstringLocal evidence condition that activates the rule.
actions[].localEvidenceInputs[]array<string>Private/local evidence inputs required before action.
actions[].localCommands[]array<string>Local commands used to generate or verify the evidence.
actions[].contentChanges[]array<string>Allowed content changes.
actions[].pageChanges[]array<string>Allowed page-level changes.
actions[].technicalChanges[]array<string>Required technical checks or changes.
actions[].noCreateRules[]array<string>Rules that prevent thin page creation or unearned outcome claims.
actions[].passCriteria[]array<string>Conditions required for the action to pass.
actions[].privateEvidenceBoundarystringWhat evidence stays local unless reviewed and aggregated.

Example response

{
  "version": "2026-07-04",
  "name": "Visa Atlas search demand action map",
  "summary": {
    "actionCount": 7,
    "criticalCount": 4,
    "commandCount": 20,
    "noCreateRuleCount": 15
  },
  "actions": [
    {
      "id": "high-impression-low-ctr-snippet-refresh",
      "actionType": "title-snippet-answer-refresh",
      "priority": "critical",
      "localCommands": ["npm run seo:gsc-opportunities -- gsc-queries.csv --json --period-start=YYYY-MM-DD --period-end=YYYY-MM-DD --property-label=gsc-domain-redacted --search-type=web","npm run seo:gsc-battlecard-experiments -- gsc-queries.csv --json --period-start=YYYY-MM-DD --period-end=YYYY-MM-DD --property-label=gsc-domain-redacted --search-type=web"],
      "noCreateRules": ["Do not create a new page for a low-CTR query when an existing canonical page can answer it."]
    }
  ]
}
  • This endpoint publishes action rules, not private Search Console rows or analytics evidence.
  • A query opportunity does not justify a new page unless source-backed uniqueness, crawl path and maintenance ownership are proven.
  • The action map does not guarantee rankings, traffic, AI citations or market-share gains.

Crawler and AI retrieval access audit

GET /api/public/crawler-accessopen live

Returns object · 25 crawler policy rows

Public audit of the robots policy, AI/search crawler access rules, crawler-facing discovery surfaces, API Link headers and local server-log proof commands. It proves access intent and discovery wiring without claiming live crawler fetches, citations or rankings.

Fields

FieldTypeDescription
versionstring (ISO date)Audit version date.
namestringHuman audit name.
datasetUrlstring (URL)Canonical JSON endpoint for the audit.
humanUrlstring (URL)Crawlable research report explaining the access matrix.
robotsTxtUrlstring (URL)Generated robots.txt URL.
sitemapUrlstring (URL)XML sitemap advertised from robots.txt.
summary.explicitAllowCountnumberCrawler rows explicitly allowed in robots.txt.
summary.inheritedAllowCountnumberCrawler rows allowed by the wildcard robots rule.
summary.deniedCrawlerCountnumberAggressive scraper rows explicitly disallowed.
summary.identityVerificationSourceCountnumberOfficial identity verification sources documented for WAF and verified-fetch workflows.
summary.officialIpRangeSourceCountnumberOfficial IP range JSON sources referenced by the audit.
crawlerPolicies[]array<object>One user-agent policy row per crawler or crawler class.
crawlerPolicies[].userAgentstringCrawler user-agent token or robots token.
crawlerPolicies[].accessPolicystringexplicit-allow, inherited-allow or disallow.
crawlerPolicies[].evidenceSurfaces[]array<string>Public pages or files supporting the row.
technicalChecks[]array<object>Crawler-facing discovery, header and log-proof controls.
identityVerificationSources[]array<object>Official crawler identity sources for IP-range, reverse-DNS and robots-token-only verification.
identityVerificationSources[].verificationMethodstringip-range-json, reverse-dns-and-ip-range or robots-token-only.
identityVerificationSources[].ipRangeUrls[]array<string>Official crawler publisher IP range JSON URLs, where available.
methodology.liveProofPolicystringExplanation that live fetch proof requires server logs or Search Console.
methodology.identityProofPolicystringExplanation that user-agent strings alone are not proof.
methodology.commands[]array<string>Local audit and server-log commands.

Example response

{
  "version": "2026-07-03",
  "name": "Visa Atlas crawler and AI retrieval access audit",
  "datasetUrl": "https://visaatlas.org/api/public/crawler-access",
  "humanUrl": "https://visaatlas.org/research/crawler-ai-retrieval-access-audit-2026",
  "summary": {
    "explicitAllowCount": 13,
    "inheritedAllowCount": 4,
    "deniedCrawlerCount": 8,
    "technicalCheckCount": 8,
    "identityVerificationSourceCount": 7,
    "officialIpRangeSourceCount": 5
  },
  "crawlerPolicies": [
    {
      "userAgent": "GPTBot",
      "accessPolicy": "explicit-allow",
      "robotsDirective": "allow",
      "evidenceSurfaces": ["/robots.txt","/api/public/crawler-access","/research/crawler-ai-retrieval-access-audit-2026"]
    }
  ],
  "identityVerificationSources": [
    {
      "userAgents": ["GPTBot"],
      "verificationMethod": "ip-range-json",
      "ipRangeUrls": ["https://openai.com/gptbot.json"]
    }
  ]
}
  • Allowed in robots.txt is not a ranking, indexing, citation or traffic guarantee.
  • A user-agent string alone is not verified fetch proof; use official IP range JSON or reverse/forward DNS checks where available.
  • Raw server logs, Search Console exports and unpublished referral evidence remain local.
  • Use npm run seo:botlog -- logs.txt --json to classify live crawler hits from a server log export.

Source freshness

GET /api/public/freshnessopen live

Returns object · 1674 dated records checked

Public source-freshness report for YMYL auditability: every dated record is evaluated against the same SLA tiers used by the internal stale-source tripwire.

Fields

FieldTypeDescription
asOfstring (ISO date)Date the freshness report was generated against.
thresholdsobjectSLA tier definitions for processing-times, money-thresholds and narrative records.
totals.checkedItemsnumberTotal number of dated records evaluated.
totals.freshnumberRecords inside their SLA and not yet in the due-soon window.
totals.dueSoonnumberRecords at or beyond 80% of their SLA threshold.
totals.stalenumberRecords older than their tier threshold.
totals.invalidDatesnumberRecords with missing or invalid date values.
summaries[]array<object>Per-tier rollup: total, fresh, dueSoon, stale, invalidDates and oldestAgeDays.
stale[]array<object>Stale or invalid item records, including URL, field, date, ageDays, thresholdDays and source URL where available.
dueSoon[]array<object>Records nearing their SLA threshold.
items[]array<object>Every dated record evaluated by the report.

Example response

{
  "asOf": "2026-07-17",
  "totals": {
    "checkedItems": 1674,
    "fresh": 1621,
    "dueSoon": 0,
    "stale": 53,
    "invalidDates": 0
  },
  "summaries": [
    {
      "tier": "processing-times",
      "thresholdDays": 45,
      "total": 98,
      "stale": 53
    }
  ],
  "stale": []
}
  • The same report powers /freshness and npm run audit:stale, so the public dashboard and internal alerting share one SLA model.
  • A stale record does not mean the underlying government fact is wrong; it means the Visa Atlas review date has exceeded the public SLA.

Processing-time planning reliability

GET /api/public/processing-reliabilityopen live

Returns object · 98 scored processing clocks

Derived index scoring how usable each official processing-time clock is for planning. The score rewards a published clock, a narrow decision window, percentile disclosure and recent source verification; it does not predict individual case outcomes.

Fields

FieldTypeDescription
versionstring (ISO date)Index version date.
namestringStable index name.
sourceDatasetstringUnderlying source dataset: /api/public/processing-times.
methodology.scoreMaxnumberMaximum possible score, currently 100.
methodology.components[]array<object>Scoring components and maximum points.
methodology.caveats[]array<string>Interpretation limits for audit and reuse.
summaryobjectCounts, average score, grade counts and disclosure counts.
strongest[]array<object>Top-scoring route clocks.
weakest[]array<object>Lowest-scoring or most opaque route clocks.
rows[]array<object>One scored processing-time record per route.
rows[].scorenumber0-100 planning-transparency score.
rows[].gradestringstrong, usable, watch or opaque.
rows[].scoreBreakdownobjectComponent points: officialClock, windowWidth, percentileDisclosure and freshness.
rows[].delayTriggerstringWhen to treat the case as delayed, based on the source record.
rows[].sourceUrlstringOfficial source URL behind the processing-time record.

Example response

{
  "version": "2026-07-01",
  "name": "Visa Atlas processing-time planning reliability index",
  "sourceDataset": "/api/public/processing-times",
  "summary": {
    "count": 98,
    "scoreAverage": 66.4,
    "notPublishedCount": 8,
    "percentileCount": 6
  },
  "rows": [
    {
      "id": "au-subclass-482-tss",
      "decisionWindow": "2 weeks – 8 weeks",
      "score": 90,
      "grade": "strong",
      "scoreBreakdown": {
        "officialClock": 40,
        "windowWidth": 20,
        "percentileDisclosure": 15,
        "freshness": 15
      }
    }
  ]
}
  • A high score means the published clock is more usable for planning; it is not a guarantee that a case will be decided by that date.
  • Opaque routes can still be valid routes; the score only reflects published planning transparency.

Skilled-migration planning accessibility

GET /api/public/skilled-migration-accessibilityopen live

Returns object · 30 scored migration routes

Derived index scoring tracked skilled and skilled-adjacent routes by planning accessibility. The score combines applicant cost, proof-of-funds exposure, salary floor, processing-clock transparency, sponsor requirement, settlement path and source freshness; it is not a route recommendation or outcome prediction.

Fields

FieldTypeDescription
versionstring (ISO date)Index version date.
namestringStable index name.
sourceDatasets[]array<string>Underlying public datasets used by the derived score.
methodology.scoreMaxnumberMaximum possible score, currently 100.
methodology.components[]array<object>Scoring components and maximum points.
methodology.caveats[]array<string>Interpretation limits for audit and reuse.
summaryobjectCounts, average score, grade counts and mapped-source counts.
mostAccessible[]array<object>Top-scoring lower-friction planning profiles.
highestFriction[]array<object>Lowest-scoring higher-friction planning profiles.
rows[]array<object>One scored route record per cost-to-complete model.
rows[].scorenumber0-100 planning-accessibility score.
rows[].gradestringmore-accessible, balanced, complex or high-friction.
rows[].scoreBreakdownobjectComponent points: sunkCost, refundableFunds, salaryFloor, processingReliability, sponsorFlexibility, settlementPath and sourceFreshness.
rows[].sunkCostobjectLocal and approximate-USD mandatory non-refundable cost range.
rows[].refundableFundsobject|nullLocal and approximate-USD proof-of-funds exposure, where tracked.
rows[].lowestSalaryThresholdobject|nullLowest mapped route-specific salary or income floor, where tracked.
rows[].sourceUrls[]array<object>Route, cost, salary, processing and FX source URLs behind the row.

Example response

{
  "version": "2026-07-01",
  "name": "Visa Atlas skilled-migration planning accessibility index",
  "sourceDatasets": [
    "/api/public/cost-to-complete",
    "/api/public/processing-reliability",
    "/api/public/salary-thresholds",
    "/api/public/visas"
  ],
  "summary": {
    "count": 30,
    "averageScore": 67.1,
    "unsponsoredCount": 11,
    "settlementPathCount": 24
  },
  "rows": [
    {
      "id": "de-chancenkarte",
      "score": 89,
      "grade": "more-accessible",
      "routePath": "/visas/germany/chancenkarte",
      "costPath": "/cost-to-complete/germany-chancenkarte",
      "sunkCost": {
        "approxUsdLabel": "$628-$1,270"
      },
      "scoreBreakdown": {
        "sunkCost": 17,
        "refundableFunds": 12,
        "salaryFloor": 15,
        "processingReliability": 15,
        "sponsorFlexibility": 15,
        "settlementPath": 10,
        "sourceFreshness": 5
      }
    }
  ]
}
  • A high score means lower planning friction in the tracked dimensions; it is not legal advice and not a prediction of eligibility, timing or outcome.
  • Use the row sourceUrls and sourceDatasets fields to cite the underlying facts behind each score.

Country comparisons

GET /api/public/country-comparisonsopen live

Returns object · 3192 indexed comparison pairs

Derived inventory of indexable country comparison pages. It exposes destination profiles and pair-level metrics for route count, sponsor flexibility, settlement routes, dominant skilled routes, salary floors, processing clocks, tracked sunk cost and recent policy activity.

Fields

FieldTypeDescription
versionstring (ISO date)Dataset version date.
namestringStable dataset name.
sourceDatasets[]array<string>Underlying public datasets used to derive the profiles and pair metrics.
methodology.indexedPairRulestringThe shared compare-page index gate used to decide which pairs are included.
methodology.caveats[]array<string>Reuse limits: not legal advice, not a recommendation, not a complete global census.
summaryobjectDestination count, pair count, editorial overlay count and source dataset count.
destinations[]array<object>One derived profile per full-coverage comparison destination.
destinations[].routeCountobjectTracked route totals: total, sponsorRequired, sponsorNotRequired and settlementPath.
destinations[].dominantSkilledRouteobject|nullDominant skilled route used by the compare page, where mapped.
destinations[].lowestSalaryThresholdobject|nullLowest mapped salary or income floor in the source-linked salary dataset.
destinations[].fastestProcessingClockobject|nullFastest tracked centrally published processing window for the destination.
destinations[].lowestTrackedSunkCostobject|nullLowest tracked cost-to-complete mandatory non-refundable cost profile.
destinations[].sourceUrls[]array<object>Government portal and metric source URLs behind the profile.
pairs[]array<object>One row per indexable /compare/{a}/vs/{b} page.
pairs[].pathstringCanonical compare page path.
pairs[].hasEditorialNotebooleanWhether the pair includes an authored comparison overlay.
pairs[].metrics[]array<object>Pair-level metric rows with metric, a, b and basis fields.
pairs[].sourceUrls[]array<object>Deduplicated source URLs backing the comparison.

Example response

{
  "version": "2026-07-01",
  "name": "Visa Atlas country comparison data",
  "sourceDatasets": [
    "/api/public/visas",
    "/api/public/destinations",
    "/api/public/salary-thresholds",
    "/api/public/processing-times",
    "/api/public/cost-to-complete",
    "/api/public/skilled-migration-accessibility",
    "/api/public/policy-updates"
  ],
  "summary": {
    "destinationCount": 178,
    "pairCount": 3192,
    "editorialPairCount": 20
  },
  "pairs": [
    {
      "id": "al-vs-au",
      "path": "/compare/albania/vs/australia",
      "hasEditorialNote": false,
      "metrics": [
        {
          "metric": "trackedRoutes",
          "a": 6,
          "b": 9
        }
      ]
    }
  ]
}
  • Use pairs[].path when citing the human comparison page and sourceUrls/sourceDatasets when citing the underlying facts.
  • This endpoint mirrors the rendered /compare index gate; it is not a personalised immigration recommendation.

Fees

GET /api/public/feesopen live

Returns array<object> · 37 fee breakdowns

Government-published fee breakdowns by destination and visa route — every line item with its amount and currency, a worked example for the headline case, and guidance on dependants and volatility.

Fields

FieldTypeDescription
destinationIsostringDestination key.
visaSlugstringRoute slug the fees apply to.
lines[]array<object>Individual fee lines (see sub-fields).
lines[].labelstringWhat the charge is.
lines[].amountLocalnumberAmount in the local currency.
lines[].currencystring (ISO 4217)Currency code, e.g. "GBP".
lines[].mandatorybooleanWhether the line is unavoidable (false = optional/conditional, e.g. priority service).
lines[].perstring?Unit, when the charge recurs, e.g. "per year of leave, per person".
lines[].notestring?Caveats or conditions.
lines[].sourceUrlstring?Line-specific official source, where it differs from the record source.
workedExampleobjectA representative all-in total: { label, totalLocal, currency, breakdown[] }.
dependantFeesobject?Dependant guidance: { perDependant, caveats? }.
summarystringPlain-language headline cost.
volatilitystringWhat recently changed and what to watch — the figure most likely to move.
sourceNamestringName of the primary source.
sourceUrlstringOfficial primary source URL.
lastCheckedstring (ISO date)When we last verified the figures.

Example response

[
  {
    "destinationIso": "uk",
    "visaSlug": "skilled-worker",
    "lines": [
      { "label": "Application fee (up to 3 years, outside UK, general)", "amountLocal": 819, "currency": "GBP", "mandatory": true, "sourceUrl": "https://www.gov.uk/skilled-worker-visa/how-much-it-costs" },
      { "label": "Immigration Health Surcharge (IHS)", "amountLocal": 1035, "currency": "GBP", "per": "per year of leave, per person", "mandatory": true, "note": "Reduced to £776/year for students and under-18s." }
    ],
    "workedExample": {
      "label": "Single applicant, 3-year CoS, general rate, no priority",
      "totalLocal": 3943.2,
      "currency": "GBP",
      "breakdown": ["£819 application fee", "£3,105 IHS (£1,035 × 3 years)", "£19.20 biometrics", "Plus £525 CoS fee (typically borne by the sponsor)"]
    },
    "dependantFees": { "perDependant": "Each dependant pays the same application fee plus their own IHS…" },
    "summary": "The UK Skilled Worker visa costs around £3,950 in government fees…",
    "volatility": "IHS rose 66% on 6 February 2024 and remains £1,035/year…",
    "sourceName": "GOV.UK — Skilled Worker visa: how much it costs",
    "sourceUrl": "https://www.gov.uk/skilled-worker-visa/how-much-it-costs",
    "lastChecked": "2026-05-31"
  }
]
  • Amounts are exact local-currency figures; we do not convert between currencies in this dataset.
  • A line with mandatory:false is optional or conditional — read its note before adding it to a total.

Cost to complete

GET /api/public/cost-to-completeopen live

Returns array<object> · 30 route cost models

All-in route cost models that separate non-refundable sunk costs from refundable proof-of-funds requirements. Use this when the question is "what do I actually need to budget?", not just "what is the government visa fee?".

Fields

FieldTypeDescription
routeKeystringStable internal key for the cost model.
pageSlugstringURL slug for /cost-to-complete/{pageSlug}.
destinationIsostringDestination key.
visaSlugstringRoute slug the model applies to.
titlestringHuman-readable model title.
summarystringPlain-language explanation of what the model includes.
lines[]array<object>Line-item cost records.
lines[].labelstringCost line label.
lines[].amountLocalnumber?Exact amount in local currency when a single figure applies.
lines[].minLocalnumber?Lower bound when the cost is a range.
lines[].maxLocalnumber?Upper bound when the cost is a range.
lines[].currencystring (ISO 4217)Currency code.
lines[].kindstringgovernment-fee, proof-of-funds, service or insurance.
lines[].refundablebooleanTrue when the money is shown or blocked rather than normally lost.
lines[].mandatorybooleanWhether the line is part of the baseline cost model.
lines[].indicativeboolean?True where the figure is an editorial estimate or provider range rather than one official tariff.
lines[].sourceNamestring?Source label for this line.
lines[].sourceUrlstring?Source URL for this line, where available.
methodologyNotestringHow the sunk/refundable split is calculated.
lastCheckedstring (ISO date)When the model was last verified.

Example response

[
  {
    "routeKey": "de-chancenkarte",
    "pageSlug": "germany-chancenkarte",
    "destinationIso": "de",
    "visaSlug": "chancenkarte",
    "title": "Germany Chancenkarte - total cost to complete",
    "lines": [
      { "label": "Consular visa application fee", "amountLocal": 75, "currency": "EUR", "kind": "government-fee", "refundable": false, "mandatory": true },
      { "label": "Blocked account funding", "amountLocal": 13092, "currency": "EUR", "kind": "proof-of-funds", "refundable": true, "mandatory": true }
    ],
    "methodologyNote": "Sunk-cost range sums every mandatory, non-refundable line...",
    "lastChecked": "2026-06-22"
  }
]
  • Do not add refundable proof-of-funds lines to non-refundable sunk-cost totals.
  • Indicative lines should be quoted as ranges or caveats, not exact government tariffs.

Salary thresholds

GET /api/public/salary-thresholdsopen live

Returns array<object> · 21 destination blocks · 61 thresholds

Minimum-salary floors by destination, grouped into one block per destination. Each block holds the individual route thresholds with their local-currency amount, basis and effective date.

Fields

FieldTypeDescription
destinationIsostringDestination key.
overviewstringHow the destination structures its salary floors.
thresholds[]array<object>The individual route thresholds (see sub-fields).
thresholds[].routeLabelstringWhich floor this is.
thresholds[].visaSlugstringRoute the threshold applies to.
thresholds[].amountLocalnumberThreshold amount in local currency. A value of 0 means the authority does not publish one fixed numeric floor; read description/overview for the pay test.
thresholds[].currencystring (ISO 4217)Currency code.
thresholds[].basisstringPeriod the amount is expressed over: "annual", "monthly" or "hourly".
thresholds[].approxUsdnumberApproximate USD equivalent — for cross-country comparison and ranking only, not a live FX quote.
thresholds[].descriptionstringContext and the rule (e.g. higher-of going rate).
thresholds[].effectiveFromstring (ISO date)When this amount took effect.
thresholds[].sourceUrlstringOfficial source URL.
thresholds[].sourceNamestringName of the source.
volatilitystringRecent movements and what to watch.
lastCheckedstring (ISO date)When the block was last verified.

Example response

[
  {
    "destinationIso": "uk",
    "overview": "The UK Home Office sets separate salary floors for variants of the Skilled Worker route…",
    "thresholds": [
      {
        "routeLabel": "Skilled Worker — general threshold",
        "visaSlug": "skilled-worker",
        "amountLocal": 41700,
        "currency": "GBP",
        "basis": "annual",
        "approxUsd": 49000,
        "description": "The default minimum salary, raised to £41,700 on 22 July 2025…",
        "effectiveFrom": "2025-07-22",
        "sourceUrl": "https://www.gov.uk/guidance/immigration-rules/immigration-rules-appendix-skilled-worker",
        "sourceName": "GOV.UK — Appendix Skilled Worker"
      }
    ],
    "volatility": "The general rate rose from £26,200 to £38,700 in April 2024, then to £41,700 on 22 July 2025…",
    "lastChecked": "2026-05-30"
  }
]
  • approxUsd is a rounded comparison figure only — for the real requirement always use amountLocal + currency. If amountLocal is 0, do not read it as a zero salary requirement; the route uses a no-fixed-floor pay test described in the row.

Processing times

GET /api/public/processing-timesopen live

Returns array<object> · 98 bands

Typical decision-time bands by destination and visa route, taken from each authority where it publishes one. Where no central decision time exists, the band is flagged rather than guessed.

Fields

FieldTypeDescription
destinationIsostringDestination key.
visaSlugstringRoute slug.
typicalMinDaysnumber?Lower bound of the typical decision window, in days. Absent when notPublished is true.
typicalMaxDaysnumber?Upper bound, in days. Absent when notPublished is true.
p80Daysnumber?80th-percentile day count, where the authority publishes one.
summarystringPlain-language window and what it measures.
notestring?Caveats (priority services, backlogs, etc.).
notPublishedboolean?true when no central decision time exists (granted on arrival, route closed, or not committed to).
guidancestring?What to check instead, present when notPublished is true.
sourceNamestringName of the source.
sourceUrlstringOfficial source URL.
lastCheckedstring (ISO date)When last verified.

Example response

[
  {
    "destinationIso": "uk",
    "visaSlug": "skilled-worker",
    "typicalMinDays": 15,
    "typicalMaxDays": 21,
    "summary": "GOV.UK publishes 3 weeks as the typical decision window for applications made outside the UK.",
    "note": "Priority service aims for 5 working days; super-priority next working day…",
    "sourceName": "GOV.UK — Visa decision waiting times",
    "sourceUrl": "https://www.gov.uk/guidance/visa-decision-waiting-times-applications-outside-the-uk",
    "lastChecked": "2026-04-20"
  },
  {
    "destinationIso": "ie",
    "visaSlug": "stamp-4",
    "notPublished": true,
    "summary": "Stamp 4 is granted on arrival or at registration; there is no separate consular decision period.",
    "guidance": "Check the specific pathway for the permission rules that apply.",
    "sourceName": "Irish Immigration Service — Registration Office",
    "sourceUrl": "https://www.irishimmigration.ie/registering-your-immigration-permission/",
    "lastChecked": "2026-04-20"
  }
]
  • These are decision windows, not end-to-end timelines — appointment, skills-assessment and card-issuance steps often dwarf the decision itself.

Canada Express Entry categories

GET /api/public/express-entry-categoriesopen live

Returns object · 10 current categories

A derived 2026 category-based selection tracker over the official Express Entry draw history and IRCC current category guidance. Use it when you need category status, category CRS ranges, categories that have not drawn yet, and program rounds kept separate from category rounds.

Fields

FieldTypeDescription
versionstring (ISO date)Report version date; matches the draw feed reconciliation date.
sourceDatasets[]array<string>Underlying public datasets, currently /api/public/express-entry-draws.
officialSources[]array<object>IRCC source records for draw rounds and category-based selection guidance.
methodologyobjectSource-of-truth statement, included-row rule and caveats.
summaryobjectCounts for current categories, drawn/not-drawn categories, category rounds and invitations.
summary.latestCategoryDrawobject|nullMost recent category-based round in the tracked 2026 draw history.
summary.lowestCategoryCrsobject|nullLowest category-based CRS cut-off in the tracked 2026 draw history.
rows[]array<object>One row per current IRCC category, including rows with no 2026 draw.
rows[].officialLabelstringIRCC category label.
rows[].drawnThisYearbooleanWhether that category has held at least one 2026 category-based round.
rows[].roundsThisYearnumberNumber of 2026 category rounds for that category.
rows[].invitationsThisYearnumberITAs issued in that category in 2026.
rows[].minCrsThisYearnumber|nullLowest 2026 CRS cut-off for the category; null if no draw yet.
rows[].maxCrsThisYearnumber|nullHighest 2026 CRS cut-off for the category; null if no draw yet.
rows[].latestDrawobject|nullLatest draw for that category, with round/date/ITAs/CRS; null if none.
programDrawsThisYear[]array<object>Canadian Experience Class, Provincial Nominee Program and general rounds, separated from category rows.

Example response

{
  "version": "2026-07-15",
  "name": "Visa Atlas Canada Express Entry category tracker",
  "sourceDatasets": ["/api/public/express-entry-draws"],
  "summary": {
    "categoryCount": 10,
    "categoriesDrawn": 5,
    "categoriesNotDrawn": 5,
    "latestCategoryDraw": {"round":426,"date":"2026-07-10","category":"Senior managers","invitations":500,"crsCutoff":392}
  },
  "rows": [
    {
      "category": "Healthcare and social services",
      "officialLabel": "Healthcare and social services occupations",
      "drawnThisYear": true,
      "roundsThisYear": 2,
      "invitationsThisYear": 8000,
      "minCrsThisYear": 467,
      "maxCrsThisYear": 475,
      "latestDraw": {"round":422,"date":"2026-06-25","category":"Healthcare and social services","invitations":4000,"crsCutoff":475,"daysSinceDraw":20,"crsChangeFromPreviousCategoryDraw":8}
    }
  ]
}
  • Rows with drawnThisYear=false are intentionally present: no-draw categories are useful evidence for category-specific queries.
  • A category CRS cut-off is a historical result for one round, not a target score or invitation guarantee.

Canada Express Entry draws

GET /api/public/express-entry-drawsopen live

Returns object · 41 rounds

The round-by-round history of Canada Express Entry invitations, confirmed against IRCC’s official feed and refreshed weekly. Unlike the other endpoints this returns an object with provenance at the top and the draws array underneath.

Fields

FieldTypeDescription
officialSourceobjectIRCC source: { label, url, authority }.
lastVerifiedstring (ISO date)When the feed was last reconciled against IRCC.
draws[]array<object>The rounds, newest first (see sub-fields).
draws[].roundnumberIRCC sequential round number.
draws[].datestring (ISO date)Draw date.
draws[].categorystringProgram or category-based selection type, e.g. "French-language proficiency", "Canadian Experience Class", "Provincial Nominee Program", "Healthcare and social services", "Trade occupations", "Physicians".
draws[].invitationsnumberInvitations to apply (ITAs) issued.
draws[].crsCutoffnumberComprehensive Ranking System cut-off score for the round.

Example response

{
  "officialSource": {
    "label": "IRCC — Express Entry rounds of invitations",
    "url": "https://www.canada.ca/en/immigration-refugees-citizenship/services/immigrate-canada/express-entry/submit-profile/rounds-invitations.html",
    "authority": "Immigration, Refugees and Citizenship Canada"
  },
  "lastVerified": "2026-07-15",
  "draws": [
    { "round": 426, "date": "2026-07-10", "category": "Senior managers", "invitations": 500, "crsCutoff": 392 }
  ]
}
  • A CRS cut-off is a per-round result, not a target — category draws can post far lower cut-offs than program draws because the eligible pool is smaller.

Rules and threshold fact changes

GET /api/public/fact-changesopen live

Returns object · 7 recorded movements

Machine-readable diff feed for tracked fees, salary thresholds and processing-time facts. Each change carries a stable fact ID, old value, new value, effective date, current owning route and primary source.

Fields

FieldTypeDescription
lastModifiedstring (ISO date)Most recent changedOn date in the feed.
countnumberNumber of recorded movements.
changes[]array<object>Fact-change records, newest first.
changes[].changeIdstringStable ID combining factId and changedOn.
changes[].factIdstringStable fact identifier from the verification registry.
changes[].kindstring?salary-threshold, fee or processing-time.
changes[].labelstringHuman label for the changed fact.
changes[].jurisdictionstring?Destination or jurisdiction affected.
changes[].owningRoutestring?Current human page that publishes the fact.
changes[].fromstringPrevious observed value.
changes[].tostringNew observed value.
changes[].changedOnstring (ISO date)Effective date of the movement.
changes[].sourceNamestring?Name of the primary source.
changes[].sourceUrlstringOfficial primary source URL for the new value.
changes[].currentValuestring?Current value published in the registry.
changes[].currentAsOfstring (ISO date)?Effective/review date of the current value.
changes[].notestring?Context on the superseded value when available.

Example response

{
  "lastModified": "2026-03-01",
  "count": 7,
  "changes": [
    {
      "changeId": "salary:ie:critical-skills-employment-permit-general-floor@2026-03-01",
      "factId": "salary:ie:critical-skills-employment-permit-general-floor",
      "kind": "salary-threshold",
      "label": "Critical Skills Employment Permit - general floor salary floor",
      "jurisdiction": "Republic of Ireland",
      "owningRoute": "/salary-thresholds/ireland",
      "from": "38000 EUR (annual)",
      "to": "40904 EUR (annual)",
      "changedOn": "2026-03-01",
      "sourceName": "DETE - Critical Skills Employment Permit",
      "sourceUrl": "https://enterprise.gov.ie/en/what-we-do/workplace-and-skills/employment-permits/permit-types/critical-skills-employment-permit/",
      "currentValue": "40904 EUR (annual)",
      "currentAsOf": "2026-03-01"
    }
  ]
}
  • Use changeId for de-duplication. Use owningRoute for the human-readable current figure and sourceUrl for the issuing authority.

Monthly immigration figure changes

GET /api/public/monthly-figure-changesopen live

Returns object · 5 months with recorded movements

Derived month-by-month archive of recorded fee, salary-threshold and processing-time movements. It groups /api/public/fact-changes by changedOn month and adds same-month policy-update context; policy rows are not counted as figure movements.

Fields

FieldTypeDescription
versionstring (ISO date)Report version date.
namestringStable report name.
sourceDatasets[]array<string>Underlying public datasets: fact changes and policy updates.
methodology.periodstringGrouping period, currently calendar-month.
methodology.caveats[]array<string>Limits for reuse and interpretation.
summaryobjectCounts by month, kind and year.
latestMonthobject|nullMost recent month that has a recorded old-to-new figure movement.
months[]array<object>Monthly archive rows, newest first.
months[].changes[]array<object>Fact-change rows for the month, each with old value, new value, source and changelog anchor.
months[].policyContext[]array<object>Policy updates whose display date falls in the same month.
changes[]array<object>Flattened fact-change rows with detailPath added.

Example response

{
  "version": "2026-07-01",
  "name": "Visa Atlas monthly immigration figure changes",
  "sourceDatasets": ["/api/public/fact-changes", "/api/public/policy-updates"],
  "summary": {
    "changeCount": 7,
    "monthCount": 5,
    "latestChangeMonthLabel": "March 2026"
  },
  "months": [
    {
      "month": "2026-03",
      "label": "March 2026",
      "changeCount": 1,
      "changes": [
        {
          "changeId": "salary:ie:critical-skills-employment-permit-general-floor@2026-03-01",
          "from": "38000 EUR (annual)",
          "to": "40904 EUR (annual)",
          "detailPath": "/changelog#change-salary-ie-critical-skills-employment-permit-general-floor-2026-03-01"
        }
      ]
    }
  ]
}
  • Months with no recorded old-to-new figure movement are omitted from months[].
  • Use /api/public/fact-changes for the canonical movement records and this endpoint when you need calendar-month grouping.

Using the data

Attribution

Reuse is welcome under CC BY 4.0 — credit “Visa Atlas” and, where you can, link the page or endpoint you took a figure from. For the underlying fact, please also cite the original government authority (each record links it). See Use our data for citation examples.

Staying current

Figures move. Two RSS feeds let you track changes without polling: policy-updates.xml (dated rule changes) and changelog.xml (every fee/threshold/processing figure that moved, from → to). The Express Entry draws are reconciled against IRCC weekly. Figure-change history is also available as JSON at /api/public/fact-changes.

Errors

There is no error envelope: a valid endpoint returns its JSON with HTTP 200; an unknown path returns the standard 404 page. If a field you expect is missing, it is simply not applicable to that record (optional fields are omitted, not nulled).

Other machine-readable surfaces

  • /api/public — the self-describing catalog with schema.org Dataset metadata.
  • llms.txt and llms-full.txt — a plain-text index of the whole site.
  • AI agents and immigration data — the retrieval contract, citation rules, public entry points, and MCP tool contract in one page.
  • Research reports — original analysis computed from these same figures, with method and limitations stated.
  • The read-only MCP (Model Context Protocol) tool wrapper exposes the same verified data with its source and last-verified date on every result; use the static JSON endpoints as the public web source of truth.

This is not legal advice

We publish neutral, sourced information about immigration routes. Rules and thresholds change often — always verify details on the official government source linked on this page and consult a regulated immigration advisor before applying.