=== SearchFIT ===
Contributors: searchfitai
Donate link: https://searchfit.ai
Tags: seo, ai, content automation, webhook, api
Requires at least: 5.0
Tested up to: 6.9
Requires PHP: 7.4
Stable tag: 1.3.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Secure REST webhook to publish posts to WordPress from AI tools, automation pipelines, or custom apps.

== Description ==

SearchFIT exposes a REST endpoint that lets you create, update, and list posts using an API key. Designed for AI content workflows (ChatGPT, Claude, Perplexity), no-code automation (Zapier, Make, n8n), and headless setups.

= Features =

* Auto-generated cryptographic API key with one-click regeneration
* Create, list, read, and update posts via REST
* Slug-based upsert — re-publishing the same slug updates the existing post instead of duplicating
* Featured images and inline content images downloaded from URLs you supply
* Category and tag management (creates missing categories on the fly)
* Custom post meta with a denylist for WordPress-internal keys
* SEO meta sync to Yoast SEO, Rank Math, SEOPress, and All in One SEO
* Multilingual support via Polylang and WPML
* JSON-LD `<script>` blocks extracted, validated, and re-emitted in `<head>`
* Optional embed allowlist for YouTube / Vimeo / SoundCloud / Spotify / Loom / TikTok / Apple Podcasts / Dailymotion
* Settings UI for default post status, author, category, tags, embeds, hero deduplication
* Health check endpoint and activity log

= Security =

* Cryptographic API key (`random_bytes`) with timing-safe comparison
* SSRF guard — outbound URL fetches reject private, loopback, link-local, and reserved IPs (IPv4 and IPv6)
* Custom-meta denylist blocks attempts to write `_edit_lock`, `_thumbnail_id`, `_wp_*` and other WP internals
* Iframes are off by default; when enabled, restricted to a strict host allowlist and src forced to https
* JSON-LD payloads are JSON-validated and re-encoded with `JSON_HEX_TAG` flags before storage
* Settings save flows through the WordPress Settings API (CSRF nonce + sanitize callbacks)
* 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

== Installation ==

1. Install and activate the plugin.
2. Open **SearchFIT** in the admin menu and copy the API key and webhook URL.
3. Send a `POST` to `/wp-json/searchfit/v1/articles` with `X-API-Key: <your key>` and a JSON body.

== Frequently Asked Questions ==

= How do I get my API key? =
Open the SearchFIT admin page. The key is generated automatically on activation and displayed there.

= Can I regenerate the key? =
Yes — click *Regenerate API Key*. The old key stops working immediately, so update integrations first.

= Which post statuses are supported? =
`draft`, `pending`, `publish`. Default is `draft` (configurable in settings).

= How do featured images work? =
Send `featured_image_url` (string) or a `featured_image` 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.

= Can I use this with AI tools? =
Yes — any tool that can make an HTTP request: ChatGPT, Claude, Perplexity, Gemini, Zapier, Make, n8n, custom scripts, etc.

= What happens to categories that don't exist? =
They're created automatically. You can also pass existing category IDs.

= Does it support custom post types? =
Not yet — it creates standard posts only.

= Can I set custom meta fields? =
Yes, via the `meta` field. Underscore-prefixed keys are rejected unless you explicitly allow them through the `searchfit_allow_meta_key` filter — this prevents writes to WordPress internals like `_edit_lock` or `_thumbnail_id`.

= Is there a rate limit? =
No application-level rate limit. Your host or WAF may enforce one.

= How do I send updates? =
`POST /wp-json/searchfit/v1/articles/{id}` (POST, not PUT — many WAFs block non-GET/POST methods). Or include a `slug` in the create request to upsert by slug.

= Where can I get support? =
[searchfit.ai](https://searchfit.ai) or the WordPress.org support forum.

== Screenshots ==

1. Dashboard with API credentials and copy buttons.
2. In-app API documentation panel.
3. Endpoint reference.
4. Request parameter reference.
5. Webhook defaults settings card.

== Changelog ==

= 1.3.0 =
* Security: SSRF guard rejects URL fetches that resolve to private/loopback/link-local/reserved IPs (IPv4 and IPv6).
* Security: Custom-meta denylist for `_searchfit_*`, `_edit_lock`, `_thumbnail_id`, and other WordPress-internal keys.
* Security: Iframes opt-in (off by default) with a strict host allowlist; non-allowlisted iframes stripped, https forced on the rest.
* Security: JSON-LD scripts JSON-validated and re-encoded with `JSON_HEX_TAG` flags before storage and `<head>` injection.
* New: Slug-based upsert — `POST /articles` with a `slug` matching an existing post updates it instead of duplicating.
* New: SEO meta sync to Yoast, Rank Math, SEOPress, and AIOSEO via new `meta_description` and `keywords` fields.
* New: Multilingual support via Polylang `pll_set_post_language()` and WPML's `wpml_set_element_language_details` action.
* New: HTML normalization (`balanceTags`, fix `<p><div>` nesting, drop stray `</a>`).
* New: Settings UI for default post status, author, category, tags, embeds, hero deduplication — all via the WordPress Settings API.
* Fix: Removed double-upload of inline content images.

= 1.2.0 =
* WAF compatibility: API key validated inside each handler instead of in `permission_callback`.
* WAF compatibility: Update endpoint accepts `POST` instead of `PUT`/`PATCH` (breaking change for callers that used `PUT`/`PATCH`).
* WAF compatibility: Health check endpoint is now public.
* `X-API-Key` is now the recommended auth header (`X-SearchFIT-API-Key` and `Authorization: Bearer` still accepted).

= 1.1.1 =
* Updated plugin logo and icons.

= 1.1.0 =
* Full CRUD API: list, read, create, update articles.
* Filtering by status / author / search; sorting; pagination.
* Featured image by `attachment_id` to reuse existing media.
* Custom meta fields and configurable default author.

= 1.0.0 =
* Initial release: webhook article creation, API key auth, featured + content images, categories, tags, draft/pending/publish, health check, activity log.

== Upgrade Notice ==

= 1.3.0 =
Security hardening (SSRF guard, meta denylist, scoped iframe allowlist, JSON-LD validation) plus slug upsert, SEO sync, multilingual, defaults UI. Recommended.

= 1.2.0 =
WAF compatibility fixes. BREAKING: update endpoint is now `POST` instead of `PUT`/`PATCH` — switch your callers.

= 1.1.1 =
Refreshed logo and icons.

= 1.1.0 =
Adds full CRUD with filtering and pagination.

= 1.0.0 =
Initial release.

== API Reference ==

Full docs at [searchfit.ai/docs](https://searchfit.ai/docs). Quick example:

`
curl -X POST "https://yoursite.com/wp-json/searchfit/v1/articles" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: YOUR_API_KEY" \
  -d '{
    "title": "My AI-Generated Article",
    "slug": "my-ai-article",
    "content": "<p>Your content here...</p>",
    "status": "draft",
    "categories": ["AI", "Technology"],
    "tags": ["ai-content", "automation"],
    "meta_description": "Short SEO description.",
    "featured_image_url": "https://example.com/image.jpg"
  }'
`

== Privacy Policy ==

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.
