Skill: sebastiangansca/wordpress-content-rest-api (version 0.1.0)

--- name: wordpress-content-rest-api description: Use the WordPress REST API for content operations only: auth setup (Application Password and Bearer), safe read/write flows for posts/pages/media, draft/publish/update patterns, taxonomy assignment, pagination/search, retry/rate-limit handling, and dry-run-first safety. metadata: {"openclaw":{"emoji":"🧩"}} --- # WordPress Content REST API Use this skill only for WordPress content API work (posts, pages, media, categories, tags). Do not use it for server admin, plugin/theme management, or shell/WP-CLI tasks. ## Safety Rules (Always) 1. Start with a dry run before any write. 2. Confirm base URL and target environment (`production` vs `staging`). 3. Read current object first, then patch minimally. 4. Prefer `status=draft` until explicit approval to publish. 5. Avoid bulk destructive updates unless explicitly approved. 6. Use least-privilege credentials. Read [references/reliability-and-safety.md](references/reliability-and-safety.md) first when operating on live sites. ## Workflow 1. Set auth model (Application Password or Bearer): [references/auth.md](references/auth.md) 2. Discover and validate target content: use read/list endpoints with pagination and filters. 3. Execute dry-run pass: - fetch current object - prepare intended payload - verify taxonomy/media IDs exist 4. Write safely: - create/update as draft first - verify response - publish only with explicit instruction 5. Handle retries/rate-limits/errors using standard policy: [references/reliability-and-safety.md](references/reliability-and-safety.md) ## Endpoint Scope Focus on these route families: - `/wp-json/wp/v2/posts` - `/wp-json/wp/v2/pages` - `/wp-json/wp/v2/media` - `/wp-json/wp/v2/categories` - `/wp-json/wp/v2/tags` For usage patterns and payload examples, read: - [references/content-flows.md](references/content-flows.md) - [references/query-and-taxonomy.md](references/query-and-taxonomy.md) ## Default Execution Pattern - Read first (`GET`). - Validate dependent IDs (author/category/tag/media). - Write to draft (`POST`/`PUT`/`PATCH` with `status=draft`). - Re-read object and compare expected fields. - Publish (`status=publish`) only after explicit approval. ## Done Criteria Treat a content task as complete only when: - API response is successful and parsed. - Changed fields match requested outcome. - Final status (`draft`/`publish`) matches explicit instruction. - Any partial failures are listed with next action.

path: references/auth.md
content: # Auth Setup

Use HTTPS only.

## 1) Application Password (Preferred for service-to-service)

Use WordPress username + application password via Basic auth.

Example:
```bash
curl -sS -u "$WP_USER:$WP_APP_PASSWORD" \
  "$WP_SITE/wp-json/wp/v2/posts?per_page=5"
```

Rules:
- Use an account with minimum required capabilities.
- Rotate/revoke app passwords after incidents or role changes.
- Never log raw credentials.

## 2) Bearer Token (Site/plugin specific)

Use only when the site explicitly supports bearer auth (JWT/OAuth/custom gateway).

Example:
```bash
curl -sS -H "Authorization: Bearer $WP_BEARER_TOKEN" \
  "$WP_SITE/wp-json/wp/v2/pages?per_page=5"
```

Rules:
- Validate token issuer and expiry.
- Keep scopes narrow.
- Prefer short-lived tokens.

## Auth Selection

- Use Application Password by default.
- Use Bearer only when required by site policy or existing integration architecture.

## Preflight Check

Before writes:
1. Call a read endpoint (`/posts` or `/pages`).
2. Confirm auth works and returns expected visibility.
3. Confirm you are on the intended site URL.


path: references/content-flows.md
content: # Safe Read/Write Flows (Posts, Pages, Media)

## A) Read Flow

Use filters to reduce payload and improve reliability.

Examples:
```bash
# Find posts by search + status
curl -sS -u "$WP_USER:$WP_APP_PASSWORD" \
  "$WP_SITE/wp-json/wp/v2/posts?search=pricing&status=draft,publish&per_page=20&page=1"

# Fetch exact page
curl -sS -u "$WP_USER:$WP_APP_PASSWORD" \
  "$WP_SITE/wp-json/wp/v2/pages/123"
```

## B) Create Flow (Draft First)

