Skip to content

Abilities

Arun Prakash edited this page Oct 25, 2026 · 2 revisions

Abilities

The WordPress Abilities API (WordPress 6.9+) lets plugins register named, schema-described functions that clients can discover and run. client.abilities wraps its REST routes (/wp-json/wp-abilities/v1) on the client's own origin.

Every call sends the default credentials, and only abilities registered with show_in_rest are visible. Check client.discovery.namespaces for wp-abilities/v1 to see whether a site supports it (Usage).

Discover

// One page
final page = await client.abilities.list(category: 'site', perPage: 50);

// All pages
final all = (await client.abilities.listAll(category: 'site')).dataOrThrow();

final ability = (await client.abilities.retrieve('my-plugin/get-user-info')).dataOrThrow();
print(ability.label);
print(ability.description);
print(ability.inputSchema);     // JSON schema (Map) or null
print(ability.outputSchema);
print(ability.isReadOnly);      // meta.annotations: readonly / destructive / idempotent
print(ability.requiredCapabilities);  // WordPress capabilities the user needs, if declared

Names are namespace/ability-name. The slash is part of the route and is handled for you. The routes are abilities, abilities/{namespace}/{ability} and abilities/{namespace}/{ability}/run under wp-abilities/v1 (verified against WordPress core; the developer.wordpress.org reference omits the abilities segment).

Categories

final cats = (await client.abilities.categories()).dataOrThrow();    // List<AbilityCategory>: slug, label, description
final cat = await client.abilities.category('site');

Run

The REST API requires the HTTP method to match the ability: GET for read-only, DELETE for destructive, POST otherwise. The client picks it for you.

// By name. Looks the ability up first to learn its method (one extra request).
final r = await client.abilities.run('my-plugin/get-user-info', input: {'user_id': 1});

// With an Ability you already have. No lookup.
final r2 = await client.abilities.runAbility(ability, input: {'user_id': 1});

// Force the method and skip the lookup
final r3 = await client.abilities.run('my-plugin/ping', method: HttpMethod.get);

print(r.dataOrNull());     // whatever the ability returns: object, list, scalar, null

input is any JSON-encodable value. For GET and DELETE it travels as the input query parameter (JSON encoded), for POST in the body.

Failures

A missing or invalid ability, bad input or insufficient permission arrives as an ApiFailure or AuthFailure with the WordPress WordpressError (for example ability_invalid_input). See Error Handling and Responses.

Other methods

Both list and categories take page, perPage (default 50) and cancelToken. Caching, Retries and Middlewares apply as for any request.

Clone this wiki locally