WPGraphQL is a free, open-source WordPress plugin that provides an extendable GraphQL schema and API for any WordPress site.

Below are some links to help you get started with WPGraphQL

Build rich JavaScript applications with WordPress and GraphQL

WPGraphQL allows you to separate your CMS from your presentation layer. Content creators can use the CMS they know, while developers can use the frameworks and tools they love.

WPGraphQL works great with:

Query what you need. Get exactly that.

With GraphQL, the client makes declarative queries, asking for the exact data needed, and in exactly what was asked for is given in response, nothing more. This allows the client have control over their application, and allows the GraphQL server to perform more efficiently by only fetching the resources requested.

Fetch many resources in a single request.

GraphQL queries allow access to multiple root resources, and also smoothly follow references between connected resources. While typical a REST API would require round-trip requests to many endpoints, GraphQL APIs can get all the data your app needs in a single request. Apps using GraphQL can be quick even on slow mobile network connections.

Powerful Debugging Tools

WPGraphQL ships with GraphiQL in your WordPress dashboard, allowing you to browse your site’s GraphQL Schema and test Queries and Mutations.


It is recommended that anytime you want to update WPGraphQL that you get familiar with what’s changed in the release.

WPGraphQL publishes release notes on Github.

WPGraphQL has been following Semver practices for a few years. We will continue to follow Semver and let version numbers communicate meaning. The summary of Semver versioning is as follows:

  • MAJOR version when you make incompatible API changes,
  • MINOR version when you add functionality in a backwards compatible manner, and
  • PATCH version when you make backwards compatible bug fixes.

You can read more about the details of Semver at semver.org

Privacy Policy

WPGraphQL uses Appsero SDK to collect some telemetry data upon user’s confirmation. This helps us to troubleshoot problems faster & make product improvements.

Appsero SDK does not gather any data by default. The SDK only starts gathering basic telemetry data when a user allows it via the admin notice. We collect the data to ensure a great user experience for all our users.

Integrating Appsero SDK DOES NOT IMMEDIATELY start gathering data, without confirmation from users in any case.

Learn more about how Appsero collects and uses this data.



Can I use WPGraphQL with xx JavaScript Framework?

WPGraphQL turns your WordPress site into a GraphQL API. Any client that can make http requests to the GraphQL endpoint can be used to interact with WPGraphQL.

Where do I get WPGraphQL Swag?

WPGraphQL Swag is available on the Gatsby Swag store.

What’s the relationship between Gatsby, WP Engine, and WPGraphQL?

WP Engine is the employer of Jason Bahl, the creator and maintainer of WPGraphQL. He was previously employed by Gatsby.

You can read more about this here.

Gatsby and WP Engine both believe that a strong GraphQL API for WordPress is a benefit for the web. Neither Gatsby or WP Engine are required to be used with WPGraphQL, however it’s important to acknowledge and understand what’s possible because of their investments into WPGraphQL and the future of headless WordPress!


May 29, 2023 1 reply
I operate a large blog that uses WordPress as a headless CMS with a Next.JS frontend, which is largely enabled by this plugin. Let me just say first that creating an entire alternative third-party data API is an ambitious undertaking and I appreciate all the work the authors have put into it. But as a developer I have to throw out a word of caution that this plugin often has major bugs that can have critical impact on your production website. For example after a recent minor update we discovered a bug where any URL with a special character in it started returning a 404, causing several of our pages to suddenly become unavailable to users and delisted from Google, and this went on for many months before we realized it. There have been many similar instances. My general approach is to lean more on WordPress’s REST API over time which is more reliable since it’s maintained by the WordPress team, and only use WPGraphQL when it’s necessary. Also recommend turning off auto-updates and test your website extremely thoroughly after any upgrade.
August 26, 2022
One of the best plugins for WordPress. It’s right up there with ACF!
May 31, 2022
Great plugin, everyone should use it. The IDE is a valuable plus, and it can be used to learn GraphQL from scratch. From the developer’s point of view, the plugin is super easy to extend, thanks to the great documentation. Don’t forget to check the official YouTube channel. If you need extra support for custom post types and metas, I just released v1.0.70 of my plugin ACPT with full support to WPGraphQL. Thank you so much John!
April 25, 2022
Great tool for getting data from your WP into your SPA. I had some trouble with a conflicting plugin (Post Types Order) that caused unexpted results when paginating my posts but the support provided by both Jason Bahl and David Levine was absolutely top notch and I managed to resolve the issue within hours.
Read all 47 reviews

Contributors & Developers

“WPGraphQL” is open source software. The following people have contributed to this plugin.


Translate “WPGraphQL” into your language.

Interested in development?

Browse the code, check out the SVN repository, or subscribe to the development log by RSS.



New Features

  • #3143: feat: Enhance tab state management with query arguments and localStorage fallback

Chores / Bugfixes

  • #3139: fix: $settings_fields param on “graphql_get_setting_section_field_value” filter not passing the correct type
  • #3137: fix: WPGraphQL Settings page fails to load when “graphiql_enabled” setting is “off”
  • #3133: build: clean up dist
  • #3146: test: add e2e test coverage for tabs in the settings page