```bash
curl -sS -u "$WP_USER:$WP_APP_PASSWORD" \
  -X POST "$WP_SITE/wp-json/wp/v2/posts" \
  -H "Content-Type: application/json" \
  -d '{
    "title":"New Article",
    "content":"<p>Draft body</p>",
    "status":"draft"
  }'
```

## C) Update Flow (Minimal Patch)

1. Read current object.
2. Change only required fields.
3. Send update.

```bash
curl -sS -u "$WP_USER:$WP_APP_PASSWORD" \
  -X POST "$WP_SITE/wp-json/wp/v2/pages/123" \
  -H "Content-Type: application/json" \
  -d '{
    "title":"Updated title",
    "status":"draft"
  }'
```

## D) Publish Pattern

Use only after explicit approval:

```bash
curl -sS -u "$WP_USER:$WP_APP_PASSWORD" \
  -X POST "$WP_SITE/wp-json/wp/v2/posts/456" \
  -H "Content-Type: application/json" \
  -d '{"status":"publish"}'
```

## E) Media Upload Pattern

```bash
curl -sS -u "$WP_USER:$WP_APP_PASSWORD" \
  -X POST "$WP_SITE/wp-json/wp/v2/media" \
  -H "Content-Disposition: attachment; filename=hero.jpg" \
  -H "Content-Type: image/jpeg" \
  --data-binary @hero.jpg
```

Then assign media ID as `featured_media` in post/page update.

## F) Delete Pattern

Avoid by default. Require explicit approval.
If needed, prefer moving content out of public state first (`draft`/`private`) before permanent delete operations.


path: references/query-and-taxonomy.md
content: # Taxonomy, Pagination, and Search

## Taxonomy Handling

Common taxonomy endpoints:
- `/wp-json/wp/v2/categories`
- `/wp-json/wp/v2/tags`

Assign taxonomy IDs on posts/pages:

```json
{
  "categories": [12, 19],
  "tags": [33, 47]
}
```

Rules:
- Resolve slug -> ID before write.
- Create missing taxonomy term only when explicitly requested.
- Avoid duplicate term creation caused by case/slug mismatch.

## Pagination

Use `page` + `per_page` and inspect headers:
- `X-WP-Total`
- `X-WP-TotalPages`

Pattern:
```bash
curl -i -sS -u "$WP_USER:$WP_APP_PASSWORD" \
  "$WP_SITE/wp-json/wp/v2/posts?per_page=50&page=1"
```

Stop paging when page > `X-WP-TotalPages`.

## Search and Filtering

Useful params:
- `search`
- `slug`
- `status`
- `categories`
- `tags`
- `orderby`
- `order`

For conflict-safe updates:
1. Search by slug/title.
2. If one clear match -> update.
3. If multiple matches -> pause and ask for disambiguation.


path: references/reliability-and-safety.md
content: # Error, Retry, Rate-Limit, and Dry-Run Rules

## Dry-Run First (Mandatory)

Before any write operation:
1. Validate auth with a read call.
2. Fetch target object (or candidate set).
3. Build intended payload and list field-level changes.
4. Validate dependencies (taxonomy/media IDs).
5. Proceed to write only after checks pass.

## Error Handling

Classify failures:
- `400/401/403`: payload/auth/permission issue -> fix input/auth; do not blind retry.
- `404`: wrong endpoint/object ID/environment mismatch.
- `409/412`: state conflict -> re-read object and retry with refreshed state.
- `429`: rate-limited -> back off and retry.
- `5xx`: transient server issue -> bounded retry.

Always capture:
- status code
- response body (sanitized)
- endpoint + method

## Retry Guidance

Retry only idempotent or safely repeatable calls.

Recommended backoff for retryable errors (`429`, `5xx`):
- up to 4 retries
- exponential delays: 1s, 2s, 4s, 8s
- add jitter if running parallel flows

Honor `Retry-After` when present.

## Rate-Limit Guidance

- Keep request bursts small.
- Prefer fewer larger reads (`per_page`) over many tiny calls.
- Serialize writes when content integrity matters.
- Pause bulk operations on repeated `429`.

## Write Safety Guards

- Default to `status=draft`.
- Publish only with explicit user approval.
- For bulk updates, process in batches and verify each batch.
- On first unexpected failure, halt and reassess before continuing.


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: clean (LOW)