Keap Connect WP Registry grade A. No security issues foundWP RegistryNo security issues foundOpen the reportA
Keap Plugin Wordpress Endpoint
Install
This is the repository archive. It installs, but the folder name will carry the branch suffix and updates will not flow.
Install straight from GitHub with WP-CLI:
wp plugin install https://github.com/ratne/keap-wordpress/archive/refs/heads/main.zipReceive leads on a generic REST endpoint and sync them to Keap (Infusionsoft) via the REST v2 API.
Keap Connect is a WordPress plugin that exposes a generic, secured REST endpoint. Any system (a form, a webhook, a custom integration) can POST a JSON body to it, and the plugin will find-or-create the matching contact in Keap, update its fields, and apply tags — with full request logging and automatic OAuth token refresh.
- Author: Ratne — ratne.dev
- License: GPL-2.0-or-later
- Requires: WordPress 5.6+, PHP 8.0+ (tested up to PHP 8.5)
Features
- Generic REST endpoint —
POST /wp-json/keap-connect/v1/intake, accepts a JSON body. - Optional Bearer protection — random token generated by the plugin and rotatable from the admin UI.
- Dual authentication with fallback — OAuth and/or PAT/SAK. In Both mode, if an OAuth call fails authentication it is automatically retried with the PAT/SAK.
- Find-or-create flow — looks the contact up by email, creates it if missing, otherwise updates it.
- Tagging — applies the tag IDs received in the body's
Tagfield. - Configurable field mapping — map incoming body keys to Keap standard fields, custom fields (fetched live from your Keap account), or address components.
- Full logging — every incoming body and every outgoing Keap request is logged with status code, response and a correlation ID (secrets are masked).
- Automatic token refresh — OAuth token refreshed every 6 hours via WP-Cron (Keap tokens expire roughly every 12–24h), with an optional external cron endpoint.
- GitHub auto-updates — ships with Plugin Update Checker so new releases appear in the WordPress updates screen.
Installation
- Copy the plugin folder into
wp-content/plugins/. - Activate Keap Connect from the WordPress Plugins screen.
- On activation the plugin creates its log table, generates the Bearer/cron secrets, and schedules the 6-hour refresh cron.
- Open Keap Connect in the admin sidebar.
Configuration
The admin screen has four tabs.
1. Connection
Choose the authentication method and enter the credentials:
- OAuth — enter the Client ID and Client Secret from your Keap app, register the displayed Redirect URI in the Keap app settings, then click Connect / reconnect OAuth.
- PAT / SAK — paste a Personal Access Token or Service Account Key.
- Method — OAuth only, PAT/SAK only, or Both (OAuth primary, PAT/SAK fallback).
Use Test connection to verify access.
Reference:
2. Endpoint
- Copy the Endpoint URL and the Bearer token.
- Toggle Require Bearer, Create if missing, and the External cron.
- Configure Log retention (in days;
0keeps logs forever). - Rotate the Bearer token or the cron secret at any time.
3. Mapping
- Click Refresh fields from Keap to fetch the custom fields from your account (
GET /contacts/model). - Add rows mapping each incoming body key to a target:
- Standard field:
given_name,family_name,email,phone,company,job_title. - Custom field: chosen from the live Keap custom fields list.
- Address:
line1,line2,locality,region,postal_code,country_code+ address type (Billing / Shipping / Other).
- Standard field:
The body Tag field (Keap tag IDs, comma-separated) is handled automatically.
4. Log
Browse incoming requests and outgoing Keap calls, filter by status or search term, and open any correlation to see the grouped request/response details.
Endpoint usage
Send a POST request with a JSON body:
curl -X POST "https://your-site.com/wp-json/keap-connect/v1/intake" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_BEARER_TOKEN" \
-d '{
"Nome": "Mario",
"Cognome": "Rossi",
"Email": "mario.rossi@example.com",
"Telefono": "+39 333 1234567",
"Tag": "103, 250"
}'
Example response:
{
"success": true,
"contact_id": "12345",
"message": "Contact created. Tags applied: 2.",
"correlation_id": "kc_20260605_120000_abcd1234"
}
Processing flow
- (Optional) Validate the Bearer token.
- Log the incoming body.
- Extract the email and search Keap:
GET /contacts?filter=email==<email>. - If no contact is found, create it:
POST /contacts. Otherwise update it:PATCH /contacts/{id}. - Apply each tag:
POST /tags/{tag_id}/contacts:applyTags. - Log the outcome and return a JSON response.
Token refresh / Cron
- A WP-Cron event runs every 6 hours and refreshes the OAuth access token (using the rotating refresh token). PAT/SAK never needs refreshing.
- If your site has WP-Cron disabled, enable External cron and hit the provided URL from a real cron job:
curl "https://your-site.com/wp-json/keap-connect/v1/cron?secret=YOUR_CRON_SECRET"
Updates from GitHub
The plugin uses Plugin Update Checker and reads releases from a GitHub repository.
-
Set your repository in the main plugin file:
define( 'KC_GITHUB_REPO', 'https://github.com/<user>/<repo>/' ); -
Commit the whole plugin, including the
vendor/folder. -
To publish an update: bump the
Version:header (andKC_VERSION), commit, and create a GitHub Release with a tag such asv1.0.1. WordPress will then offer the update.
For a private repository, define a token in wp-config.php:
define( 'KC_GITHUB_TOKEN', 'ghp_xxx' );
Security
Secret encryption at rest
Sensitive credentials are never stored in clear text in the database:
- Encrypted (reversible) — needed to call Keap:
client_id,client_secret,access_token,refresh_token,pat_token. Encrypted with libsodium (sodium_crypto_secretbox, XSalsa20-Poly1305), with an OpenSSL AES-256-GCM fallback. - Hashed (one-way) — only used for comparison: the Bearer token and the external cron secret. The database stores only an HMAC-SHA256, so they cannot be recovered, even with the key. Their clear value is shown only once, right after generation.
The encryption key is not stored in the database.
Recommended: dedicated key
By default the key is derived from the WordPress salts. For maximum robustness (so secrets do not break if you rotate the WordPress salts), define a dedicated key in wp-config.php:
define( 'KC_ENCRYPTION_KEY', 'PASTE_A_64_HEX_CHARACTER_KEY_HERE' );
Generate a 32-byte (64 hex) key with any of:
openssl rand -hex 32
# or
php -r 'echo bin2hex(random_bytes(32)), "\n";'
Or simply try from the admin area and if the wp-config.php is writable (It shouldn't be and it shouldn't even be under the same owner as the webserver) it will try ot show the snippet
Notes:
- A value of exactly 64 hexadecimal characters is used as the raw 32-byte key; any other string is hashed to 32 bytes.
- If the key changes or is lost, encrypted Keap credentials become unreadable and must be re-entered (OAuth reconnected); the Bearer/cron secrets can simply be regenerated.
- Protect backups of
wp-config.phpas carefully as the database. - Existing installs are migrated automatically: legacy clear-text secrets are hashed/encrypted on first load.
Other measures
- Admin pages require the
manage_optionscapability and use nonces; secrets are masked in logs. - The intake endpoint can require a Bearer token (recommended); failed attempts are throttled.
- Logged request/response bodies are size-capped, and the cron secret can be sent via the
X-KC-Cron-Secretheader instead of the query string.
Uninstall / data removal
Deleting the plugin runs uninstall.php, which removes every trace it stores in the database:
- All plugin options (
kc_settings,kc_field_map,kc_keap_model,kc_source,kc_db_version,kc_secrets_migrated) plus a safety sweep of anykc_*option/transient. - Fixed and per-user transients (
kc_oauth_state,kc_notify_rate,kc_show_bearer_*,kc_show_cron_*,kc_enc_snippet_*, etc.). - The custom log table (
{prefix}kc_logs). - Scheduled cron events (
kc_refresh_oauth) and the Plugin Update Checker artifacts (external_updates-<slug>option,puc_cron_check_updates-<slug>cron, related site transient).
Manual step: the KC_ENCRYPTION_KEY constant added to wp-config.php is not removed automatically (editing wp-config.php during uninstall is unsafe). If you defined it, delete that line manually after uninstalling.
Internationalization
- Source strings are in English; the text domain is
keap-connect. - Translation files live in
languages/:keap-connect.pot— template.keap-connect-it_IT.po/.mo— Italian translation.
The interface follows the WordPress Site Language (Settings → General) or the user's profile language. To add another language, copy the .pot, translate it, and compile:
msgfmt -o languages/keap-connect-<locale>.mo languages/keap-connect-<locale>.po
File structure
plugin_keap/
├── keap-connect.php # Bootstrap, constants, updater
├── uninstall.php # Cleanup on uninstall
├── readme.txt # WordPress-style readme
├── includes/
│ ├── class-kc-settings.php # Options storage & helpers
│ ├── class-kc-admin.php # Admin UI (4 tabs)
│ ├── class-kc-auth.php # OAuth + PAT/SAK with fallback
│ ├── class-kc-keap-client.php # Keap REST v2 HTTP client
│ ├── class-kc-endpoint.php # Intake REST route
│ ├── class-kc-mapper.php # Body -> Keap payload
│ ├── class-kc-processor.php # Orchestration
│ ├── class-kc-logger.php # Log table & queries
│ ├── class-kc-notifier.php # Email notifications (wp_mail)
│ ├── class-kc-crypto.php # Secret encryption / hashing
│ └── class-kc-cron.php # 6h refresh + external cron
├── admin/assets/ # CSS & JS
├── languages/ # .pot / .po / .mo
└── vendor/plugin-update-checker/ # GitHub update library
License
GPL-2.0-or-later. Built by Ratne.
Releases
6 releases.
These releases are tags only. The author does not attach a packaged zip, so there are no download counts to report.