New Features

  • #3125: refactor: improve query handling in AbstractConnectionResolver
    • new: graphql_connection_pre_get_query filter
    • new: AbstractConnectionResolver::is_valid_query_class()
    • new: AbstractConnectionResolver::get_query()
    • new: AbstractConnectionResolver::get_query_class()
    • new: AsbtractConnectionResolver::query_class()
    • new: AbstractConnectionResolver::$query_class
  • #3124: refactor: split AbstractConnectionResolver::get_args() and ::get_query_args() into ::prepare_*() methods
  • #3123: refactor: split AbstractConnectionResolver::get_ids() into ::prepare_ids()
  • #3121: refactor: split AbstractConnectionResolver::get_nodes() and get_edges() into prepare_*() methods
  • #3120: refactor: wrap AbstractConnectionResolver::is_valid_model() in ::get_is_valid_model()

Chores / Bugfixes

  • #3125: refactor: improve query handling in AbstractConnectionResolver
    • Implement PHPStan Generic Type
    • Update generic Exceptions to InvariantViolation
  • #3127: chore: update references to the WPGraphQL Slack Community to point to the new WPGraphQL Discord community instead.
  • #3122: chore: relocate AbstractConnectionResolver::is_valid_offset() with other abstract methods.


New Features

  • #3104: feat: add AbsractConnectionResolver::pre_should_execute(). Thanks @justlevine!

Chores / Bugfixes
#3104: refactor: AbstractConnectionResolver::should_execute() Thanks @justlevine!
#3112: fix: fixes a regression from v1.24.0 relating to field arguments defined on Interfaces not being properly merged onto Object Types that implement the interface. Thanks @kidunot89!
#3114: fix: node IDs not showing in the Query Analyzer / X-GraphQL-Keys when using DataLoader->load_many()
#3116: chore: Update WPGraphQLTestCase to v3. Thanks @kidunot89!


New Features

  • #3084: perf: refactor PluginConnectionResolver to only fetch plugins once. Thanks @justlevine!
  • #3088: refactor: improve loader handling in AbstractConnectionResolver. Thanks @justlevine!
  • #3087: feat: improve query amount handling in AbstractConnectionResolver. Thanks @justlevine!
  • #3086: refactor: add AbstractConnectionResolver::get_unfiltered_args() public getter. Thanks @justlevine!
  • #3085: refactor: add AbstractConnectionResolver::prepare_page_info()and only instantiate once. Thanks @justlevine!
  • #3083: refactor: deprecate camelCase methods in AbstractConnectionResolver for snake_case equivalents. Thanks @justlevine!

Chores / Bugfixes

  • #3095: chore: lint for superfluous whitespace. Thanks @justlevine!
  • #3100: fix: recursion issues with interfaces
  • #3082: chore: prepare ConnectionResolver classes for v2 backport


New Features

  • #3073: feat: expose hasPassword and password fields on Post objects. Thanks @justlevine!
  • #3091: feat: introduce actions and filters for GraphQL Admin Notices

Chores / Bugfixes

  • #3079: fix: GraphiQL IDE test failures
  • #3084: perf: refactor PluginConnectionResolver to only fetch plugins once. Thanks @justlevine!
  • #3092: ci: test against wp 6.5
  • #3093: ci: Update actions in GitHub workflows and cleanup. Thanks @justlevine!
  • #3093: chore: update Composer dev-deps and lint. Thanks @justlevine!


Chores / Bugfixes

  • #3067: fix: respect show avatar setting
  • #3063: fix: fixes a bug in cursor stability filters that could lead to empty order
  • #3070: test(3063): Adds test for #3063


New Features

  • #3044: feat: add graphql_pre_resolve_menu_item_connected_node filter
  • #3039: feat: add UniformResourceIdentifiable interface to Comment type
  • #3020: feat: introduce graphql_query_analyzer_get_headers filter

Chores / Bugfixes

  • #3062: ci: pin wp-browser to “<3.5” to allow automated tests to run properly
  • #3057: fix: admin_enqueue_scripts callback should expect a possible null value passed to it
  • #3048: fix: isPostsPage on content type
  • #3043: fix: return empty when filtering menuItems by a location with no assigned items
  • #3045: fix: UsersConnectionSearchColumnEnum values should be prefixed with user_


New Features

  • #3035: feat: provide better error when field references a type that does not exist
  • #3027: feat: Add register_graphql_admin_notice API and intial use to inform users of the new WPGraphQL for ACF plugin

Chores / Bugfixes

  • #3038: chore(deps-dev): bump the composer group across 1 directories with 1 update. Thanks @dependabot!
  • #3033: fix: php deprecation error for dynamic properties on AppContext class
  • #3031: fix(graphiql): Allow GraphiQL to run even if a valid schema cannot be returned. Thanks @linucks!


New Features

  • #3013: feat: output GRAPHQL_DEBUG message if requested amount is larger than connection limit. Thanks @justlevine!
  • #3008: perf: Expose graphql_should_analyze_queries as setting. Thanks @justlevine!

