=== Contesimal Connector ===

Contributors: wondermentkirpal,contesimal
Tags: rest api, publishing, content, post types, categories
Requires at least: 5.9
Tested up to: 6.9
Requires PHP: 7.4
Stable tag: 1.0.2
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Publish content to WordPress from external applications via a secure REST API using API key authentication.

== Description ==

Contesimal Connector adds REST API endpoints to your WordPress site, allowing external applications to create and manage content using an API key.

Requests are made to your site’s `/wp-json/contesimal/v1/` endpoints. The plugin does not send any data externally on its own.

**External services and privacy**

* **Service:** Designed to work with Contesimal (https://contesimal.ai), but compatible with any client using your API key.
* **Data received:** Post title, content (HTML), excerpt, status, categories, tags, post type, author ID, and media URLs. The optional users endpoint returns public-style author fields (ID, display name, slug) for users who can edit posts—no passwords or email.
* **Media handling:** Your WordPress site may download remote files from provided URLs to create Media Library attachments.
* **When:** Only when a valid API request is sent to your site. No background communication occurs.
* **Control:** External access is enabled only if you share the API key. You can regenerate the key or deactivate the plugin at any time.
* **Consent:** By enabling the plugin and sharing the API key, the site administrator allows external applications to submit content.

**Authentication**

All endpoints require an API key sent in the `X-API-Key` header (or `Authorization: Bearer`).

The key is:
- Generated on your site
- Stored as a secure hash
- Managed by administrators only

Requests without a valid key are rejected (401). Rate limiting is applied per IP.

API keys should be treated as sensitive credentials and only shared with trusted systems.

**Features**

* API key authentication (hashed storage)
* Create posts via REST API
* List categories, post types, and author-capable users (IDs for `author_id`)
* Media import from external URLs
* Rate limiting (per IP)
* Configurable CORS
* Optional request logging (admin only)

**REST endpoints (base: `/wp-json/contesimal/v1`)**

* `GET /ping` – Health check
* `GET /categories` – List categories
* `GET /post-types` – List public post types
* `GET /users` – List users with `edit_posts` (optional `session_only`, `search`, `limit`)
* `GET /posts` – List posts by post type with pagination and total count
* `POST /publish` – Create post
* `POST /media/import` – Import media from URLs

An admin notice is shown when API access is enabled, indicating that external publishing is active.

== Installation ==

1. Upload the plugin to `/wp-content/plugins/` or install via Plugins screen.
2. Activate the plugin (API key is generated).
3. Go to **Settings → Contesimal Connector** and copy your API key.
4. Configure rate limiting, CORS, and logging if needed.
5. Use the API key in requests via the `X-API-Key` header.

== REST API Reference ==

All endpoints require: `X-API-Key: your_api_key`

= GET /wp-json/contesimal/v1/ping =

Returns plugin status.

**Response:**
{ "status": "ok", "plugin": "contesimal-connector", "version": "1.0.0" }

= GET /wp-json/contesimal/v1/categories =

Returns category list.

= GET /wp-json/contesimal/v1/post-types =

Returns public post types.

= GET /wp-json/contesimal/v1/users =

Returns users who can author posts (`edit_posts`), suitable for `author_id` on `POST /publish`.

**Query parameters (all optional):**

| Parameter | Description |
|-----------|-------------|
| search | Substring match on login, nicename, or display name |
| session_only | `1` to only include users with stored WordPress session tokens (typically logged in recently) |
| limit | Max results, 1–200 (default 200) |

**Response (example):**
{ "success": true, "users": [ { "id": 1, "name": "Site Admin", "slug": "admin" } ] }

= GET /wp-json/contesimal/v1/posts =

Returns a paginated list of posts for a given post type, plus the total count for that filter.

**Query parameters (all optional):**

| Parameter | Description |
|-----------|-------------|
| post_type | Public post type (default `post`) |
| per_page | 1–100, default 50 |
| offset | Number of posts to skip (default 0) |
| status | Comma-separated status list (default `publish`), or `any` |
| search | Optional keyword across title/content |

**Response (example):**
{ "success": true, "post_type": "post", "total": 124, "per_page": 50, "offset": 0, "count": 50, "posts": [ { "post_id": 42, "title": "Hello world", "slug": "hello-world", "status": "publish", "date": "2026-05-14T11:50:00+00:00", "author_name": "Site Admin", "link": "https://example.com/hello-world/", "featured_image": "https://example.com/wp-content/uploads/2026/05/cover.jpg", "featured_image_id": 99, "categories": [ "News", "Updates" ], "tags": [ "Announcement", "WordPress" ], "content": "<!-- wp:paragraph --><p>Hello</p><!-- /wp:paragraph -->" } ] }

= POST /wp-json/contesimal/v1/publish =

Creates a post.

**Headers:**
Content-Type: application/json  
X-API-Key: your_api_key

**Body:**

| Field | Type | Required | Description |
|------|------|----------|-------------|
| title | string | Yes | Post title |
| content | string | Yes | HTML content |
| status | string | No | publish, draft, pending, private |
| excerpt | string | No | Post excerpt |
| post_type | string | No | Default: post |
| category_ids | array | No | Category IDs |
| tags | array | No | Tag names |
| featured_image_url | string | No | Image URL |
| author_id | integer | No | Default: 1 |

**Responses:**
- 200 Success
- 400 Bad request
- 401 Invalid API key
- 429 Rate limit exceeded
- 500 Server error

== Frequently Asked Questions ==

= Does the plugin send data externally? =

No. The plugin only receives data via API requests made to your site.

= Who can use the API? =

Only external applications with your API key.

= Where is the API key managed? =

In **Settings → Contesimal Connector**. It is shown once and stored securely as a hash.

= Is this GPL compatible? =

Yes, GPL v2 or later.

== Changelog ==

= 1.0.2 =
* Add `GET /posts` to list posts by post type with pagination, total count, featured image, categories, and tags

= 1.0.1 =
* Add `GET /users` to list author-capable users (ID, name, slug); optional `session_only` for users with active sessions

= 1.0.0 =
* Initial stable release
* REST API for publishing, categories, post types, and media import
* API key authentication with hashed storage
* Rate limiting, CORS, and optional logging
* Admin notice for external publishing awareness

== Upgrade Notice ==

= 1.0.2 =
Adds `GET /wp-json/contesimal/v1/posts` with pagination and total count for any public post type.

= 1.0.1 =
Adds `GET /wp-json/contesimal/v1/users` for listing author-capable user IDs.

= 1.0.0 =
Initial release.