How to Use the WordPress Abilities API (Register & Execute)
WordPress 6.9 is shipped with a number of interesting features. Among these is a new API called Abilities API.
The Abilities API provides a standardized way for WordPress core, plugins, and themes to define their capabilities in a format both humans and machines can read.
In this post, we’ll explore what the Abilities API is, why it matters, and how to use it in practice with some code examples.
Without further ado, let’s get started.
What is Abilities API?
The Abilities API is a new feature in WordPress that acts like a dictionary of everything a site can do. Before this, there was no simple or consistent way for plugins or external tools to discover a site’s available features. Functionality was often scattered across hooks, REST API endpoints, and various pieces of custom code.
With the Abilities API, automation tools, AI assistants, and other plugins can more easily understand how to interact with a WordPress site. Tools like AI agents, Zapier, or n8n can simply ask WordPress, “What can you do?” and receive a structured list of abilities.
This API also makes cross-plugin collaboration much cleaner. Plugins can call each other’s abilities directly instead of relying on hidden hooks or fragile workarounds.
Getting Started
To use the Abilities API, the first step is to register a new ability. This is typically done within your plugin or theme. An “Ability” should contain:
- A unique name that consists of only lowercase alphanumeric characters, dashes, and forward slashes e.g.
hongkiatcom/create-invoice - A human-readable description and label.
- A defined output and input schema.
- A permission check.
Here is a simple example of how we register an ability that analyzes a site and returns some metrics.
In this example, we call it hongkiatcom/site-analytics-summary. It doesn’t require any inputs and returns an object containing three metrics: visits, signups, and sales. The ability can only be executed by users with the manage_options capability.
add_action( 'wp_abilities_api_init', function () {
if ( ! function_exists( 'wp_register_ability' ) ) {
return;
}
wp_register_ability(
'hongkiatcom/site-analytics-summary',
[
'label' => __( 'Get Site Analytics Summary', 'myplugin' ),
'description' => __( 'Returns a simple overview of site performance.', 'myplugin' ),
'input_schema' => [
'type' => 'object',
'properties' => [],
],
'output_schema' => [
'type' => 'object',
'properties' => [
'visits' => [ 'type' => 'integer' ],
'signups' => [ 'type' => 'integer' ],
'sales' => [ 'type' => 'integer' ],
],
],
'permission_callback' => function () {
return current_user_can( 'manage_options' );
},
'execute_callback' => function () {
return [
'visits' => 1473,
'signups' => 32,
'sales' => 5,
];
},
]
);
});
Here is another example of registering an ability that processes an order. This ability takes in customer ID, product SKUs, and a payment token as input, and returns the order ID, status, and a confirmation message as output.
add_action( 'init', function() {
if ( ! function_exists( 'wp_register_ability' ) ) {
return;
}
wp_register_ability( 'hongkiatcom/process-order', [
'description' => 'Handles payment, creates an order record, and sends a confirmation email.',
'execute_callback' => function () {
// Implementation of order processing logic goes here...
},
'input_schema' => [
'type' => 'object',
'properties' => [
'customer_id' => [
'type' => 'integer',
'description' => 'The ID of the customer placing the order.',
],
'product_skus' => [
'type' => 'array',
'description' => 'An array of product SKUs (strings) to be included in the order.',
'items' => [ 'type' => 'string' ],
],
'payment_token' => [
'type' => 'string',
'description' => 'A secure, single-use token from the payment gateway.',
],
],
'required' => [ 'customer_id', 'product_skus', 'payment_token' ],
],
'output_schema' => [
'type' => 'object',
'properties' => [
'order_id' => [
'type' => 'integer',
'description' => 'The ID of the newly created order post.',
],
'order_status' => [
'type' => 'string',
'description' => 'The resulting status of the order (e.g., "processing", "pending").',
],
'message' => [
'type' => 'string',
'description' => 'A confirmation message.',
],
],
],
] );
} );
Executing Abilities
Registering an ability doesn’t do much on its own. We also want to execute it and get the result.
In PHP
In PHP, using an ability is straightforward. WordPress provides a function wp_get_ability() to retrieve the ability object by name, and then you call the ability’s execute() method.
Here’s how you might execute the site-analytics-summary ability we registered:
$ability = wp_get_ability( 'hongkiatcom/site-analytics-summary' );
if ( $ability ) {
$result = $ability->execute();
}
If the ability requires inputs such as in the process-order example, you would pass an associative array of inputs to the execute() method:
$ability = wp_get_ability( 'hongkiatcom/process-order' );
if ( $ability ) {
$inputs = [
'customer_id' => 123,
'product_skus' => [ 'SKU123', 'SKU456' ],
'payment_token'=> 'tok_1A2B3C****',
];
$result = $ability->execute( $inputs );
}
Notice that we didn’t have to manually handle permission checks or input validation here. If the current user didn’t have permission, or if we passed a wrong type of input, execute() would fail gracefully. It wouldn’t run the callback and would return an error or false. This is thanks to the schemas and permission callback we set up during registration. It makes using the ability safe and predictable.
Now that we’ve seen how to declare and use abilities on the back-end, let’s look at how abilities can be accessed from JavaScript, which covers front-end use cases and external integrations.
In JavaScript
The Abilities API supports REST API out of the box, but you need to make sure that you enable the show_in_rest on the Ability registration, for example:
add_action( 'wp_abilities_api_init', function () {
if ( ! function_exists( 'wp_register_ability' ) ) {
return;
}
wp_register_ability(
'hongkiatcom/site-analytics-summary',
[
...
'execute_callback' => function () {
return [
'visits' => 1473,
'signups' => 32,
'sales' => 5,
];
},
'meta' => [
'show_in_rest' => true,
],
]
);
});
Once that’s set, the ability becomes accessible under a special REST namespace wp-abilities/v1/{ability-namespace}/{ability-name}. In our example above, the full REST endpoint to execute the ability would be: /wp-json/wp-abilities/v1/hongkiatcom/site-analytics-summary.
This means external applications or your own front-end code can execute abilities by sending HTTP requests without you writing any extra REST handler code. WordPress takes care of that based on the info you provided.
WordPress is also introducing a JavaScript client library for the Abilities API, making it much easier to call abilities from the browser or any headless JS setup. Instead of writing manual fetch() calls, you can simply use built-in helper functions to list, fetch, and run abilities.
First, we’d need to install the library with NPM:
npm i @wordpress/abilities
Then, we can use it like this in our JavaScript application:
useEffect(() => {
executeAbility( 'hongkiatcom/site-analytics-summary' ).then( ( response ) => {
setResponse( response ); // Store the result in state.
} );
}, []);
Wrapping Up
The Abilities API introduces a new way for WordPress to describe what it can do in a clear and more standardized format. This improves the interoperability of your site and allows it to work more naturally with AI assistants or automation tools.
In this article, we’ve just scratched the surface of what’s possible with the Abilities API. As more plugins and themes adopt it, we can expect a richer ecosystem where capabilities are easily discoverable and usable across different contexts.
And in the next article, we’ll see how we can integrate your WordPress site with external applications like Claude or LM Studio using the Abilities API.
So stay tuned!