Chores / Bugfixes

  • #3022: chore: add @justlevine to list of contributors! 🙌 🥳
  • #3011: chore: update composer dev-dependencies and use php-compatibility:develop branch to 8.0+ lints. Thanks @justlevine!
  • #3010: chore: implement stricter PHPDoc types. Thanks @justlevine!
  • #3009: chore: implement stricter PHPStan config and clean up unnecessary type-guards. Thanks @justlevine!
  • #3007: fix: call html_entity_decode() with explicit flags and decode single-quotes. Thanks @justlevine!
  • #3006: fix: replace deprecated AbstractConnectionResolver::setQueryArg() call with ::set_query_arg(). Thanks @justlevine!
  • #3004: docs: Update using-data-from-custom-database-tables.md
  • #2998: docs: Update build-your-first-wpgraphql-extension.md. Thanks @Jacob-Daniel!
  • #2997: docs: update wpgraphql-concepts.md. Thanks @Jacob-Daniel!
  • #2996: fix: Field id duplicates uri field description. Thanks @marcinkrzeminski!


New Features

  • #2988: feat: add missing extra fields to EnqueuedAsset, EnqueuedScript and EnqueuedStylesheet

Chores / Bugfixes

  • #2989: fix: make User.url public
  • #2990: chore: autolint tests with phpcbf
  • #2992: fix: add polyfills for str_starts_with() and str_ends_with() to prevent fatal errors in PHP < 8.0


Chores / Bugfixes

  • ci: update tests to run against WordPress 6.4.1. Update Docker Deploy to include WP 6.4.1. Update README, plugin file’s “tested up to” to reflect.


Chores / Bugfixes

  • #2984: ci: update tests to run against WordPress 6.4. Update README, plugin file’s “tested up to” to reflect.


New Features

  • #2937: fix: Support asPreview by URI/SLUG Id Type (this is technically a bugfix, but introduces new functionality)

Chores / Bugfixes

  • #2972: chore(deps): bump @babel/traverse from 7.17.3 to 7.23.2
  • #2930: fix: unstable term cursor identical names
  • #2976: chore: restore commenting sniffs to PHPCS ruleset
  • #2973: chore: update composer deps to latest
  • #2975: chore: lint and remove useless variables [phpcs]
  • #2977: chore: sort use statements alphabetically with SlevomatCodingStandard.Namespaces.AlphabeticallySortedUses (autofix)
  • #2978: chore: implement stricter type hinting with SlevomatCodingStandard.TypeHints [phpcs]


New Features

  • #2940: feat: add graphql_format_name() access method
  • #2256: feat: add connectedTerms connection to Taxonomy Object

Chores / Bugfixes

  • #2808: fix: fallback to template filename if sanitized name is empty
  • #2968: fix: Add graphql_debug warning when using hasPublishedPosts: ATTACHMENT
  • #2968: fix: improve DX for updateComment mutation
  • #2962: fix: respect hasPublishedPosts where arg on unauthenticated users queries
  • #2967: fix: use all roles for UserRoleEnum instead of the filtered editible_roles
  • #2940: fix: Decode slug so it works with other languages
  • #2959: chore: remove @phpstan-ignore annotations
  • #2945: fix: rename fields registered by connections when using rename_graphql_field()
  • #2949: fix: correctly get default user role for settings selectbox
  • #2955: test: back-fill register_graphql_input|union_type() tests
  • #2953: fix: term uri, early return. (Follow up to #2341)
  • #2956: chore(deps-dev): bump postcss from 8.4.12 to 8.4.31
  • #2954: fix: regression to autoloader for bedrock sites. (Follow-up to #2935)
  • #2950: fix: rename typo in component name – AuthSwitchProvider
  • #2948: chore: fix spelling mistakes (non-logical)
  • #2944: fix: skip setting if no $setting[‘group’]
  • #2934: chore(deps-dev): bump composer/composer from 2.2.21 to 2.2.22
  • #2936: chore(deps): bump graphql from 16.5.0 to 16.8.1
  • #2341: fix: wrong term URI on sub-sites of multisite subdomain installs
  • #2935: fix: admin notice wasn’t displaying if composer dependencies were missing
  • #2933: chore: remove unused parameters from resolver callbacks
  • #2932: chore: cleanup PHPCS inline annotations
  • #2934: chore: use .php extension for stub files
  • #2924: chore: upgrade WPCS to v3.0
  • #2921: fix: zip artifact in GitHub not in sub folder


New Features

  • #2918: feat: Use graphql endpoint without scheme in url header.
  • #2882: feat: Config and Cursor Classes refactor


New Features

  • #2908: feat: Skip param added to Utils::map_input(). Thanks @kidunot89!

