{"id":125129,"date":"2026-07-31T19:15:49","date_gmt":"2026-07-31T19:15:49","guid":{"rendered":"https:\/\/make.wordpress.org\/core\/?p=125129"},"modified":"2026-07-31T19:15:50","modified_gmt":"2026-07-31T19:15:50","slug":"json-schema-preparation-for-client-compatibility-in-wordpress-7-1","status":"publish","type":"post","link":"https:\/\/make.wordpress.org\/core\/2026\/07\/31\/json-schema-preparation-for-client-compatibility-in-wordpress-7-1\/","title":{"rendered":"JSON Schema preparation for client compatibility in WordPress 7.1"},"content":{"rendered":"<p class=\"wp-block-paragraph\">WordPress 7.1 introduces a shared <span tabindex='0' class='glossary-item-container'>JSON<span class='glossary-item-hidden-content'><span class='glossary-item-header'>JSON<\/span> <span class='glossary-item-description'>JSON, or JavaScript Object Notation, is a minimal, readable format for structuring data. It is used primarily to transmit data between a server and web application, as an alternative to XML.<\/span><\/span><\/span> Schema preparation layer for schemas exposed to REST clients, frontend applications, and AI tools.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">WordPress accepts several internal schema conventions that are useful during server-side validation but are not portable JSON Schema <code>draft-04<\/code>. Passing these schemas directly to external validators could cause validation errors or expose <span tabindex='0' class='glossary-item-container'>PHP<span class='glossary-item-hidden-content'><span class='glossary-item-header'>PHP<\/span> <span class='glossary-item-description'>The web scripting language in which WordPress is primarily architected. WordPress requires PHP 7.4 or higher<\/span><\/span><\/span> callbacks and other server-only implementation details.<\/p>\n\n\n<nav aria-label=\"Table of Contents\" class=\"wp-block-table-of-contents\"><ol><li><a class=\"wp-block-table-of-contents__entry\" href=\"#the-wp-prepare-json-schema-for-client-function\">The wp_prepare_json_schema_for_client() function<\/a><ol><li><a class=\"wp-block-table-of-contents__entry\" href=\"#compatibility-guidance\">Compatibility guidance<\/a><\/li><li><a class=\"wp-block-table-of-contents__entry\" href=\"#choosing-a-schema-profile\">Choosing a schema profile<\/a><\/li><\/ol><\/li><li><a class=\"wp-block-table-of-contents__entry\" href=\"#schema-transformations\">Schema transformations<\/a><ol><li><a class=\"wp-block-table-of-contents__entry\" href=\"#required-properties-use-draft-4-syntax\">Required properties use Draft 4 syntax<\/a><\/li><li><a class=\"wp-block-table-of-contents__entry\" href=\"#server-only-keywords-are-removed\">Server-only keywords are removed<\/a><\/li><li><a class=\"wp-block-table-of-contents__entry\" href=\"#empty-object-defaults-are-represented-as-objects\">Empty object defaults are represented as objects<\/a><\/li><\/ol><\/li><li><a class=\"wp-block-table-of-contents__entry\" href=\"#allowed-keywords-filter\">Allowed keywords filter<\/a><\/li><li><a class=\"wp-block-table-of-contents__entry\" href=\"#abilities-rest-api-changes\">Abilities REST API changes<\/a><\/li><li><a class=\"wp-block-table-of-contents__entry\" href=\"#ai-client-integration\">AI Client integration<\/a><ol><li><a class=\"wp-block-table-of-contents__entry\" href=\"#follow-up\">Follow-up<\/a><\/li><\/ol><\/li><li><a class=\"wp-block-table-of-contents__entry\" href=\"#related-ticket\">Related ticket<\/a><\/li><\/ol><\/nav>\n\n\n<h2 id=\"the-wp-prepare-json-schema-for-client-function\" class=\"wp-block-heading\">The <code>wp_prepare_json_schema_for_client()<\/code> function<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The new <code>wp_prepare_json_schema_for_client()<\/code> function converts a WordPress schema into a portable, client-facing representation before it is exposed to REST clients, frontend applications, AI tools, or other external consumers.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Most developers do not need to take action. <span tabindex='0' class='glossary-item-container'>Core<span class='glossary-item-hidden-content'><span class='glossary-item-header'>Core<\/span> <span class='glossary-item-description'>Core is the set of software required to run WordPress. The Core Development Team builds WordPress.<\/span><\/span><\/span> now applies this preparation automatically to:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Abilities <span tabindex='0' class='glossary-item-container'>API<span class='glossary-item-hidden-content'><span class='glossary-item-header'>API<\/span> <span class='glossary-item-description'>An API or Application Programming Interface is a software intermediary that allows programs to interact with each other and share data in limited, clearly defined ways.<\/span><\/span><\/span> schemas exposed through REST responses.<\/li>\n\n\n\n<li>Ability input schemas converted into AI Client function declarations.<\/li>\n<\/ul>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: php; title: ; notranslate\" title=\"\">\n$prepared_schema = wp_prepare_json_schema_for_client( $schema );\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">This keeps the schemas used by clients (REST clients, <span tabindex='0' class='glossary-item-container'>JavaScript<span class='glossary-item-hidden-content'><span class='glossary-item-header'>JavaScript<\/span> <span class='glossary-item-description'>JavaScript or JS is an object-oriented computer programming language commonly used to create interactive effects within web browsers. WordPress makes extensive use of JS for a better user experience. While PHP is executed on the server, JS executes within a user\u2019s browser.\r<a href=\"https:\/\/www.javascript.com\/\">https:\/\/www.javascript.com<\/a><\/span><\/span><\/span> applications, and AI tools) consistent. See <span tabindex='0' class='glossary-item-container'>ticket<span class='glossary-item-hidden-content'><span class='glossary-item-header'>ticket<\/span> <span class='glossary-item-description'>Created for both bug reports and feature development on the bug tracker.<\/span><\/span><\/span> <a href=\"https:\/\/core.trac.wordpress.org\/ticket\/64955\">#64955<\/a> and changeset <a href=\"https:\/\/core.trac.wordpress.org\/changeset\/62591\">[62591]<\/a>.<\/p>\n\n\n\n<h3 id=\"compatibility-guidance\" class=\"wp-block-heading\">Compatibility guidance<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">This change is primarily automatic. Existing ability registration and execution code does not need to call the new function.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Call <code>wp_prepare_json_schema_for_client()<\/code> directly when a <span tabindex='0' class='glossary-item-container'>plugin<span class='glossary-item-hidden-content'><span class='glossary-item-header'>Plugin<\/span> <span class='glossary-item-description'>A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory <a href=\"https:\/\/wordpress.org\/plugins\/\">https:\/\/wordpress.org\/plugins\/<\/a> or can be cost-based plugin from a third-party.<\/span><\/span><\/span> exposes a WordPress-style schema outside the server-side PHP validation boundary, for example through:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>a custom REST endpoint;<\/li>\n\n\n\n<li>a JavaScript configuration object;<\/li>\n\n\n\n<li>an MCP tool declaration;<\/li>\n\n\n\n<li>an AI function declaration; or<\/li>\n\n\n\n<li>another external schema consumer.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Do not replace the schema stored by an ability with the prepared version. Keep the canonical WordPress schema for server-side use and prepare a copy only when sending it to a client.<\/p>\n\n\n\n<h3 id=\"choosing-a-schema-profile\" class=\"wp-block-heading\">Choosing a schema profile<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">This new function accepts a schema and an optional schema profile:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: php; title: ; notranslate\" title=\"\">\n\/** \n * Prepares a JSON Schema for clients.\n * \n * @param array&lt;string, mixed&gt; $schema         The schema array.\n * @param string               $schema_profile Optional. Name of the schema\n *                                             profile whose keywords should be\n *                                             preserved. Default 'draft-04'.\n * @return array&lt;string, mixed&gt; The prepared schema.\n *\/\nwp_prepare_json_schema_for_client(\n\tarray $schema,\n\tstring $schema_profile = 'draft-04'\n): array\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">WordPress provides two schema profiles out of the box:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>draft-04<\/code> <strong>is the default<\/strong>. Use it when publishing a standalone schema to general-purpose clients, including Ability metadata, frontend validators, MCP integrations, and AI tooling. It preserves the broader <a href=\"https:\/\/json-schema.org\/draft-04\/draft-zyp-json-schema-04\">JSON Schema Draft 4<\/a> vocabulary, including composition and reference keywords such as <code>$ref<\/code>, <code>definitions<\/code>, <code>allOf<\/code>, <code>not<\/code>, <code>dependencies<\/code>, and <code>additionalItems<\/code>.<\/li>\n\n\n\n<li><code>rest-api<\/code> uses the narrower keyword set supported by WordPress <span tabindex='0' class='glossary-item-container'>REST API<span class='glossary-item-hidden-content'><span class='glossary-item-header'>REST API<\/span> <span class='glossary-item-description'>The REST API is an acronym for the RESTful Application Program Interface (API) that uses HTTP requests to GET, PUT, POST and DELETE data. It is how the front end of an application (think \u201cphone app\u201d or \u201cwebsite\u201d) can communicate with the data store (think \u201cdatabase\u201d or \u201cfile system\u201d)\r<a href=\"https:\/\/developer.wordpress.org\/rest-api\/\">https:\/\/developer.wordpress.org\/rest-api\/<\/a><\/span><\/span><\/span> route schemas. Use it when preparing a schema that must follow the same conventions as a REST route\u2019s argument or response schema.<\/li>\n<\/ul>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: php; title: ; notranslate\" title=\"\">\n\/\/ General client-facing or Ability schema.\n$prepared_schema = wp_prepare_json_schema_for_client( $schema );\n\n\/\/ Schema intended to match WordPress REST API conventions.\n$prepared_rest_schema = wp_prepare_json_schema_for_client(\n\t$schema,\n\t'rest-api'\n);\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Both profiles produce JSON Schema Draft 4 output. The difference is the set of keywords retained in the prepared schema.<\/p>\n\n\n\n<details class=\"wp-block-details is-layout-flow wp-block-details-is-layout-flow\"><summary>What is JSON Schema Draft 4?<\/summary>\n<p class=\"wp-block-paragraph\">\u201cDraft 4\u201d refers to the fourth published draft of the JSON Schema specification, which defines a JSON-based contract for describing and validating JSON data. See the <a href=\"https:\/\/json-schema.org\/draft-04\/draft-zyp-json-schema-04\">JSON Schema Draft 4 core specification<\/a> for its terminology and behaviour.<\/p>\n<\/details>\n\n\n\n<h2 id=\"schema-transformations\" class=\"wp-block-heading\">Schema transformations<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Preparation is recursive and applies to nested object properties, array items, composition keywords, definitions, dependencies, and other subschemas.<\/p>\n\n\n\n<h3 id=\"required-properties-use-draft-4-syntax\" class=\"wp-block-heading\">Required properties use Draft 4 syntax<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">WordPress schemas may mark individual properties as required:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: php; title: ; notranslate\" title=\"\">\n'properties' =&gt; array(\n\t'title' =&gt; array(\n\t\t'type'     =&gt; 'string',\n\t\t'required' =&gt; true,\n\t),\n)\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">The prepared schema moves those property names into the containing object\u2019s Draft 4 <code>required<\/code> array:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: php; title: ; notranslate\" title=\"\">\n'required' =&gt; array( 'title' ),\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">The property-level boolean is then removed.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If the object already has a valid <code>required<\/code> array, that array takes precedence over property-level boolean values. A property-level <code>required =&gt; false<\/code> is removed without creating an empty <code>required<\/code> array.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A boolean <code>required<\/code> value on a scalar schema is also removed because it has no Draft 4 equivalent.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This preparation only affects schemas sent to clients. It does not change the server-side behaviour of <code>rest_validate_value_from_schema()<\/code> or <code>WP_Ability::validate_input()<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Example of transforming schema:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: php; title: ; notranslate\" title=\"\">\n$schema = array(\n\t'type'       =&gt; 'object',\n\t'properties' =&gt; array(\n\t\t'title'   =&gt; array(\n\t\t\t'type'              =&gt; 'string',\n\t\t\t'required'          =&gt; true,\n\t\t\t'sanitize_callback' =&gt; 'sanitize_text_field',\n\t\t),\n\t\t'content' =&gt; array(\n\t\t\t'type'              =&gt; 'string',\n\t\t\t'validate_callback' =&gt; 'is_string',\n\t\t),\n\t),\n);\n\n$prepared_schema = wp_prepare_json_schema_for_client( $schema );\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">The prepared schema is equivalent to:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: php; title: ; notranslate\" title=\"\">\narray(\n\t'type'       =&gt; 'object',\n\t'required'   =&gt; array( 'title' ),\n\t'properties' =&gt; array(\n\t\t'title'   =&gt; array(\n\t\t\t'type' =&gt; 'string',\n\t\t),\n\t\t'content' =&gt; array(\n\t\t\t'type' =&gt; 'string',\n\t\t),\n\t),\n);\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">The original <code>$schema<\/code> is not modified.<\/p>\n\n\n\n<h3 id=\"server-only-keywords-are-removed\" class=\"wp-block-heading\">Server-only keywords are removed<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">PHP callbacks and other WordPress-specific keywords cannot be represented meaningfully in JSON. The preparation process removes unsupported keywords, including:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>sanitize_callback<\/code><\/li>\n\n\n\n<li><code>validate_callback<\/code><\/li>\n\n\n\n<li><code>arg_options<\/code><\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">These keywords are removed recursively, including when they appear inside:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>properties<\/code><\/li>\n\n\n\n<li><code>patternProperties<\/code><\/li>\n\n\n\n<li><code>definitions<\/code><\/li>\n\n\n\n<li><code>dependencies<\/code><\/li>\n\n\n\n<li><code>items<\/code><\/li>\n\n\n\n<li><code>additionalItems<\/code><\/li>\n\n\n\n<li><code>additionalProperties<\/code><\/li>\n\n\n\n<li><code>anyOf<\/code><\/li>\n\n\n\n<li><code>oneOf<\/code><\/li>\n\n\n\n<li><code>allOf<\/code><\/li>\n\n\n\n<li><code>not<\/code><\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">The callbacks remain available in the original server-side schema. They are removed only from its client-facing representation.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ability authors should also note that <code>validate_callback<\/code> and <code>sanitize_callback<\/code> are not executed by the Abilities API\u2019s runtime validation. Custom ability validation should use the <code>wp_ability_validate_input<\/code> and <code>wp_ability_validate_output<\/code> <a href=\"https:\/\/make.wordpress.org\/core\/2026\/07\/31\/abilities-api-improvements-in-wordpress-7-1\/#custom-input-and-output-validation\">filters introduced in WordPress 7.1<\/a>.<\/p>\n\n\n\n<h3 id=\"empty-object-defaults-are-represented-as-objects\" class=\"wp-block-heading\">Empty object defaults are represented as objects<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">In PHP, an empty array serializes to <code>[]<\/code>, even when its schema declares an object:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: php; title: ; notranslate\" title=\"\">\narray(\n\t'type'    =&gt; 'object',\n\t'default' =&gt; array(),\n)\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">For client-facing schemas, the empty default is prepared so that JSON serialization produces an object:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\n{\n\t\"type\": \"object\",\n\t\"default\": {}\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">This prevents client validators from rejecting the default because its serialized type does not match the declared <code>object<\/code> type.<\/p>\n\n\n\n<h2 id=\"allowed-keywords-filter\" class=\"wp-block-heading\">Allowed keywords <span tabindex='0' class='glossary-item-container'>filter<span class='glossary-item-hidden-content'><span class='glossary-item-header'>Filter<\/span> <span class='glossary-item-description'>Filters are one of the two types of Hooks <a href=\"https:\/\/codex.wordpress.org\/Plugin_API\/Hooks\">https:\/\/codex.wordpress.org\/Plugin_API\/Hooks<\/a>. They provide a way for functions to modify data of other functions. They are the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output.<\/span><\/span><\/span><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><code>wp_prepare_json_schema_for_client()<\/code> uses <code>wp_get_json_schema_allowed_keywords()<\/code> to decide which keywords to preserve.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The broader <code>draft-04<\/code> profile can preserve composition and documentation keywords such as:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>$ref<\/code><\/li>\n\n\n\n<li><code>definitions<\/code><\/li>\n\n\n\n<li><code>allOf<\/code><\/li>\n\n\n\n<li><code>not<\/code><\/li>\n\n\n\n<li><code>dependencies<\/code><\/li>\n\n\n\n<li><code>additionalItems<\/code><\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Preserving a keyword means that it may be included in the client-facing schema. It does not mean that WordPress validates or sanitizes values against that keyword on the server.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The allowed keyword list is filterable:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: php; title: ; notranslate\" title=\"\">\nadd_filter(\n\t'wp_json_schema_allowed_keywords',\n\tfunction ( $keywords, $schema_profile ) {\n\t\tif ( 'draft-04' === $schema_profile ) {\n\t\t\t$keywords[] = 'x-example-keyword';\n\t\t}\n\n\t\treturn $keywords;\n\t},\n\t10,\n\t2\n);\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Custom keywords should only be exposed when the receiving clients are known to understand them.<\/p>\n\n\n\n<h2 id=\"abilities-rest-api-changes\" class=\"wp-block-heading\">Abilities REST API changes<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">WordPress now prepares an ability\u2019s input and output schemas before including them in Abilities REST API responses.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For abilities registered with REST visibility, consumers of endpoints under:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n\/wp-json\/wp-abilities\/v1\/abilities\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">receive portable schemas instead of the original WordPress-internal schema arrays.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This is an output-boundary transformation:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>WP_Ability::get_input_schema()<\/code> and <code>WP_Ability::get_output_schema()<\/code> continue to return the original schemas to server-side PHP.<\/li>\n\n\n\n<li>REST responses contain prepared versions.<\/li>\n\n\n\n<li>Ability execution and server-side validation remain unchanged.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Developers comparing a schema retrieved directly from a <code>WP_Ability<\/code> object with one returned through REST may therefore see intentional differences.<\/p>\n\n\n\n<h2 id=\"ai-client-integration\" class=\"wp-block-heading\">AI Client integration<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">When the WordPress AI Client converts abilities into function declarations, it now prepares each ability\u2019s input schema first:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: php; title: ; notranslate\" title=\"\">\n$input_schema = wp_prepare_json_schema_for_client(\n\t$ability-&gt;get_input_schema()\n);\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">This prevents WordPress-only schema keywords and nonportable <code>required<\/code> conventions from being passed directly into AI function declarations.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The helper prepares a portable Draft 4 schema; it is not a provider-specific compiler. Individual AI providers may support a smaller schema vocabulary or impose additional requirements. Provider-specific adaptation may therefore still occur elsewhere in the integration.<\/p>\n\n\n\n<h3 id=\"follow-up\" class=\"wp-block-heading\">Follow-up<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Provider-specific adaptation is tracked in\u00a0<a href=\"https:\/\/github.com\/WordPress\/php-ai-client\/issues\/256\">WordPress\/php-ai-client#256<\/a>: each provider should be able to override the input schema for its own API requirements, which differ across providers and evolve over time.<\/p>\n\n\n\n<h2 id=\"related-ticket\" class=\"wp-block-heading\">Related ticket<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/core.trac.wordpress.org\/ticket\/64955\">#64955<\/a> \u2014 Add schema compiler for AI tool calling compatibility<\/li>\n\n\n\n<li>Changeset <a href=\"https:\/\/core.trac.wordpress.org\/changeset\/62591\">[62591]<\/a> \u2014 Abilities API:\u00a0Reuse JSON Schema client preparation<\/li>\n\n\n\n<li>Changeset <a href=\"https:\/\/core.trac.wordpress.org\/changeset\/62549\">[62549]<\/a> \u2014 REST API: Add a shared helper for JSON Schema allowed keywords.<\/li>\n\n\n\n<li>Changeset <a href=\"https:\/\/core.trac.wordpress.org\/changeset\/62449\">[62449]<\/a> \u2014 Abilities API: Normalize\u00a0<code>required<\/code>\u00a0schema shape for REST responses\u00a0<\/li>\n<\/ul>\n\n\n\n<p class=\"has-text-align-right wp-block-paragraph\"><em>Props to <a href=\"https:\/\/profiles.wordpress.org\/jorbin\/\" class=\"mention\"><span class=\"mentions-prefix\">@<\/span>jorbin<\/a> for peer review and suggested improvements.<\/em><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n<p class=\"o2-appended-tags\"><a href=\"https:\/\/make.wordpress.org\/core\/tag\/abilities-api\/\" class=\"tag\"><span class=\"tag-prefix\">#<\/span>abilities-api<\/a>, <a href=\"https:\/\/make.wordpress.org\/core\/tag\/7-1\/\" class=\"tag\"><span class=\"tag-prefix\">#<\/span>7-1<\/a>, <a href=\"https:\/\/make.wordpress.org\/core\/tag\/dev-notes\/\" class=\"tag\"><span class=\"tag-prefix\">#<\/span>dev-notes<\/a>, <a href=\"https:\/\/make.wordpress.org\/core\/tag\/dev-notes-7-1\/\" class=\"tag\"><span class=\"tag-prefix\">#<\/span>dev-notes-7-1<\/a>, <a href=\"https:\/\/make.wordpress.org\/core\/tag\/rest-api\/\" class=\"tag\"><span class=\"tag-prefix\">#<\/span>rest-api<\/a><\/p><nav class='o2-post-footer-actions'><ul class='o2-post-footer-action-row'><li class='o2-post-footer-action'><a href=\"https:\/\/login.wordpress.org\/?redirect_to=https%3A%2F%2Fmake.wordpress.org%2Fcore%2F2026%2F07%2F31%2Fjson-schema-preparation-for-client-compatibility-in-wordpress-7-1%2F%23respond&#038;locale=en_US\" title=\"Login to Reply\"  class=\"genericon  genericon-reply\"  data-action=\"login-to-reply\"  data-actionstate=\"default\" >Login to Reply<\/a><\/li><\/ul><div class='o2-post-footer-action-likes'><\/div><ul class='o2-post-footer-action-row'><\/ul><\/nav>","protected":false},"excerpt":{"rendered":"<p>WordPress 7.1 introduces a shared JSONJSON JSON, or JavaScript Object Notation, is a minimal, readable format for structuring data. It is used primarily to transmit data between a server and web application, as an alternative to XML. Schema preparation layer for schemas exposed to REST clients, frontend applications, and AI tools. WordPress accepts several internal [&hellip;]<\/p>\n","protected":false},"author":7923389,"featured_media":0,"comment_status":"open","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"advanced_seo_description":"","jetpack_seo_html_title":"","jetpack_seo_noindex":false,"jetpack_seo_schema_type":"","_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_post_was_ever_published":false},"categories":[1175],"tags":[5778,5885,1443,5894,1526],"class_list":["post-125129","post","type-post","status-publish","format-standard","hentry","category-general","tag-abilities-api","tag-7-1","tag-dev-notes","tag-dev-notes-7-1","tag-rest-api","mentions-jorbin","author-milana_cap"],"revision_note":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p2AvED-wyd","jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/make.wordpress.org\/core\/wp-json\/wp\/v2\/posts\/125129","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/make.wordpress.org\/core\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/make.wordpress.org\/core\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/make.wordpress.org\/core\/wp-json\/wp\/v2\/users\/7923389"}],"replies":[{"embeddable":true,"href":"https:\/\/make.wordpress.org\/core\/wp-json\/wp\/v2\/comments?post=125129"}],"version-history":[{"count":27,"href":"https:\/\/make.wordpress.org\/core\/wp-json\/wp\/v2\/posts\/125129\/revisions"}],"predecessor-version":[{"id":125232,"href":"https:\/\/make.wordpress.org\/core\/wp-json\/wp\/v2\/posts\/125129\/revisions\/125232"}],"wp:attachment":[{"href":"https:\/\/make.wordpress.org\/core\/wp-json\/wp\/v2\/media?parent=125129"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/make.wordpress.org\/core\/wp-json\/wp\/v2\/categories?post=125129"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/make.wordpress.org\/core\/wp-json\/wp\/v2\/tags?post=125129"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}