Schema Validator API: check the markup, or write it for them
Google retired the API behind its own structured data testing tool and the public validator is rate limited, so there is nowhere to call this from a build pipeline. This endpoint reads the schema.org markup on a page, reports every type it declares and the required fields that are missing, and can write correct markup from a real business record.
POST/v1/schema/validate
{
"data": {
"blocks": 2,
"types": [
"Dentist",
"FAQPage",
"GeoCoordinates",
"PostalAddress",
"Question"
],
"checked": true,
"checked_types": [
"FAQPage",
"LocalBusiness",
"PostalAddress",
"Question"
],
"unchecked_types": [
"GeoCoordinates"
],
"items": [
{
"type": "Dentist",
"checked": true,
"checked_against": "LocalBusiness",
"valid": true,
"missing_required": [],
"missing_recommended": [
"image",
"priceRange"
]
},
{
"type": "GeoCoordinates",
"checked": false,
"checked_against": null,
"valid": null,
"missing_required": [],
"missing_recommended": []
}
],
"errors": [],
"valid": true
},
"meta": {
"credits_used": 1,
"source": "websites"
}
}
What you get
Every field in the response.
| Field | Meaning |
|---|---|
items[] | Every typed object on the page, with the ruleset it was judged against |
checked, valid | Whether we hold rules for that type, and the verdict. A type we have no rules for comes back checked: false and valid: null, never invalid |
missing_required, missing_recommended | What is absent, named field by field |
types, checked_types, unchecked_types | What the page declares, what it was judged against, and what was skipped |
errors, valid | Broken JSON, a missing @context, every missing required field, and the one-line verdict. valid is null when nothing could be judged |
script, validation (on generate) | The JSON-LD wrapped in a script tag ready to paste, and the validator run over that exact document |
How it works
What happens between your request and the response.
Reads what is there
Every JSON-LD block on the page, including @graph documents and nested objects, parsed the way a search engine would.
Judges by the documented rules
Required and recommended fields for the types rich results are documented for. A Dentist is judged as a LocalBusiness, a Corporation as an Organization, a cafe as a food business.
Says when it did not judge
A type we hold no rules for is reported as unchecked rather than invalid, and unchecked_types names every one. A page where nothing could be judged never reads as a pass.
Writes from real data
Pass a place_id and the generator fills LocalBusiness markup with the real address, coordinates, phone, rating, opening hours and social profiles. No other vendor has that record to hand.
Checks its own output
The generated markup is run back through the validator and returned in the validation block, so you never paste something that fails.
Pricing
One credit system for every endpoint.
Checking a URL costs one credit; checking HTML or a JSON-LD document you already hold is free. Generating markup costs one credit.
Run it on Apify.
For bigger runs, or without writing any code, the same engine runs on Apify as the listing below. Apify bills per result, so there is no subscription and nothing to pay us, and Apify's own free plan includes $5 of usage a month with no card.
Questions
Things people ask about the Schema Validator API.
Will this tell me if I get a rich result?
It tells you whether the markup meets the documented requirements, which is the part that can be checked. Whether a search engine grants a rich result is its decision and no API can promise it.
Can I use it in continuous integration?
That is what it is for. Send the built HTML rather than a URL and the check is free, so a build can fail on missing required fields without spending credits.
Can I send the JSON-LD as an object rather than a string?
Yes. The jsonld field accepts a JSON-encoded string, a single object, or an array of objects, and all three are read the same way. Sending the object straight out of your code is usually simplest.
What does valid: null mean?
It means nothing on the page matched a ruleset we hold, so we formed no opinion. That is deliberate: a page we could not judge should never report a clean pass. The unchecked_types list names the types that were skipped.
What makes the generator different from a template?
It is filled from a live business record: the real address in parts, coordinates, phone in international format, rating with review count, and seven days of opening hours.