Chores / Bugfixes

  • #2907: ci: Use WP 6.3 image, not the beta one
  • #2902: chore: handle unused variables (phpcs). Thanks @justlevine!
  • #2901: chore: remove useless ternaries (phpcs). Thanks @justlevine!
  • #2898: chore: restore excluded PHPCS sniffs. Thanks @justlevine!
  • #2899: chore: Configure PHPCS blank line check and autofix. Thanks @justlevine!
  • #2900: chore: implement PHPCS sniffs from Slevomat Coding Standards. Thanks @justlevine!
  • #2897: fix: default excerptRendered to empty string. Thanks @izzygld!
  • #2890: fix: Use hostname for graphql cache header url for varnish
  • #2892: chore: GitHub template tweaks. Thanks @justlevine!
  • #2889: ci: update tests to test against WordPress 6.3, simplify the matrix
  • #2891: chore: bump graphql-php to 14.11.10 and update Composer dev-deps. Thanks @justlevine!


Chores / Bugfixes

  • #2874: fix: improve PostObjectCursor support for meta queries. Thanks @kidunot89!
  • #2880: fix: increase clarity of the description of “asPreview” argument


Chores / Bugfixes

  • #2865: fix: user roles should return empty if user doesn’t have roles. Thanks @j3ang!
  • #2870: fix: Type Loader returns null when “graphql_single_name” value has underscores [regression]
  • #2871: fix: update tests, follow-up to #2865


Chores / Bugfixes

  • #2855: perf: enforce static closures when possible (PHPCS). Thanks @justlevine!
  • #2857: fix: Prevent truncation of query name inside the GraphiQL Query composer explorer tab. Thanks @LarsEjaas!
  • #2856: chore: add missing translator comments. Thanks @justlevine!
  • #2862: chore(deps-dev): bump word-wrap from 1.2.3 to 1.2.4
  • #2861: fix: output list:$type keys for Root fields that return a list of nodes


Chores / Bugfixes

  • #2853: fix: internal server error when query max depth setting is left empty
  • #2851: fix: querying posts by slug or uri with non-ascii characters
  • #2849: ci: Indent WP 6.2 in workflow file. Fixes Docker deploys. Thanks @markkelnar!
  • #2846: chore(deps): bump tough-cookie from 4.0.0 to 4.1.3


Chores / Bugfixes

  • #2841: ci: support STEP_DEBUG in Code Quality workflow. Thanks @justlevine!
  • #2840: fix: update createMediaItem mutation to have better validation of input.
  • #2838: chore: update security.md


Chores / Bugfixes

  • #2834: fix: improve how the Query Analyzer tracks list types, only tracking lists from the RootType and not nested lists.
  • #2828: chore: update composer dev-deps to latest. Thanks @justlevine!
  • #2835: ci: update docker deploy workflow to use latest docker actions.
  • #2836: ci: update schema upload workflow to pin mariadb to 10.8.2


New Features

  • #2826: feat: pass connection config to connection field

Chores / Bugfixes

  • #2818: chore: update webonyx/graphql-php to v14.11.9. Thanks @justlevine!
  • #2813: fix: replace double negation with true. Thanks @cesarkohl!


Chores / Bugfixes

  • #2801: fix: conflict between custom post type and media slugs
  • #2799: fix: querying posts by slug fails when custom permalinks are set
  • #2794: chore(deps): bump guzzlehttp/psr7 from 1.9.0 to 1.9.1


Chores / Bugfixes

  • #2792: fix: uri field is null when querying the page for posts uri


New Features

  • #2763: feat: add shouldShowAdminToolbar field to the User type, resolving from the “show_admin_bar_front” meta value. Thanks @blakewilson!

Chores / Bugfixes

  • #2758: fix: Allow post types and taxonomies to be registered without “graphql_plural_name”.
  • #2762: Bump webpack version.
  • #2770: fix: wrong order in term/post ancestor queries. Thanks @creative-andrew!
  • #2775: fix: properly resolve when querying terms filtered by multiple taxonomies. Thanks @thecodeassassin!
  • #2776: chore: remove internal usage of deprecated functions. Thanks @justlevine!
  • #2777: chore: update composer dev-deps (not PHPStan). Thanks @justlevine!
  • #2778: fix: Update PHPStan and fix smells. Thanks @justlevine!
  • #2779: ci: test against WordPress 6.2. Thanks @justlevine!
  • #2781: chore: call _doing_it_wrong() when using deprecated PostObjectUnion and TermObjectUnion. Thanks @justlevine!
  • #2782: ci: fix deprecation warnings in Github workflows. Thanks @justlevine!
  • #2786: fix: early return for HTTP OPTIONS requests.


New Features

  • #2745: feat: Allow fields, connections and mutations to optionally be registered with undersores in the field name.
  • #2651: feat: Add deregister_graphql_mutation() and graphql_excluded_mutations filter. Thanks @justlevine!
  • #2652: feat: Add deregister_graphql_connection and graphql_excluded_connections filter. Thanks @justlevine!
  • #2680: feat: Refactor the NodeResolver::resolve_uri to use WP_Query. Thanks @justlevine!
  • #2643: feat: Add post_lock check on edit/delete mutation. Thanks @markkelnar!
  • #2649: feat: Add pageInfo field to the Connection type.

