Массовые операции с сайтами
const url = 'https://example.com/wp-json/wp2/site-manager/v1/sites/bulk';const options = { method: 'POST', headers: {'X-WP-Nonce': '<X-WP-Nonce>', 'Content-Type': 'application/json'}, body: '{"blog_ids":[5,8],"action":"archive"}'};
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-manager/v1/sites/bulk \ --header 'Content-Type: application/json' \ --header 'X-WP-Nonce: <X-WP-Nonce>' \ --data '{ "blog_ids": [ 5, 8 ], "action": "archive" }'Применяет одну операцию ко всем blog_ids текущей сети: archive, unarchive, activate, deactivate, delete или patch.
До 10 сайтов включительно — синхронно 200 BulkSiteResult (ошибки отдельных сайтов в failed, HTTP всё равно 200). Больше 10 — очередь site_manager.bulk и 202.
Обязательны непустые blog_ids и непустой action, иначе 400 missing_fields. Нужно delete_sites или manage_network. Только multisite.
Authorizations
Заголовок раздела «Authorizations»Request Bodyrequired
Заголовок раздела «Request Bodyrequired»object
ID сайтов текущей сети. Обязательно; пустой массив — 400 missing_fields. Больше 10 элементов — фоновое задание 202 (BulkSiteService::SYNC_THRESHOLD).
Операция над каждым blog_id. Пустая строка — 400 missing_fields. Неизвестное значение в синхронном прогоне попадает в failed с кодом invalid_action, HTTP 200.
Тело метаданных для action=patch. Для archive/delete можно не передавать. PHP передаёт массив как есть в SiteMetadataPatch::from_array.
object
Новый blogname. Необязательно; отсутствие ключа — не менять. PHP делает sanitize_text_field и пишет опцию блога плюс site meta blogname.
Новый адресный ярлык. Необязательно. PHP нормализует и через domain_exists проверяет занятость; чужой сайт с тем же domain+path — 409 slug_conflict. Главный сайт сети — 403 main_site_slug_forbidden.
Новый blogdescription. Необязательно; PHP пишет sanitize_text_field в опцию блога.
ID статуса Site Manager или null, чтобы снять статус. Ключ должен быть передан (array_key_exists): иначе PHP статус не трогает. Несуществующий термин — 400 invalid_term.
Полный набор ID категорий сайта. Если ключ передан (даже пустой массив) — PHP перезаписывает meta. Каждый id должен быть термином категорий; иначе 400 invalid_term.
True — update_blog_status(..., archived, 1); false — снять архив. Главный сайт — 403 main_site_forbidden. Не путать с integer-флагом в SiteDto.
1 — активировать сайт (WP_Site->public=1); иначе деактивировать (0). Главный сайт — 403 main_site_forbidden.
Пишет site meta wp2platform_site_manager_is_template (1 или 0). Нужен ключ в JSON, иначе PHP флаг не меняет.
Только для action=delete: true — wpmu_delete_blog($id, true) (дроп таблиц сайта). Для остальных action PHP игнорирует.
Example
{ "blog_ids": [ 5, 8 ], "action": "archive"}Responses
Заголовок раздела «Responses»Синхронный прогон (≤10 сайтов). succeeded — ок, failed — WP_Error по сайту (main_site_forbidden и т.д.).
object
Blog_id, для которых операция прошла без WP_Error.
Сайты с ошибкой; общий HTTP-статус при синхронном bulk остаётся 200.
object
Сайт, на котором операция вернула WP_Error.
Код WP_Error (main_site_forbidden, invalid_action, slug_conflict и т.д.).
Текст WP_Error для этого сайта.
Example
{ "succeeded": [ 5, 8 ], "failed": []}Асинхронное задание (больше 10 сайтов). Location — poll_url, Retry-After=2.
object
UUID задания PlatformJob. Тот же id в GET /jobs/{job_id} и SSE /jobs/{job_id}/events.
Текущий статус задания на момент 202 (обычно pending сразу после enqueue).
Тип задания Site Manager. Создание копии — site_manager.create_from_source; массовые операции — site_manager.bulk.
URL опроса JSON-состояния (rest_url(…/jobs/{job_id})). Дублируется в заголовке Location; Retry-After=2.
URL SSE-потока прогресса (…/jobs/{job_id}/events), не JSON-poll.
Example
{ "job_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7", "status": "pending", "type": "site_manager.bulk", "poll_url": "https://example.com/wp-json/wp2/site-manager/v1/jobs/7c9e6679-7425-40de-944b-e07fc1f90ae7", "events_url": "https://example.com/wp-json/wp2/site-manager/v1/jobs/7c9e6679-7425-40de-944b-e07fc1f90ae7/events"}Headers
Заголовок раздела «Headers»URL GET состояния задания.
PHP ставит 2.
Missing_fields — нет blog_ids или action; not_multisite.
object
Машинный код ошибки или события.
Текст сообщения (лог, PIN, сброс пароля).
Дополнительные данные WP_Error или лицензии.
object
Examplegenerated
{ "code": "example", "message": "example", "data": {}}Не аутентифицирован. DualRest: rest_forbidden (status 401), если нет cookie-сессии. Cookie + X-WP-Nonce или Application Password.
object
Машинный код ошибки или события.
Текст сообщения (лог, PIN, сброс пароля).
Дополнительные данные WP_Error или лицензии.
object
Examplegenerated
{ "code": "example", "message": "example", "data": {}}Нет права delete_sites/manage_network (код forbidden) или невалидный REST nonce.
object
Машинный код ошибки или события.
Текст сообщения (лог, PIN, сброс пароля).
Дополнительные данные WP_Error или лицензии.
object
Examplegenerated
{ "code": "example", "message": "example", "data": {}}