KeyPort LogoKeyPort
Back to all guides
Tutorial• April 2026

How to Add License Keys to a WordPress Plugin

A practical guide to adding license key validation to any WordPress plugin using the KeyPort REST API with real PHP examples.

ER
Emily RodriguezAuthor • 5 min read

If you're selling a premium WordPress plugin, you need license key enforcement. Without it, a buyer can share your plugin ZIP and anyone can install it for free. This guide adds real enforcement using the KeyPort API — all in PHP, no dependencies.

Step 1 — Create Your Product on KeyPort

Sign up at app.keyport.sbs. Create an organization, then a product called "Your Plugin Name." Copy your product API key. Store it in wp-config.php, not in the plugin file itself.

Step 2 — Settings Page for the License Key

<?php
function my_plugin_render_license_settings() {
    $license_key    = get_option('my_plugin_license_key', '');
    $license_status = get_option('my_plugin_license_status', null);
?>
<div class="my-plugin-license">
    <h2>License</h2>
    <?php if ($license_status === 'active'): ?>
        <p style="color: green">✓ License active</p>
    <?php elseif ($license_status): ?>
        <p style="color: red">Issue: <?= esc_html($license_status) ?></p>
    <?php endif; ?>
    <form method="post" action="options.php">
        <?php settings_fields('my_plugin_settings'); ?>
        <input type="text" name="my_plugin_license_key"
            value="<?= esc_attr($license_key) ?>"
            placeholder="XXXX-XXXX-XXXX-XXXX" style="width: 300px">
        <?php submit_button('Save License', 'primary', 'submit', false); ?>
    </form>
</div>
<?php }

Step 3 — Validate the License Key

<?php
function my_plugin_validate_license(string $key): array {
    $response = wp_remote_post('https://api.keyport.sbs/api/v1/validate', [
        'timeout' => 8,
        'headers' => [
            'Content-Type'  => 'application/json',
            'Authorization' => 'Bearer ' . MY_PLUGIN_API_KEY,
        ],
        'body' => wp_json_encode(['license_key' => $key]),
    ]);

    if (is_wp_error($response)) {
        // Network error — use cached result (24-hour grace)
        return get_transient('my_plugin_license_cache') ?: [
            'valid' => false, 'status' => 'network_error'
        ];
    }

    $data = json_decode(wp_remote_retrieve_body($response), true);

    if ($data['valid']) {
        set_transient('my_plugin_license_cache', $data, DAY_IN_SECONDS);
        update_option('my_plugin_license_status', 'active');
    } else {
        update_option('my_plugin_license_status', $data['status']);
    }

    return $data;
}

// Re-validate on settings save
add_action('update_option_my_plugin_license_key', function($old, $new) {
    my_plugin_validate_license($new);
}, 10, 2);

Step 4 — Gate Premium Features

<?php
function my_plugin_is_licensed(): bool {
    return get_option('my_plugin_license_status') === 'active';
}

// In your premium feature code:
if (!my_plugin_is_licensed()) {
    echo '<p>This feature requires a valid license. '
       . '<a href="https://yourdomain.com/pricing">Get a license →</a></p>';
    return;
}
// Full feature code here...

Step 5 — Gate Plugin Updates (Optional)

<?php
add_filter('site_transient_update_plugins', function($transient) {
    if (!my_plugin_is_licensed()) {
        $plugin_file = 'my-plugin/my-plugin.php';
        unset($transient->response[$plugin_file]);
    }
    return $transient;
});

Testing Checklist

  • [ ] Valid key → shows "active"
  • [ ] Invalid key → shows error
  • [ ] Expired key → shows "expired"
  • [ ] No network → uses 24-hour cached result
  • [ ] Premium features hidden without valid license
  • [ ] Update notification hidden without valid license

Scale your product with KeyPort

Free tier available for launch and small production workloads. No credit card required.