Chores / Bugfixes

  • #2752: fix: handle 404s in NodeResolver.php. Thanks @justlevine!
  • #2735: fix: Explicitly check for DEBUG enabled value for tests. Thanks @markkelnar!
  • #2659: test: Add tests for nodeByUri. Thanks @justlevine!
  • #2724: test: Add test for graphql:Query key in headers. Thanks @markkelnar!
  • #2718: fix: deprecation notice. Thanks @decodekult!
  • #2705: chore: Use fully qualified classnames in PHPDoc annotations. Thanks @justlevine!
  • #2706: chore: update PHPStan and fix newly surfaced sniffs. Thanks @justlevine!
  • #2698: chore: bump simple-get from 3.15.1 to 3.16.0. Thanks @dependabot!
  • #2701: fix: navigation url. Thanks @jiwon-mun!
  • #2704: fix: missing apostrophe after escape. Thanks @i-mann!
  • #2709: chore: update http-cache-semantics. Thanks @dependabot!
  • #2707: ci: update and fix Lint PR workflow. Thanks @justlevine!
  • #2689: fix: prevent infinite recursion for interfaces that implement themselves as an interface.
  • #2691: fix: prevent non-node types from being output in the query analyzer lis-type
  • #2684: chore: remove deprecated use of WPGraphQL\Data\DataSource::resolve_user(). Thanks @renatonascalves
  • #2675: ci: keep the develop branch in sync with master.


Chores / Bugfixes

  • #2741: Change the plugin name from “WP GraphQL” to “WPGraphQL”. Thanks @josephfusco!
  • #2742: Update Stalebot rules. Thanks @justlevine!


Chores / Bugfixes

  • #2726: fix: invalid schema when custom post types and custom taxonomies are registered with underscores in the “graphql_single_name” / “graphql_plural_name”


Chores / Bugfixes

  • #2712: fix: query analyzer outputting unexpected list types


