wp_update_post
Updates an existing post or page. For one or more specific content fragments, prefer edit_many: read the post first, dry-run the proposed edits, then save with the same content hash. edit_many changes content only and returns a compact receipt; update titles, status, and other fields in a separate call. For a user-requested author task, resolve the account with wp_find_users; never guess IDs or choose an ambiguous match. Read back successful author assignment with wp_read_post. Only the fields you provide will be changed. Do not use content on Elementor-managed pages; use wp_elementor_* tools for Elementor content/layout changes.
Tool call template
Replace each placeholder with a value matching the input schema. Only required parameters are included; add optional parameters as needed.
{
"id": 1,
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"arguments": {
"site_id": "<site_id>",
"id": "<id>"
},
"name": "wp_update_post"
}
}Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | The post ID to update. | |
| mode | No | replace accepts full content. edit changes one unique exact fragment and retains full before/after snapshots. edit_many changes one or more distinct, non-overlapping exact content fragments in one post and returns a compact receipt. Do not combine edit_many with title, status, or other post fields. Both edit modes require a fresh wp_read_post.content_sha256 as expected_current_sha256. Conflict detection is best-effort, not an atomic lock. Elementor content is not supported. | replace |
| slug | No | Optional permalink slug. Omit to retain the current slug, subject to WordPress status transitions. WordPress sanitizes it and applies uniqueness. Empty allows an empty draft/pending slug; published posts derive one from the title. See after.slug for the persisted value. | |
| tags | No | Existing tag term IDs. Supplied arrays replace assignments; empty clears tags. Omit on update to preserve. Never creates terms. Read IDs with wp_read_post. | |
| edits | No | edit_many only: distinct exact fragments from the original content. Each must occur exactly once, and matches must not overlap. | |
| title | No | New post title. | |
| author | No | Native WordPress account ID. Omit to preserve the current author. Requires author support; an explicit other account requires edit_others_posts even when unchanged. | |
| dryRun | No | edit_many only: validate and report exact match offsets and proposed hash without saving. Defaults to false; a later save rechecks the original content hash. | |
| status | No | New post status. | |
| content | No | New post content as HTML or block markup. | |
| excerpt | No | New post excerpt. | |
| newText | No | Required in edit mode only: replacement bytes, different from oldText. Empty deletes the fragment. | |
| oldText | No | Required in edit mode only: nonempty exact fragment from stored content, occurring exactly once. | |
| site_id | Yes | The connected site's id returned by list_sites. Call list_sites first; do not use a URL or WordPress post ID. | |
| template | No | Pages only: an available native page-template slug/file, or default to reset. Omit on update to preserve. Read the actual assignment in wp_read_post.template. | |
| categories | No | Existing category term IDs. Supplied arrays replace assignments; omit on update to preserve. Empty uses the WordPress default category for posts (and filtered default-category post types), except auto-drafts; otherwise clears. Never creates terms. Read IDs with wp_read_post. | |
| expected_current_sha256 | No | Required in edit and edit_many modes: lowercase SHA256 from a fresh wp_read_post.content_sha256. Any content change requires reading again. |