Duplicate site (async)
const url = 'https://example.com/wp-json/wp2/site-duplicator/v1/sites/1/duplicate';const options = { method: 'POST', headers: {'X-WP-Nonce': '<X-WP-Nonce>', 'Content-Type': 'application/json'}, body: '{"title":"example","slug":"example","description":"example","status_id":1,"category_ids":[1]}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://example.com/wp-json/wp2/site-duplicator/v1/sites/1/duplicate \ --header 'Content-Type: application/json' \ --header 'X-WP-Nonce: <X-WP-Nonce>' \ --data '{ "title": "example", "slug": "example", "description": "example", "status_id": 1, "category_ids": [ 1 ] }'Enqueues a full duplicate of the given site. title and slug are required. Returns 202 with a job id. This does not create a blank site — use Site Manager POST /sites without source_blog_id for that.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”Network site ID. Optional on a single site.
Request Body
Section titled “Request Body”object
Title.
Slug (site, post, or section).
Field “description” as returned or accepted by PHP.
Site status ID.
Field “category_ids” as returned or accepted by PHP.
Examplegenerated
{ "title": "example", "slug": "example", "description": "example", "status_id": 1, "category_ids": [ 1 ]}Responses
Section titled “Responses”Job accepted
object
Job UUID (PlatformJob::$job_id). Site Manager GET returns 404 job_not_found if the type does not start with site_manager. or the row is missing.
Machine job type. Site Manager: site_manager.create_from_source, site_manager.bulk. Site Duplicator uses its own prefixes of the same PlatformJob.
Lifecycle status (pending / running / completed / failed; PHP may also return cancelled as terminal).
Current worker phase (short progress label, e.g. bulk), not an HTTP status.
Progress counters (percent / current / total) as the worker stored them in PlatformJob::$progress.
object
Percent complete 0–100, if the worker writes it.
How many units have been processed.
How many units in total (e.g. number of blog_ids in bulk).
Human-readable worker status (not a PIN and not a WP-CLI log).
Who enqueued the job. GET of another user’s job without manage_network — 403 forbidden. The jobs list returns only the current user’s jobs.
Network where the job was created. Another network — 404 job_not_in_network (message “Job not found.”).
Worker input (for bulk — blog_ids/action/patch/drop_tables; for create_from_source — source_blog_id and new-site fields).
object
Result after completed (for bulk — succeeded/failed/total/processed). null until the job finishes successfully.
object
Error on failed. PHP stores {code, message} in PlatformJob::$error; null if it did not fail.
Job created time (GMT, gmdate('c')).
Last progress/status update time.
Time of transition to a terminal status; null while the job is running.
Example
{ "status": "pending"}Headers
Section titled “Headers”Not authenticated. WordPress REST: rest_not_logged_in / rest_forbidden. Use cookie + X-WP-Nonce or Application Password.
object
Machine-readable error or event code.
Message text (log, PIN, or password reset).
Extra WP_Error or license payload.
object
Examplegenerated
{ "code": "example", "message": "example", "data": {}}Insufficient capability or invalid REST nonce. WordPress REST: rest_forbidden / rest_cookie_invalid_nonce.
object
Machine-readable error or event code.
Message text (log, PIN, or password reset).
Extra WP_Error or license payload.
object
Examplegenerated
{ "code": "example", "message": "example", "data": {}}