Chores / Bugfixes

  • (#2661): chore(deps): bump simple-git from 3.10.0 to 3.15.1
  • (#2665): chore(deps): bump decode-uri-component from 0.2.0 to 0.2.2
  • (#2668): test: Multiple domain tests. Thanks @markkelnar!
  • (#2669): ci: Use last working version of xdebug for php7. Thanks @markkelnar!
  • (#2671): fix: correct regressions to field formatting forcing snake_case and UcFirst fields to be lcfirst/camelCase
  • (#2672): chore: update lint-pr workflow


New Feature

  • (#2657): feat: pass unfiltered args through to filters in the ConnectionResolver classes. Thanks @kidunot89!
  • (#2655): feat: add includeDefaultInterfaces to connection config, allowing connections to be registered without the default Connection and Edge interfaces applied.. Thanks @justlevine!

Chores / Bugfixes

  • (#2656): chore: clean up NodeResolver::resolve_uri() logic. Thanks @justlevine!


Chores / Bugfixes

  • (#2647): fix: properly register the node field on ConnectionEdge interfaces
  • (#2645): fix: regression where fields of an object type were forced to be camelCase. This allows snake_case fields again.


Chores / Bugfixes

  • (#2631): simplify (DRY up) connection interface registration.


  • fix: update versions for WordPress.org deploys


Chores / Bugfixes

  • (#2627): fix: Fixes regression where Connection classes were moved to another namespace. This adds deprecated classes back to the old namespace to extend the new classes. Thanks @justlevine!


Chores / Bugfixes

  • (#2625): fix: Fixes a regression to v1.13.0 where mutations registered with an uppercase first letter weren’t properly being transformed to a lowercase first letter when the field is added to the Schema.


Possible Breaking Change for some users

The work to introduce the Connection and Edge (and other) Interfaces required the User.revisions and RootQuery.revisions connection to
change from resolving to the ContentRevisionUnion type and instead resolve to the ContentNode type.

We believe that it’s highly likely that most users will not be impacted by this change.

Any queries that directly reference the following types:

  • ...on UserToContentRevisionUnionConnection
  • ...on RootQueryToContentRevisionUnionConnection

Would need to be updated to reference these types instead:

  • ...on UserToRevisionsConnection
  • ...on RootQueryToRevisionsConnection

For example:



viewer {
revisions {
… on UserToContentRevisionUnionConnection {
nodes {
… on Post {
… on Page {
revisions {
… on RootQueryToContentRevisionUnionConnection {
nodes {
… on Post {
… on Page {



viewer {
revisions {
… on UserToRevisionsConnection {
nodes {
… on Post {
… on Page {
revisions {
… on RootQueryToRevisionsConnection {
nodes {
… on Post {
… on Page {

New Features

  • (#2617: feat: Introduce Connection, Edge and other common Interfaces.
  • (#2563: feat: refactor mutation registration to use new WPMutationType. Thanks @justlevine!
  • (#2557: feat: add deregister_graphql_type() access function and corresponding graphql_excluded_types filter. Thanks @justlevine!
  • (#2546: feat: Add new register_graphql_edge_fields() and register_graphql_connection_where_args() access functions. Thanks @justlevine!

Chores / Bugfixes

  • (#2622: fix: deprecate the previews field for non-publicly queryable post types, and limit the Previewable Interface to publicly queryable post types.
  • (#2614: chore(deps): bump loader-utils from 2.0.3 to 2.0.4.
  • (#2540: fix: deprecate Comment.approved field in favor of Comment.status: CommentStatusEnum. Thanks @justlevine!
  • (#2542: Move parse_request logic in NodeResolver::resolve_uri() to its own method. Thanks @justlevine!


New Features

  • (#2541): feat: Obfuscate SendPasswordResetEmail response. Thanks @justlevine!

Chores / Bugfixes

  • (#2544): chore: log and cleanup deprecations. Thanks @justlevine!
  • (#2605): chore: bump tested version of WordPress to 6.1. Thanks @justlevine!
  • (#2606): fix: update resolver in post->author connection to be more strict about the value of the author ID
  • (#2609): chore(deps): bump loader-utils from 2.0.2 to 2.0.3


New Features

  • (#2593): feat: use sha256 instead of md5 for hashing queryId
  • (#2581): feat: support deprecation reason when using register_graphql_connection.
  • (#2603): feat: add GraphQL operation name to x-graphql-keys headers.

Chores / Bugfixes

  • (#2472): fix: Return CommentAuthor avatar urls in public requests. Thanks @justlevine!
  • (#2549): chore: fix bug_report.yml description input. Thanks @justlevine!
  • (#2582): fix(noderesolver): adding extra_query_vars in graphql_pre_resolve_uri. Thanks @yanmorinokamca!
  • (#2583): chore: prepare docs for new website. Thanks @moonmeister!
  • (#2590): fix: Add list of node types as X-GraphQL-Keys instead of list of edge types
  • (#2599): fix: only use Appsero add_plugin_data if the method exists in the version of the Appsero client that’s loaded.
  • (#2600): docs: fix contributing doc render errors. Thanks @moonmeister!



This release removes the ContentNode and DatabaseIdentifier interfaces from the NodeWithFeaturedImage Interface.

This is considered a breaking change for client applications using a ...on NodeWithFeaturedImage fragment that reference fields applied by those interfaces. If you have client applications doing this (or are unsure if you do) you can use the following filter to bring back the previous behavior:


add_filter( ‘graphql_wp_interface_type_config’, function( $config ) {
if ( $config[‘name’] === ‘NodeWithFeaturedImage’ ) {
$config[‘interfaces’][] = ‘ContentNode’;
$config[‘interfaces’][] = ‘DatabaseIdentifier’;
return $config;
}, 10, 1 );

New Features

  • (#2399): New Schema Customization options for register_post_type and register_taxonomy. Thanks @justlevine!
  • (#2565): Expose X-GraphQL-URL header.

Chores / Bugfixes

  • (#2568): Fix typo in docs. Thanks @altearius!
  • (#2569): Update Appsero Client SDK.
  • (#2571): Dependabot bumps.
  • (#2572): Fixes a bug in the GraphiQL Query Composer when working with fields that return Unions. Thanks @chrisherold!
  • (#2556): Updates script that installs test environment to use env vars. Makes spinning up environments more convenient for contributors. Thanks @justlevine!
  • (#2538): Updates phpstan and fixes surfaced issues. Thanks @justlevine!
  • (#2545): Update WPBrowser to v3.1.6 and update test for SendPasswordResetEmail. Thanks @justlevine!


Chores / Bugfixes

  • (#2555): Further changes to X-GraphQL-Keys header output. Truncate keys based on a filterable max length. Output the skipped keys in extensions payload for debugging, and add skipped:$type keys to the X-GraphQL-Keys header for nodes that are skipped.


Chores / Bugfixes

  • (#2551): Chunks X-GraphQL-Keys header into multiple headers under a set max header limit length.
  • (#2539): Set IDE direction to prevent breaks in RTL mode. Thanks @justlevine!
  • (#2549): Fix bug_report.yml field to be textarea instead of input. Thanks @justlevine!


Chores / Bugfixes

  • (#2530): Fixes a regression introduced in v1.11.0 where querying menuItems with parentId where arg set to 0 was returning all menuItems instead of just top level items.


New Features

  • (#2519): Add new “QueryAnalyzer” class which tracks Types, Models and Nodes asked for and returned in a request and adds them to the response headers.
  • (#2519): Add 2nd argument to graphql() function that will return the Request object instead executing and returning the response.
  • (#2522): Allow global/database IDs in Comment connection where args. Thanks @justlevine!
  • (#2523): Allow global/database IDs in MenuItem connection where args ID Inputs. Thanks @justlevine!
  • (#2524): Allow global/database IDs in Term connection where args ID Inputs. Thanks @justlevine!
  • (#2525): Allow global/database IDs in Post connection where args ID Inputs. Thanks @justlevine!

Chores / Bugfixes

  • (#2521): Refactor $args in AbstractConnectionResolver. Thanks @justlevine!
  • (#2526): Ensure tracked data in QueryAnalyzer is unique.


New Features

  • (#2503): Enable codeception debugging via Github Actions. Thanks @justlevine!
  • (#2502): Add idType arg to RootQuery.comment. Thanks @justlevine!
  • (#2505): Return user after resetUserPassword mutation. Thanks @justlevine!

Chores / Bugfixes

  • (#2482): Add PHP Code Sniffer support for the WordPress.com VIP GO standard. Thanks @renatonascalves!
  • (#2490): Fix bug related to querying the page set as “Posts Page”
  • (#2497): Only enqueue admin scripts on the settings page. Thanks @justlevine!
  • (#2498): Add include and exclude args to MediaDetails.sizes. Thanks @justlevine!
  • (#2499): Check for multiple theme capabilities in the Theme Model. Thanks @justlevine!
  • (#2504): Filter mediaItems query by mimeType. Thanks @justlevine!
  • (#2506): Update descriptions for input fields that accept a databaseId. Thanks @justlevine!
  • (#2511): Update link in docs to point to correct “nonce” example. Thanks @NielsdeBlaauw!


Chores / Bugfixes

  • (#2471): feat: PHPCS: enhancements to the Coding Standards Setup. Thanks @renatonascalves!
  • (#2472): fix: return CommentAuthor avatar urls to public users. Thanks @justlevine!
  • (#2473): fix: Update GraphiQL “user switch” to be accessible. Thanks @nickcernis!
  • (#2477): fix(graphiql): graphiql fails if variables are invalid json



There are 2 changes that might require action when updating to 1.9.0.

  1. (#2464)

When querying for a nodeByUri, if your site has the “page_for_posts” setting configured, the behavior of the nodeByUri query for that uri might be different for you.

Previously a bug caused this query to return a “Page” type, when it should have returned a “ContentType” Type.

The bug fix might change your application if you were using the bug as a feature.

  1. (#2457)

There were a lot of bug fixes related to connections to ensure they behave as intended. If you were querying lists of data, in some cases the data might be returned in a different order than it was before.

For example, using the “last” input on a Comment or User query should still return the same nodes, but in a different order than before.

This might cause behavior you don’t want in your application because you had coded around the bug. This change was needed to support proper backward pagination.

** Chores / Bugfixes**

  • (#2450): Fix PHPCompatibility lint config. Thanks @justlevine!
  • (#2452): Fixes a bug with Comment.author connections not properly resolving for public (non-authenticated) requests.
  • (#2453): Update Github Workflows to use PHP 7.3. Thanks @justlevine!
  • (#2454): Add linter to ensure Pull Requests use “Conventional Commit” standards.
  • (#2455): Refactors and Lints the WPUnit tests. Cleans up some “leaky” data in test suites. Thanks @justlevine!
  • (#2457): Refactor Connection Resolvers to better adhere to Relay Connection spec. This fixes several bugs related to pagination across connections, specifically User and Comment connections which didn’t properly support backward pagination at all. Thanks @justlevine!
  • (#2460): Update documentation for running tests with Docker. Thanks @markkelnar!
  • (#2463): Add Issue templates to the repo. Thanks @justlevine!
  • (#2464): Fixes node resolver when “page_for_posts” setting is set to a page.


Chores / Bugfixes

  • (#2441): Fix contentNodes field not showing if a taxonomy is registered without connected post types. Thanks @saimonh3!
  • (#2446): Update “terser” from 5.11.0 to 5.14.2 (GraphiQL Dependency)
  • (#2440): Update JS dependencies for GraphiQL

New Features

  • (#2435): Add filter in execute for query string. Thanks @markkelnar!
  • (#2432): Add query_id to after_execute_actions for batch requests. Thanks @markkelnar!


Chores / Bugfixes

  • (#2427): Fixes a regression of the 1.8.3 release where there could be fatal errors when GraphQL Tracing is enabled and a queryId is used as a query param.


Chores / Bugfixes

  • (#2422): Fixes a regression of the 1.8.3 release where there could be fatal errors when GraphQL Tracing is enabled.


Chores / Bugfixes

  • (#2416): Fixes schema artifact workflow in Github.


New Features

  • (#2388): Adds ability to query menus by SLUG and LOCATION. Thanks @justlevine!

Chores / Bugfixes

  • (#2412): Update tests to run in PHP 8, 8.1 and with WordPress 6.0. Updates Docker Deploy workflow as well.
  • (#2411): Fixes bug where menuItems “location” arg was conflicting if a taxonomy is also registered with “location” as its name.
  • (#2410): Fixes a regression with Taxonomy Connection pagination.
  • (#2406): Updates PHPUnit, WPBrowser and WPGraphQL Test Case for use in workflows. Thanks @justlevine!
  • (#2387): Fixes a bug with asset versions when querying for Enqueued Scripts and Styles. Thanks @justlevine!


New Features

  • (#2363): Adds “uri” field to MenuItem type which resolves the path of the node which can then be used in a nodeByUri query to get the linked node. The path is relative and does not contain subdirectory path in a subdirectory multisite. the path field does include the multisite subdirectory path, still. Thanks @josephfusco and @justlevine!
  • (#2337): Allows for either global ID or databaseId to be supplied in the ID field for user mutations. Thanks @justlevine!
  • (#2338): Allows either global “relay” ID or databaseId for post object mutations. Thanks @justlevine!
  • (#2336): Allows either global “relay” ID or databaseId for term object mutations. Thanks @justlevine!
  • (#2331): Allows either global “relay” ID or databaseId for MediaItem object mutations. Thanks @justlevine!
  • (#2328): Allows either global “relay” ID or databaseId for Comment object mutations. Thanks @justlevine!


  • (#2368): Updates dependencies for Schema Linter workflow.
  • (#2369): Replaces the Codecov badge in the README with Coveralls badge. Thanks @justlevine!
  • (#2374): Updates descriptions for PostObjectFieldFormatEnum. Thanks @justlevine!
  • (#2375): Sets up the testing integration workflow to be able to run in multisite. Adds one workflow that runs in multisite. Fixes tests related to multisite.
  • (#2376): Adds support for ['auth']['callback'] and isPrivate for the register_graphql_mutation() API.
  • (#2379): Fixes a bug where term mutations were adding slashes when being stored in the database.
  • (#2380): Fixes a bug where WPGraphQL wasn’t sending the Wp class to the parse_request filter as a reference.
  • (#2382): Fixes a bug where register_graphql_field() was not being respected by GraphQL Types added to the schema to represent Setting Groups of the core WordPress register_setting() API.


New Features

  • (#2349): Adds tags to wpkses_post for WPGraphQL settings pages to be extended further. Thanks @eavonius!


  • (#2358): Updates NPM dependencies. Thanks @dependabot!
  • (#2357): Updates NPM dependencies. Thanks @dependabot!
  • (#2356): Refactors codebase to take advantage of the work done in #2353. Thanks @justlevine!
  • (#2354): Fixes console warnings in GraphiQL related to missing React keys.
  • (#2353): Refactors the WPGraphQL::get_allowed_post_types() and WPGraphQL::get_allowed_taxonomies() functions. Thanks @justlevine!
  • (#2350): Fixes bug where Comment Authors were not always properly returning


New Features

  • (#2286): Introduce new Utils::get_database_id_from_id() function to help DRY up some code around inputs that can accept Global IDs or Database IDs. Thanks @justlevine!
  • (#2327): Update capability for plugin queries. Changes from update_plugins to activate_plugins. Thanks @justlevine!
  • (#2298): Adds $where arguments to Plugin Connections. Thanks @justlevine!
  • (#2332): Adds new Github workflow to build the GraphiQL App on pushes to develop and master. This should allow users that install WPGraphQL to install/update with Composer and have the GraphiQL app running, instead of having to run npm install && npm run build in addition to composer install.

Chores / Bugfixes

  • (#2286): Remove old, no-longer used JS files. Remnant from 1.7.0 release.
  • (#2296): Fixes bug with how post/page templates are added to the Schema. Thanks @justlevine!
  • (#2295): Fixes bug where menus were returning when they shouldn’t be. Thanks @justlevine!
  • (#2299): Fixes bug with author ID not being cast to an integer properly in the MediaItemUpdate mutation. Thanks @abaicus!
  • (#2310): Bumps node-forge npm dependency
  • (#2317): Bumps composer dependencies
  • (#2291): Add “allow-plugins” to composer.json to reduce warning output when running composer install. Thanks @justlevine!
  • (#2294): Refactors AbstractConnectionResolver::get_nodes() to prevent double slicing. Thanks @justlevine!
  • (#2293): Fixes connections that can be missing nodes when before/after arguments are empty. Thanks @justlevine!
  • (#2323): Fixes bug in Comment mutations. Thanks @justlevine!
  • (#2320): Fixes bug with filtering comments by commentType. Thanks @justlevine!
  • (#2319): Fixes bug with the comment_text filter in Comment queries. Thanks @justlevine!


Chores / Bugfixes

  • (#2276): Fixes a bug where generalSettings.url field was not in the Schema for multisite installs.
  • (#2278): Adds a composer post-install script that installs JS dependencies and builds the JS app when composer install is run
  • (#2277): Adds a condition to the docker image to only run npm scripts if the project has a package.json. Thanks @markkelnar!


Chores / Bugfixes

  • (#2268): Fixes a bug in GraphiQL that would update browser history with every change to a query param.


Chores / Bugfixes

  • (#2228): Allows optional fields to be set to empty values in the updateUser mutation. Thanks @victormattosvm!
  • (#2247): Add WordPress 5.9 to the automated testing matrix. Thanks @markkelnar!
  • (#2242): Adds End 2 End tests to test GraphiQL functionality in the admin.
  • (#2261): Fixes a bug where the pageByUri query might return incorrect data when custom permalinks are set. Thanks @blakewilson!
  • (#2263): Adds documentation entry for WordPress Application Passwords guide. Thanks @abhisekmazumdar!
  • (#2262): Fixes a bug where settings registered via the core register_setting() API would cause Schema Introspection …