{"id":279584,"date":"2026-02-18T11:23:42","date_gmt":"2026-02-18T11:23:42","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/searchfit\/"},"modified":"2026-07-01T23:20:31","modified_gmt":"2026-07-01T23:20:31","slug":"searchfit","status":"publish","type":"plugin","link":"https:\/\/co.wordpress.org\/plugins\/searchfit\/","author":23445691,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.4.0","stable_tag":"1.4.0","tested":"6.9.4","requires":"5.0","requires_php":"7.4","requires_plugins":null,"header_name":"SearchFIT","header_author":"SearchFIT","header_description":"Automate your WordPress content with AI. Receive articles via secure webhook API to create posts with images, categories, and tags. Perfect for ChatGPT, Claude, and AI content workflows.","assets_banners_color":"567aff","last_updated":"2026-07-01 23:20:31","external_support_url":"","external_repository_url":"","donate_link":"https:\/\/searchfit.ai","header_plugin_uri":"https:\/\/searchfit.ai\/extensions\/wordpress","header_author_uri":"https:\/\/searchfit.ai","rating":0,"author_block_rating":0,"active_installs":0,"downloads":388,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.1.0":{"tag":"1.1.0","author":"searchfitai","date":"2026-02-18 11:24:22"},"1.3.0":{"tag":"1.3.0","author":"searchfitai","date":"2026-05-14 02:45:10"},"1.4.0":{"tag":"1.4.0","author":"searchfitai","date":"2026-07-01 23:20:31"}},"upgrade_notice":{"1.4.0":"<p>Adds bulk CSV import \u2014 upload a SearchFIT content-export CSV from the admin screen (with preview, slug-matched upsert, and batched progress) alongside the existing webhook. UI consistency fixes. Recommended.<\/p>","1.3.0":"<p>Security hardening (SSRF guard, meta denylist, scoped iframe allowlist, JSON-LD validation) plus slug upsert, SEO sync, multilingual, defaults UI. Recommended.<\/p>","1.2.0":"<p>WAF compatibility fixes. BREAKING: update endpoint is now <code>POST<\/code> instead of <code>PUT<\/code>\/<code>PATCH<\/code> \u2014 switch your callers.<\/p>","1.1.1":"<p>Refreshed logo and icons.<\/p>","1.1.0":"<p>Adds full CRUD with filtering and pagination.<\/p>","1.0.0":"<p>Initial release.<\/p>"},"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3531508,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3531508,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500.jpg":{"filename":"banner-1544x500.jpg","revision":3464262,"resolution":"1544x500","location":"assets","locale":"","width":3088,"height":1000},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3464262,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.1.0","1.3.0","1.4.0"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3464262,"resolution":"1","location":"assets","locale":"","width":1024,"height":800},"screenshot-2.png":{"filename":"screenshot-2.png","revision":3464262,"resolution":"2","location":"assets","locale":"","width":1024,"height":800},"screenshot-3.png":{"filename":"screenshot-3.png","revision":3464262,"resolution":"3","location":"assets","locale":"","width":1024,"height":801}},"screenshots":{"1":"Dashboard with API credentials and copy buttons.","2":"In-app API documentation panel.","3":"Endpoint reference."}},"plugin_section":[],"plugin_tags":[2353,1556,181641,186,15439],"plugin_category":[55],"plugin_contributors":[256099],"plugin_business_model":[],"class_list":["post-279584","plugin","type-plugin","status-publish","hentry","plugin_tags-ai","plugin_tags-api","plugin_tags-content-automation","plugin_tags-seo","plugin_tags-webhook","plugin_category-seo-and-marketing","plugin_contributors-searchfitai","plugin_committers-searchfitai"],"banners":{"banner":"https:\/\/ps.w.org\/searchfit\/assets\/banner-772x250.png?rev=3464262","banner_2x":"https:\/\/ps.w.org\/searchfit\/assets\/banner-1544x500.jpg?rev=3464262","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/searchfit\/assets\/icon-128x128.png?rev=3531508","icon_2x":"https:\/\/ps.w.org\/searchfit\/assets\/icon-256x256.png?rev=3531508","generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/searchfit\/assets\/screenshot-1.png?rev=3464262","caption":"Dashboard with API credentials and copy buttons."},{"src":"https:\/\/ps.w.org\/searchfit\/assets\/screenshot-2.png?rev=3464262","caption":"In-app API documentation panel."},{"src":"https:\/\/ps.w.org\/searchfit\/assets\/screenshot-3.png?rev=3464262","caption":"Endpoint reference."}],"raw_content":"<!--section=description-->\n<p>SearchFIT gives you two ways to get content into WordPress. <strong>Webhook mode<\/strong> exposes a REST endpoint that lets you create, update, and list posts using an API key \u2014 accepting an incoming payload as-is. <strong>Import mode<\/strong> lets an administrator bulk-import a SearchFIT content-export CSV straight from the admin screen. Designed for AI content workflows (ChatGPT, Claude, Perplexity), no-code automation (Zapier, Make, n8n), and headless setups.<\/p>\n\n<h4>Features<\/h4>\n\n<ul>\n<li>Two ingestion modes: accept an incoming webhook payload as-is, or bulk-import a SearchFIT content-export CSV<\/li>\n<li>Bulk CSV import with Markdown-to-HTML conversion, processed in batches with a live progress bar<\/li>\n<li>Slug-matched import \u2014 re-importing the same CSV updates existing posts instead of duplicating<\/li>\n<li>Auto-generated cryptographic API key with one-click regeneration<\/li>\n<li>Create, list, read, and update posts via REST<\/li>\n<li>Slug-based upsert \u2014 re-publishing the same slug updates the existing post instead of duplicating<\/li>\n<li>Featured images and inline content images downloaded from URLs you supply<\/li>\n<li>Category and tag management (creates missing categories on the fly)<\/li>\n<li>Custom post meta with a denylist for WordPress-internal keys<\/li>\n<li>SEO meta sync to Yoast SEO, Rank Math, SEOPress, and All in One SEO<\/li>\n<li>Multilingual support via Polylang and WPML<\/li>\n<li>JSON-LD <code>&lt;script&gt;<\/code> blocks extracted, validated, and re-emitted in <code>&lt;head&gt;<\/code><\/li>\n<li>Optional embed allowlist for YouTube \/ Vimeo \/ SoundCloud \/ Spotify \/ Loom \/ TikTok \/ Apple Podcasts \/ Dailymotion<\/li>\n<li>Settings UI for default post status, author, category, tags, embeds, hero deduplication<\/li>\n<li>Health check endpoint and activity log<\/li>\n<\/ul>\n\n<h4>Security<\/h4>\n\n<ul>\n<li>Cryptographic API key (<code>random_bytes<\/code>) with timing-safe comparison<\/li>\n<li>SSRF guard \u2014 outbound URL fetches reject private, loopback, link-local, and reserved IPs (IPv4 and IPv6)<\/li>\n<li>Custom-meta denylist blocks attempts to write <code>_edit_lock<\/code>, <code>_thumbnail_id<\/code>, <code>_wp_*<\/code> and other WP internals<\/li>\n<li>Iframes are off by default; when enabled, restricted to a strict host allowlist and src forced to https<\/li>\n<li>JSON-LD payloads are JSON-validated and re-encoded with <code>JSON_HEX_TAG<\/code> flags before storage<\/li>\n<li>Settings save flows through the WordPress Settings API (CSRF nonce + sanitize callbacks)<\/li>\n<li>WAF-friendly: auth runs inside handlers (so failed requests don't trigger Wordfence\/Sucuri lockout heuristics); POST-only methods (no PUT\/PATCH); public health endpoint<\/li>\n<\/ul>\n\n<h3>API Reference<\/h3>\n\n<p>Full docs at <a href=\"https:\/\/searchfit.ai\/docs\">searchfit.ai\/docs<\/a>. Quick example:<\/p>\n\n<pre><code>curl -X POST \"https:\/\/yoursite.com\/wp-json\/searchfit\/v1\/articles\" \\\n  -H \"Content-Type: application\/json\" \\\n  -H \"X-API-Key: YOUR_API_KEY\" \\\n  -d '{\n    \"title\": \"My AI-Generated Article\",\n    \"slug\": \"my-ai-article\",\n    \"content\": \"&lt;p&gt;Your content here...&lt;\/p&gt;\",\n    \"status\": \"draft\",\n    \"categories\": [\"AI\", \"Technology\"],\n    \"tags\": [\"ai-content\", \"automation\"],\n    \"meta_description\": \"Short SEO description.\",\n    \"featured_image_url\": \"https:\/\/example.com\/image.jpg\"\n  }'\n<\/code><\/pre>\n\n<h3>Privacy Policy<\/h3>\n\n<p>SearchFIT does not collect or transmit any personal data. API keys and the webhook activity log are stored in the WordPress database and never sent to external servers.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Install and activate the plugin.<\/li>\n<li>Open <strong>SearchFIT<\/strong> in the admin menu and copy the API key and webhook URL.<\/li>\n<li><strong>Webhook mode:<\/strong> send a <code>POST<\/code> to <code>\/wp-json\/searchfit\/v1\/articles<\/code> with <code>X-API-Key: &lt;your key&gt;<\/code> and a JSON body.<\/li>\n<li><strong>Import mode:<\/strong> scroll to <strong>Bulk Import from CSV<\/strong>, drop in a SearchFIT content-export CSV, review the preview table, and click <strong>Start Import<\/strong>.<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"what%27s%20the%20difference%20between%20the%20two%20modes%3F\"><h3>What's the difference between the two modes?<\/h3><\/dt>\n<dd><p><strong>Webhook mode<\/strong> receives content pushed to your site over the REST API in real time \u2014 ideal for automated pipelines. <strong>Import mode<\/strong> is a one-off bulk operation: you upload a SearchFIT content-export CSV from the admin screen and it creates the posts. Both produce ordinary WordPress posts and share the same defaults (category, tags, author).<\/p><\/dd>\n<dt id=\"what%20format%20is%20the%20csv%2C%20and%20how%20are%20columns%20mapped%3F\"><h3>What format is the CSV, and how are columns mapped?<\/h3><\/dt>\n<dd><p>It's the SearchFIT content export. Expected columns: Title, Slug, Type, Status, Locale, Target Keyword, Meta Description, Word Count, Read Time (min), Article Score, Keyword Difficulty, Search Volume, Scheduled Date, Content. Title \u2192 post title, Slug \u2192 post slug, Content \u2192 post body, Meta Description + Target Keyword \u2192 SEO fields (synced to Yoast \/ Rank Math \/ SEOPress \/ AIOSEO), Locale \u2192 language (via Polylang\/WPML). The remaining analytical columns are stored as <code>searchfit_*<\/code> post meta so nothing is lost. Only Title and Content are strictly required.<\/p><\/dd>\n<dt id=\"do%20i%20need%20to%20choose%20a%20content%20format%20when%20importing%3F\"><h3>Do I need to choose a content format when importing?<\/h3><\/dt>\n<dd><p>No. SearchFIT exports the Content column as Markdown, so the importer converts it to clean post HTML for you automatically \u2014 there's nothing to configure.<\/p><\/dd>\n<dt id=\"what%20happens%20on%20re-import%2C%20or%20if%20a%20slug%20already%20exists%3F\"><h3>What happens on re-import, or if a slug already exists?<\/h3><\/dt>\n<dd><p>Rows are matched to existing posts by slug. You choose whether a match <strong>updates<\/strong> the existing post (safe to re-run) or is <strong>skipped<\/strong>. Newly created posts also receive the category, tags, and author from your Webhook Defaults (each overridable per-import).<\/p><\/dd>\n<dt id=\"how%20are%20statuses%20and%20scheduled%20dates%20handled%3F\"><h3>How are statuses and scheduled dates handled?<\/h3><\/dt>\n<dd><p>You can keep the CSV's status or force everything to draft\/pending\/publish. When keeping the CSV status, a <code>scheduled<\/code> row with a future date becomes a genuine WordPress scheduled post; a past date publishes at that date.<\/p><\/dd>\n<dt id=\"is%20the%20csv%20import%20safe%20on%20large%20files%3F\"><h3>Is the CSV import safe on large files?<\/h3><\/dt>\n<dd><p>Yes. The file is parsed once, then imported in small AJAX batches with a live progress bar, so it won't hit PHP's execution-time limit. You see a preview of the first rows before anything is written.<\/p><\/dd>\n<dt id=\"how%20do%20i%20get%20my%20api%20key%3F\"><h3>How do I get my API key?<\/h3><\/dt>\n<dd><p>Open the SearchFIT admin page. The key is generated automatically on activation and displayed there.<\/p><\/dd>\n<dt id=\"can%20i%20regenerate%20the%20key%3F\"><h3>Can I regenerate the key?<\/h3><\/dt>\n<dd><p>Yes \u2014 click <em>Regenerate API Key<\/em>. The old key stops working immediately, so update integrations first.<\/p><\/dd>\n<dt id=\"which%20post%20statuses%20are%20supported%3F\"><h3>Which post statuses are supported?<\/h3><\/dt>\n<dd><p>draft, <code>pending<\/code>, <code>publish<\/code>. Default is <code>draft<\/code> (configurable in settings).<\/p><\/dd>\n<dt id=\"how%20do%20featured%20images%20work%3F\"><h3>How do featured images work?<\/h3><\/dt>\n<dd><p>Send <code>featured_image_url<\/code> (string) or a <code>featured_image<\/code> object with metadata. The plugin downloads the image, adds it to the Media Library, and sets it as the featured image. URLs that resolve to private\/loopback IPs are rejected.<\/p><\/dd>\n<dt id=\"can%20i%20use%20this%20with%20ai%20tools%3F\"><h3>Can I use this with AI tools?<\/h3><\/dt>\n<dd><p>Yes \u2014 any tool that can make an HTTP request: ChatGPT, Claude, Perplexity, Gemini, Zapier, Make, n8n, custom scripts, etc.<\/p><\/dd>\n<dt id=\"what%20happens%20to%20categories%20that%20don%27t%20exist%3F\"><h3>What happens to categories that don't exist?<\/h3><\/dt>\n<dd><p>They're created automatically. You can also pass existing category IDs.<\/p><\/dd>\n<dt id=\"does%20it%20support%20custom%20post%20types%3F\"><h3>Does it support custom post types?<\/h3><\/dt>\n<dd><p>Not yet \u2014 it creates standard posts only.<\/p><\/dd>\n<dt id=\"can%20i%20set%20custom%20meta%20fields%3F\"><h3>Can I set custom meta fields?<\/h3><\/dt>\n<dd><p>Yes, via the <code>meta<\/code> field. Underscore-prefixed keys are rejected unless you explicitly allow them through the <code>searchfit_allow_meta_key<\/code> filter \u2014 this prevents writes to WordPress internals like <code>_edit_lock<\/code> or <code>_thumbnail_id<\/code>.<\/p><\/dd>\n<dt id=\"is%20there%20a%20rate%20limit%3F\"><h3>Is there a rate limit?<\/h3><\/dt>\n<dd><p>No application-level rate limit. Your host or WAF may enforce one.<\/p><\/dd>\n<dt id=\"how%20do%20i%20send%20updates%3F\"><h3>How do I send updates?<\/h3><\/dt>\n<dd><p>POST \/wp-json\/searchfit\/v1\/articles\/{id} (POST, not PUT \u2014 many WAFs block non-GET\/POST methods). Or include a <code>slug<\/code> in the create request to upsert by slug.<\/p><\/dd>\n<dt id=\"where%20can%20i%20get%20support%3F\"><h3>Where can I get support?<\/h3><\/dt>\n<dd><p><a href=\"https:\/\/searchfit.ai\">searchfit.ai<\/a> or the WordPress.org support forum.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.4.0<\/h4>\n\n<ul>\n<li>New: Bulk CSV import \u2014 a second ingestion mode alongside the webhook. Import a SearchFIT content-export CSV (Title, Slug, Type, Status, Locale, Target Keyword, Meta Description, Content, and more) directly from the admin screen, with a preview of the file before importing.<\/li>\n<li>New: SearchFIT exports the Content column as Markdown, so the importer converts it to clean post HTML automatically \u2014 no format choice to make.<\/li>\n<li>New: Self-contained Markdown-to-HTML converter (headings, links, images, bold\/italic, inline &amp; fenced code, blockquotes, ordered\/unordered lists, GitHub task lists, horizontal rules, and pipe tables).<\/li>\n<li>New: Imports are matched to existing posts by slug (update or skip), run in AJAX batches with a live progress bar, and can force a post status or preserve the CSV's scheduled dates.<\/li>\n<li>New: Webhook Defaults (default category, tags, and author) are now also applied to newly created posts during CSV import.<\/li>\n<li>New: SearchFIT export columns (Type, Word Count, Read Time, Article Score, Keyword Difficulty, Search Volume, Target Keyword, Locale, Scheduled Date) are stored as post meta; Meta Description and Target Keyword sync to Yoast \/ Rank Math \/ SEOPress \/ AIOSEO.<\/li>\n<li>UI: Consistent card corner radius across the admin screen and a single button style for all actions.<\/li>\n<\/ul>\n\n<h4>1.3.0<\/h4>\n\n<ul>\n<li>Security: SSRF guard rejects URL fetches that resolve to private\/loopback\/link-local\/reserved IPs (IPv4 and IPv6).<\/li>\n<li>Security: Custom-meta denylist for <code>_searchfit_*<\/code>, <code>_edit_lock<\/code>, <code>_thumbnail_id<\/code>, and other WordPress-internal keys.<\/li>\n<li>Security: Iframes opt-in (off by default) with a strict host allowlist; non-allowlisted iframes stripped, https forced on the rest.<\/li>\n<li>Security: JSON-LD scripts JSON-validated and re-encoded with <code>JSON_HEX_TAG<\/code> flags before storage and <code>&lt;head&gt;<\/code> injection.<\/li>\n<li>New: Slug-based upsert \u2014 <code>POST \/articles<\/code> with a <code>slug<\/code> matching an existing post updates it instead of duplicating.<\/li>\n<li>New: SEO meta sync to Yoast, Rank Math, SEOPress, and AIOSEO via new <code>meta_description<\/code> and <code>keywords<\/code> fields.<\/li>\n<li>New: Multilingual support via Polylang <code>pll_set_post_language()<\/code> and WPML's <code>wpml_set_element_language_details<\/code> action.<\/li>\n<li>New: HTML normalization (<code>balanceTags<\/code>, fix <code>&lt;p&gt;&lt;div&gt;<\/code> nesting, drop stray <code>&lt;\/a&gt;<\/code>).<\/li>\n<li>New: Settings UI for default post status, author, category, tags, embeds, hero deduplication \u2014 all via the WordPress Settings API.<\/li>\n<li>Fix: Removed double-upload of inline content images.<\/li>\n<\/ul>\n\n<h4>1.2.0<\/h4>\n\n<ul>\n<li>WAF compatibility: API key validated inside each handler instead of in <code>permission_callback<\/code>.<\/li>\n<li>WAF compatibility: Update endpoint accepts <code>POST<\/code> instead of <code>PUT<\/code>\/<code>PATCH<\/code> (breaking change for callers that used <code>PUT<\/code>\/<code>PATCH<\/code>).<\/li>\n<li>WAF compatibility: Health check endpoint is now public.<\/li>\n<li><code>X-API-Key<\/code> is now the recommended auth header (<code>X-SearchFIT-API-Key<\/code> and <code>Authorization: Bearer<\/code> still accepted).<\/li>\n<\/ul>\n\n<h4>1.1.1<\/h4>\n\n<ul>\n<li>Updated plugin logo and icons.<\/li>\n<\/ul>\n\n<h4>1.1.0<\/h4>\n\n<ul>\n<li>Full CRUD API: list, read, create, update articles.<\/li>\n<li>Filtering by status \/ author \/ search; sorting; pagination.<\/li>\n<li>Featured image by <code>attachment_id<\/code> to reuse existing media.<\/li>\n<li>Custom meta fields and configurable default author.<\/li>\n<\/ul>\n\n<h4>1.0.0<\/h4>\n\n<ul>\n<li>Initial release: webhook article creation, API key auth, featured + content images, categories, tags, draft\/pending\/publish, health check, activity log.<\/li>\n<\/ul>","raw_excerpt":"Secure REST webhook and bulk CSV importer to publish posts to WordPress from AI tools, automation pipelines, or custom apps.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/co.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/279584","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/co.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/co.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/co.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=279584"}],"author":[{"embeddable":true,"href":"https:\/\/co.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/searchfitai"}],"wp:attachment":[{"href":"https:\/\/co.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=279584"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/co.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=279584"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/co.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=279584"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/co.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=279584"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/co.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=279584"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/co.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=279584"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}