WordPress Secrets API: A New Way to Secure Plugin API Keys
WordPress plugins rely on external services more than ever. From payment gateways and email marketing platforms to AI integrations, analytics tools, cloud storage, and CRM systems, modern plugins regularly communicate with third-party APIs.
But there is one security challenge that plugin developers have faced for years: How should sensitive API keys and credentials be stored securely in WordPress?
Traditionally, developers have relied on the WordPress Options API to save credentials. Functions such as update_option() and get_option() make it easy to store and retrieve configuration values. However, these functions do not automatically encrypt sensitive information.
This means API keys, access tokens, and other credentials may be stored as readable text in the WordPress database.
WordPress 7.2 introduces an important development that aims to address this problem: the WordPress Secrets API.
The new API provides a standardized mechanism for storing encrypted credentials, managing previous versions, rotating secrets, and integrating external secret-management systems.
For plugin developers, this could significantly improve how WordPress applications handle sensitive information.
In this article, we’ll explore what the Secrets API is, why it matters, how developers can use it, and what it could mean for the future of WordPress plugin development.
1. Why Does WordPress Need a Secrets API?
Let’s start with a common development scenario.
Imagine you are building a WordPress plugin that connects a website to an external service. The plugin requires an API key to authenticate requests.
A typical implementation might look like this:
// Save the API key.
update_option( 'my_plugin_api_key', $api_key );
// Retrieve the API key.
$api_key = get_option( 'my_plugin_api_key' );
This approach is simple and works perfectly well for ordinary plugin settings.
However, API keys are different from regular configuration values.
An API key can provide access to external services, customer information, payment operations, or other sensitive resources. If someone obtains a database backup or gains unauthorized access to the database, credentials stored as plain text may also become exposed.
Consider some common situations:
- A developer downloads a production database to troubleshoot a website.
- A database backup is accidentally shared with an unauthorized person.
- A staging website contains copied production credentials.
- A database vulnerability exposes information stored in the options table.
- A developer accidentally includes credentials in debugging output.
- A backup file is stored in an insecure location.
In these situations, API keys stored as plain text can increase the potential impact of a security incident.
Until now, plugin developers have often implemented their own encryption mechanisms or relied on third-party libraries to protect credentials.
The problem is that different plugins use different approaches. This creates additional development work and makes security practices inconsistent across the WordPress ecosystem.
The Secrets API introduces a common foundation that developers can use instead of creating their own credential-storage systems.
2. What Is the WordPress Secrets API?
The WordPress Secrets API is a new Core feature introduced in the WordPress 7.2 development cycle.
Its primary purpose is to provide a standardized way to store, retrieve, update, and delete sensitive information such as:
- Third-party API keys.
- OAuth access tokens.
- OAuth client secrets.
- Payment gateway credentials.
- External service passwords.
- Webhook signing secrets.
- Other sensitive integration credentials.
Instead of storing these values directly using the traditional Options API, developers can use dedicated functions designed specifically for managing secrets.
Some of the important functions include:
| Function | Purpose |
|---|---|
wp_set_secret() |
Creates or updates a secret. |
wp_get_secret() |
Retrieves a stored secret. |
wp_delete_secret() |
Deletes a secret. |
wp_retire_secret_version() |
Removes the previous version of a secret. |
wp_list_secrets() |
Lists secret names and metadata. |
wp_import_option_as_secret() |
Imports an existing option into secure storage. |
The API also supports network-level secret management for WordPress Multisite installations.
One important advantage is that developers can use the same API regardless of the underlying storage implementation.
This means a website could use WordPress’s default encrypted database storage or an alternative storage system provided by its hosting company.
3. How to Store API Keys Using the Secrets API
Let’s look at a practical example.
Suppose you are developing a plugin called my-plugin that connects WordPress to an external service.
Your plugin needs to store an API key securely.
Step 1: Store the API key
Instead of using update_option(), you can use wp_set_secret().
$api_key = 'your-api-key-here';
$result = wp_set_secret(
'my-plugin/api-key',
$api_key
);
if ( is_wp_error( $result ) ) {
error_log( 'Unable to save API key.' );
}
Here, my-plugin/api-key is the unique name assigned to the secret.
WordPress recommends using the following naming convention:
plugin-slug/secret-name
For example:
my-plugin/api-key
my-plugin/client-secret
my-plugin/access-token
my-plugin/webhook-secret
This makes it easier to organize credentials belonging to different plugins.
However, namespaces are organizational rather than security boundaries. They do not prevent other PHP code running on the same WordPress installation from accessing a secret.
Step 2: Retrieve the API key
When your plugin needs to communicate with the external service, use wp_get_secret().
$secret = wp_get_secret( 'my-plugin/api-key' );
if ( is_wp_error( $secret ) ) {
// Handle retrieval or decryption errors.
return;
}
if ( null === $secret ) {
// API key has not been configured.
return;
}
$api_key = $secret->reveal();
// Use the API key.
$client = new API_Client( $api_key );
There is an interesting difference here.
Unlike get_option(), which returns the stored value directly, wp_get_secret() returns a WP_Secret object when the secret is available.
The developer must explicitly call:
$secret->reveal();
to access the actual credential.
This design helps reduce accidental exposure through debugging and logging.
For example, printing or inspecting the WP_Secret object does not reveal the original API key. Developers must deliberately request the sensitive value.
Step 3: Delete a secret
When a user disconnects an external integration, the plugin can delete its stored credential.
wp_delete_secret( 'my-plugin/api-key' );
This provides a dedicated method for managing the complete credential lifecycle.
4. How Does WordPress Encrypt Secrets?
One of the most important aspects of the Secrets API is its encryption mechanism.
WordPress uses libsodium encryption with XChaCha20-Poly1305 to protect secrets at rest.
The default implementation uses a root key and derived encryption keys.
Here is the simplified process:
- WordPress generates a random root key.
- The root key is protected using the
WP_SECRETS_KEYconstant. - Individual secrets are encrypted using derived encryption keys.
- The encrypted records are stored in the WordPress database.
- When a plugin requests a credential, WordPress decrypts it and returns a
WP_Secretobject.
The important point is that the database stores encrypted credentials rather than their original readable values.
This reduces the risk of exposing API keys when someone gains access to a database backup or database export without obtaining the corresponding encryption key.
Understanding WP_SECRETS_KEY
The Secrets API introduces a new configuration constant:
define(
'WP_SECRETS_KEY',
'your-base64-encoded-random-32-byte-key'
);
This constant is placed in the wp-config.php file.
New WordPress installations generate this key automatically during installation. Existing installations need to configure it before using the API.
Developers can generate a suitable key using PHP:
php -r 'echo base64_encode( random_bytes( 32 ) ), "\n";'
Important: Do not treat WP_SECRETS_KEY like ordinary WordPress authentication salts.
Once secrets have been stored, changing or removing this key can make existing credentials unreadable.
Key rotation must follow the documented WordPress procedure to avoid losing access to stored secrets.
WordPress also includes Site Health checks to help administrators identify missing encryption keys and secrets that cannot be decrypted.
5. Secret Rotation: An Important New Feature
API credentials do not remain valid forever.
Developers and website administrators regularly need to replace credentials because of:
- Expired API tokens.
- Security incidents.
- Third-party service changes.
- Routine security maintenance.
- Changes to external application permissions.
Traditionally, replacing an API key meant overwriting the existing database value.
However, this can create problems when an integration is still using the previous credential.
The Secrets API introduces support for retaining two versions of a secret: the current version and the previous version.
For example:
Before rotation:
Current API key: API_KEY_OLD
After rotation:
Current API key: API_KEY_NEW
Previous API key: API_KEY_OLD
When a new secret is saved, WordPress retains the previous version.
Developers can retrieve that previous credential using:
$previous_secret = wp_get_secret(
'my-plugin/api-key',
WP_Secret_Version::PREVIOUS
);
if ( $previous_secret instanceof WP_Secret ) {
$old_api_key = $previous_secret->reveal();
}
Once the old credential is no longer required, developers can retire it:
wp_retire_secret_version( 'my-plugin/api-key' );
This is particularly useful for integrations that need a transition period when replacing credentials.
However, WordPress cannot automatically determine when an external service has stopped accepting the previous key. Plugin developers must manage that process and retire the old version when appropriate.
6. What Happens to Existing Plugins Using update_option()?
This is one of the biggest questions for developers who maintain established WordPress plugins.
Millions of websites already have API credentials stored through the Options API.
WordPress does not automatically scan the database and convert every option that looks like an API key into an encrypted secret.
Instead, developers can migrate existing credentials using:
wp_import_option_as_secret(
'my_plugin_api_key',
'my-plugin/api-key'
);
This imports the existing option into the Secrets API.
However, the original option is not automatically deleted. Developers need to handle that separately.
For example:
$result = wp_import_option_as_secret(
'my_plugin_api_key',
'my-plugin/api-key'
);
if ( ! is_wp_error( $result ) ) {
delete_option( 'my_plugin_api_key' );
}
Before performing the migration, developers should check whether the Secrets API is available:
if ( wp_is_secrets_api_available() ) {
// Safely perform the migration.
}
Another important consideration is credential rotation.
Importing a credential does not remove copies that may already exist in old backups, staging environments, or database exports.
The imported secret is flagged as pending rotation so that developers can arrange for the actual external API credential to be replaced.
This makes migration more meaningful than simply encrypting an existing value.
7. Can Hosting Providers Use Their Own Secret Storage?
Yes, and this is one of the most interesting aspects of the Secrets API.
Not every website needs to store sensitive credentials directly in its WordPress database.
Enterprise websites and managed hosting environments may already use external secret-management solutions such as:
- AWS Secrets Manager.
- AWS Key Management Service.
- HashiCorp Vault.
- Hardware Security Modules.
- Other cloud-based secret-management services.
WordPress provides a wp-content/secrets.php drop-in that allows hosting providers to replace parts of the default implementation.
There are three important extension points:
| Component | Responsibility |
|---|---|
WP_Secrets_Keyring |
Manages encryption key protection. |
WP_Secrets_Store |
Controls where encrypted secrets are stored. |
WP_Secrets_Provider |
Provides an alternative secret-management implementation. |
For example, a hosting provider could store credentials in an external secret manager rather than keeping encrypted records in the WordPress database.
The plugin developer does not need to know where the credential is stored.
They can continue using:
$secret = wp_get_secret( 'my-plugin/api-key' );
The underlying provider handles the storage and retrieval process.
Some hosting providers may offer read-only secret storage, where credentials are managed through their hosting dashboard or command-line tools.
Developers should check whether the provider supports writing before displaying an API-key input field.
if ( ! wp_secrets_provider_is_writable() ) {
// Credentials are managed by the hosting provider.
return;
}
If a provider does not support writing, plugins should not silently fall back to storing credentials as plain-text options. Doing so would defeat the purpose of using the Secrets API.
8. Does the Secrets API Prevent Other Plugins from Accessing Credentials?
There is an important security distinction developers should understand.
The Secrets API provides encryption at rest, but it does not create complete isolation between plugins.
For example, naming a credential:
my-plugin/api-key
does not automatically mean that only my-plugin can retrieve it.
Other PHP code running within the same WordPress installation may be able to request and reveal that secret.
The API also does not automatically implement user permission checks for every plugin settings screen or REST endpoint.
Developers must still use appropriate capability checks, nonce verification, input validation, and secure request handling.
For example, an API-key management screen should restrict access to authorized administrators:
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( 'You are not allowed to manage these settings.' );
}
The Secrets API also cannot prevent an attacker with arbitrary PHP code execution from accessing credentials that the application itself needs to use.
Therefore, it should be considered an additional security layer rather than a complete replacement for good WordPress security practices.
9. Is There a Centralized Secrets Management Dashboard?
WordPress 7.2 introduces the underlying API rather than a complete graphical interface for managing every secret.
This means administrators will generally continue managing credentials through individual plugin settings screens or hosting-provider tools.
The API also introduces Site Health checks to help identify important problems, including:
- Missing or unusable encryption keys.
- Secrets that cannot be decrypted.
- Credentials pending rotation.
A centralized management interface is planned for a later development cycle, with the original proposal targeting WordPress 7.3.
This could eventually make it easier for administrators to understand which plugins are storing credentials and identify potential configuration problems.
10. What Should Plugin Developers Do Before Adopting the Secrets API?
If you develop WordPress plugins, now is a good time to review how your code handles sensitive information.
Start by identifying all the credentials currently stored using update_option().
These may include API keys, access tokens, client secrets, SMTP passwords, and external service credentials.
Here are some practical recommendations:
1. Identify sensitive options
Review your plugin’s database options and identify which values should be treated as secrets.
2. Check API availability
Use wp_is_secrets_api_available() before attempting to store or migrate credentials.
3. Use dedicated secret functions
Use wp_set_secret() and wp_get_secret() rather than relying on ordinary options for new credential storage.
4. Handle errors properly
Account for WP_Error, null, and WP_Secret responses when retrieving credentials.
5. Implement permission checks
Make sure only authorized users can manage API keys through your plugin settings.
6. Support credential rotation
Plan how your plugin will transition from previous credentials to newly generated ones.
7. Consider hosting compatibility
Check whether an external provider supports writing secrets before allowing users to configure credentials through your plugin.
8. Plan existing credential migrations
Use wp_import_option_as_secret() to migrate existing credentials carefully.
9. Maintain backward compatibility
If your plugin supports older WordPress versions, check whether the Secrets API is available before calling its functions.
10. Test before production deployment
Test installation, migration, key changes, backups, database restoration, and multisite behaviour in a staging environment.
11. What Does the Secrets API Mean for the Future of WordPress?
The Secrets API is more than another set of WordPress functions.
It represents a shift toward treating sensitive information differently from ordinary website settings.
Consider how many popular WordPress plugin categories depend on external credentials.
| Plugin category | Sensitive information |
|---|---|
| Payment gateways | Payment API keys and merchant credentials |
| SMTP plugins | Email server passwords and API tokens |
| SEO integrations | Analytics and Search Console tokens |
| Backup plugins | Cloud storage credentials |
| AI plugins | OpenAI and other AI provider API keys |
| Membership plugins | External authentication tokens |
| Marketing plugins | CRM and email marketing credentials |
Until now, developers have often implemented their own credential-storage and encryption solutions.
A standardized API could reduce duplicated development work and create more consistent security practices across the ecosystem.
It could also make it easier for hosting providers to integrate enterprise-grade secret-management infrastructure into WordPress websites.
This is particularly relevant as WordPress continues to expand into AI-powered applications.
AI plugins increasingly connect websites to external services for content generation, chatbots, image generation, automation, and data processing.
Each integration introduces another API key or authentication token that needs to be managed responsibly.
The Secrets API provides a common foundation for handling these credentials.
12. Final Thoughts
For years, WordPress plugin developers have relied on the Options API to store everything from simple configuration values to sensitive third-party credentials.
While this approach is convenient, it does not provide the encryption and credential-management features that modern integrations increasingly require.
The WordPress Secrets API addresses an important gap by introducing dedicated functions for encrypted credential storage, retrieval, migration, and rotation.
Its support for alternative storage providers is equally interesting because it creates opportunities for hosting companies to integrate external secret-management infrastructure.
There are still limitations. Encryption at rest does not prevent other plugins from accessing credentials, and developers must continue implementing proper permissions and secure coding practices.
Nevertheless, the Secrets API is a meaningful step toward improving WordPress security.
For plugin developers, the recommendation is simple: start reviewing how your plugins handle API keys and prepare to adopt the Secrets API where appropriate.
As WordPress becomes more connected to AI services, payment platforms, cloud infrastructure, and external applications, secure credential management will become increasingly important.
The Secrets API could be one of the foundations that makes that future safer.
