REST API WordPress: чтение и запись данных без плагинов
REST API WordPress позволяет получать записи обычным GET-запросом, а создавать и менять их — через POST с авторизацией. Разбираем структуру запросов, Application Passwords, права доступа и ошибки, которые проявляются в продакшене.

Публичную запись WordPress можно получить одним GET-запросом, но для создания или изменения поста понадобится авторизация, право редактировать контент и корректный JSON. Ниже — практический сценарий для WordPress 6.x: сначала читаем записи через /wp-json/wp/v2/posts, затем создаём черновик и разбираем, почему тот же запрос не работает без HTTPS, nonce или нужной роли.
Что именно умеет REST API WordPress
REST API встроен в WordPress начиная с версии 4.7 и доступен по адресу с префиксом /wp-json/. Для стандартных записей используется маршрут /wp/v2/posts, для страниц — /wp/v2/pages, для пользователей — /wp/v2/users.
Чтение опубликованных записей обычно открыто. Запись данных — создание, изменение и удаление — защищена проверкой пользователя и его возможностей. Поэтому одинаковый URL ведёт себя по-разному в зависимости от метода HTTP и заголовков авторизации.
Главное различие простое: GET отвечает на вопрос «что опубликовано», а POST и PUT требуют доказать, кто вы и что вам разрешено менять.
| Задача | Метод | Маршрут | Авторизация |
|---|---|---|---|
| Получить список записей | GET | /wp-json/wp/v2/posts | Не нужна для публичных записей |
| Получить одну запись | GET | /wp-json/wp/v2/posts/{id} | Нужна для закрытого контента |
| Создать запись | POST | /wp-json/wp/v2/posts | Нужна |
| Изменить запись | POST | /wp-json/wp/v2/posts/{id} | Нужна |
| Удалить запись | DELETE | /wp-json/wp/v2/posts/{id} | Нужна |
Сноска. REST-маршрут — адрес API, который связывает HTTP-запрос с конкретным типом данных и операцией. В WordPress маршрут постов начинается с /wp-json/wp/v2/posts, а идентификатор записи добавляется в конце.
Чтение: от списка до конкретного поля
Начните с простого GET-запроса. Укажите полный адрес сайта, иначе относительный путь будет работать только в коде, который уже выполняется на этом домене.
curl "https://example.com/wp-json/wp/v2/posts?per_page=5&page=1"
В ответе придёт JSON-массив. У каждой записи будут, среди прочего, id, date, slug, link, title и content. Поля title и content содержат объект с представлением rendered — уже подготовленным для вывода HTML.
Чтобы не передавать весь объект, запросите только нужные поля. Параметр _fields поддерживается стандартным REST API WordPress.
curl "https://example.com/wp-json/wp/v2/posts?per_page=5&_fields=id,slug,date,title,link"
Проверяйте заголовки ответа. WordPress передаёт общее число найденных записей в X-WP-Total, а количество страниц — в X-WP-TotalPages. При большой выгрузке нельзя бездумно ставить огромное значение per_page: сервер и лимиты хостинга могут ответить ошибкой.
Фильтрация списка
Для типичного каталога пригодятся параметры search, after, before, categories, author и orderby. Например, запрос ниже ищет опубликованные записи после указанной даты и сортирует их по дате.
curl "https://example.com/wp-json/wp/v2/posts?after=2024-01-01T00:00:00&orderby=date&order=desc&status=publish"
Дата передаётся в ISO 8601. Если фильтр возвращает пустой массив, это не обязательно ошибка: проверьте часовой пояс сайта, статус публикации и код категории.
Авторизация для записи
Для внешнего скрипта в WordPress 6.x обычно используют Application Passwords — отдельный пароль приложения, связанный с учётной записью пользователя. Он не заменяет основной пароль и может быть отозван отдельно. Создать его можно в профиле пользователя, если хостинг или плагин безопасности не отключили эту возможность.
Запрос отправляется по HTTPS с Basic Authentication. В заголовке передаются имя пользователя и пароль приложения. Это не означает, что сайт становится открытым: WordPress дополнительно проверяет роль и возможность конкретного пользователя редактировать посты.
Не вставляйте пароль в репозиторий, JavaScript браузера или публичный URL. В примерах ниже стоят заглушки, а в реальном проекте секрет храните в защищённой переменной окружения или секрет-хранилище.
curl --user "YOUR_USERNAME:YOUR_APPLICATION_PASSWORD" \
"https://example.com/wp-json/wp/v2/users/me?_fields=id,name,capabilities"
Успешный ответ содержит данные текущего пользователя. Если сервер возвращает 401, проблема обычно в учётных данных, HTTPS или блокировке Basic Authentication на уровне прокси. Если ответ 200 есть, но создание записи завершается кодом 403, проверьте права пользователя.
Создание и изменение записи
Безопаснее сначала создавать черновик. Так вы проверите авторизацию и формат данных, не публикуя неполный текст.
curl --user "YOUR_USERNAME:YOUR_APPLICATION_PASSWORD" \
--header "Content-Type: application/json" \
--request POST \
--data '{
"title": "Тестовая запись из REST API",
"content": "<p>Текст создан внешним клиентом.</p>",
"status": "draft"
}' \
"https://example.com/wp-json/wp/v2/posts"
В ответе появится объект новой записи с полем id. Сохраните этот идентификатор: он понадобится для чтения, обновления и удаления. Статус draft не публикует запись и не делает её доступной посетителям как обычную статью.
Изменение выполняется POST-запросом на URL с идентификатором. Передавайте только те поля, которые действительно хотите поменять.
curl --user "YOUR_USERNAME:YOUR_APPLICATION_PASSWORD" \
--header "Content-Type: application/json" \
--request POST \
--data '{
"title": "Обновлённый заголовок",
"status": "draft"
}' \
"https://example.com/wp-json/wp/v2/posts/123"
Число 123 здесь замените на реальный ID. После успешного запроса проверьте ответ GET-запросом и убедитесь, что сервер вернул ожидаемые title.rendered, status и modified.
Публикация — отдельное право
Передача status=publish не гарантирует публикацию. WordPress проверяет, может ли текущий пользователь публиковать записи, а не только создавать черновики. Автор без соответствующей возможности получит ошибку прав или запись останется в другом статусе.
Также учитывайте, что поле content принимает HTML, а не Markdown. Если клиент отправляет Markdown, его нужно преобразовать до запроса либо подключить отдельную обработку на стороне WordPress. Работа с медиафайлами, категориями, тегами и пользовательскими типами записей — смежные темы: у них свои маршруты и ограничения.
Три способа авторизации и их цена
Выбор зависит от места выполнения клиента. Для серверного интегратора и внутреннего скрипта подход с Application Passwords проще всего. Для кода внутри админки WordPress безопаснее использовать cookie-сессию и nonce. Публичному браузерному приложению нельзя выдавать пароль приложения.
| Подход | Где применять | Плюс | Ограничение |
|---|---|---|---|
| Application Passwords | Серверный скрипт, CI-задача, интеграция | Простой стандартный механизм WordPress | Секрет нельзя отправлять в браузер |
| Cookie и nonce | JavaScript внутри авторизованной панели или темы | Использует текущую сессию WordPress | Клиент должен работать в контексте этого сайта |
| Плагин или собственная схема | Публичное внешнее приложение со своими пользователями | Можно настроить отдельную модель доступа | Появляются собственная безопасность и сопровождение |
Если интеграция запускается на другом сервере, не пытайтесь решить задачу передачей cookie из браузера. Создайте отдельную учётную запись с минимально необходимыми правами и отдельный пароль приложения. Отзыв этого пароля отключит только конкретную интеграцию.
Что ломается на практике
- 404 на
/wp-json/. Проверьте адрес сайта, работу постоянных ссылок и настройки веб-сервера. На старых или нестандартных конфигурациях REST API может блокироваться правилами прокси или безопасности. - 401 rest_cannot_access. Проверьте имя пользователя, пароль приложения и передачу заголовка авторизации. Некоторые прокси не прокидывают заголовок
Authorizationдо PHP. - 403 rest_forbidden. Пользователь вошёл, но ему не хватает возможности для операции. Проверьте роль, статус записи и ограничения плагинов, которые управляют доступом.
- 400 rest_invalid_param. В JSON есть неизвестное или неверно оформленное поле. Сверьте название параметра, тип значения и маршрут конкретного типа записи.
- Ответ обрезается или приходит слишком медленно. Уменьшите
per_page, используйте_fieldsи постраничную загрузку. Большие поляcontentи связанные данные сильнее нагружают PHP и базу.
Что проверить перед продакшеном
Сначала прогоните сценарий на копии сайта: получить список, создать черновик, изменить его, прочитать результат и удалить тестовую запись. Затем добавьте журналирование HTTP-кода, URL без секретов, идентификатора записи и текста ошибки. Сам пароль в логи не записывайте.
Для чтения измерьте размер ответа и время запроса при разных значениях per_page. Для записи проверьте повторную отправку: сетевой сбой может оставить запись созданной, хотя клиент не получил ответ. Если интеграция повторяет запрос автоматически, продумайте защиту от дублей по внешнему идентификатору. Сам REST API не предоставляет универсальную идемпотентность для создания постов.
В продакшене также следите за обновлениями WordPress, плагинов безопасности и обратными прокси. Поведение стандартных маршрутов сохраняется в рамках совместимости, но пользовательские поля, типы записей и ограничения конкретной установки могут отличаться.
Что делать дальше
Соберите минимальный клиент с четырьмя операциями: GET списка, GET по ID, POST черновика и POST обновления. После этого добавьте пагинацию, выборку через _fields, обработку кодов 401/403/404/429 и отзыв пароля приложения при смене владельца интеграции. Для следующего шага изучите схему нужного маршрута в официальном справочнике REST API, особенно если сайт использует пользовательский тип записи или собственные поля.
Материал написан для WordPress 6.x. Перед внедрением проверьте документацию версии сайта и ограничения хостинга: плагины, прокси и настройки безопасности могут менять доступность стандартной авторизации и маршрутов.
Аналитик звонков: Разбор записи звонка по этапам сделки: где сорвалось, что упущено, три исправляемые рекомендации с цитатами.
Спросить за 90 ₽Источники: WordPress REST API Handbook, Authentication — Application Passwords
Частые вопросы
Можно ли читать записи WordPress без авторизации?
Почему POST-запрос возвращает 401, хотя пароль правильный?
Грозит ли что-то, если я не успею перейти на новый способ авторизации?
Можно ли использовать Application Passwords в JavaScript на сайте?
Что делать, если у меня другая версия WordPress?
Почему запись создаётся, но не публикуется?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.