Справочник: кредиты и автоматизация
Что здесь. Платные действия платформы и всё, что их запускает: кредиты пользователя, промпты ИИ сайта, очередь задач ИИ, публикация релизов GitHub в чейнджлог и автоматические новости. В дашборде это раздел «Автоматизация». Каждая ручка, параметр и код отказа на этой странице сверены с кодом; чтение, отказы и проверки цены прогнаны вызовом на тестовом сайте, платные запуски описаны по коду.
Адреса. Кредиты — ручки сети: https://onpress.pro/api/v2/me/credits…, сайт не выбирается. Остальное — ручки сайта: https://onpress.pro/api/v2/site/{siteId}/…, права — администратор сайта или суперадмин сети. В примерах op_XXXX — ваш токен, SITE_ID — внешний идентификатор сайта (поле site_id ответа GET /sites/{id}). Как выбирается сайт и в какой форме приходят отказы — доступ.
Деньги. Ничего платного не уходит без явного подтверждения цены там, где её заранее не видно: GitHub через ИИ просит confirm и expected_cost, новость стоит ровно столько, сколько показывает GET /news/auto. Кредиты списываются только после результата; сбой возвращает резерв целиком.
Кредиты
| Пункт | Ручка | Тело |
|---|---|---|
| Баланс, прайс и пределы пополнения | GET /me/credits | — |
| История движений | GET /me/credits/transactions | ?limit=50&before=ID&direction=out |
| Пополнение | POST /me/credits/topup | {"amount": 500, "flow": "widget"} |
| Состояние пополнения | GET /me/credits/topups/{id} | ?verify=1 |
| Начисление и коррекция | POST /credits/grant | {"user_id": 12, "amount": 100} |
1 кредит = 1 ₽. Баланс принадлежит пользователю, а не сайту: один баланс тратится на все сайты, где вы администратор, и в каждом списании записан сайт. Новый пользователь начинает с нулевого баланса.
Прайс — за одно действие:
| Действие | Ключ | Кредитов |
|---|---|---|
| Запись чейнджлога через ИИ | github_ai | 5 |
| Новость без картинки | news | 5 |
| Новость с картинкой 16:9 (всё вместе) | news_image | 20 |
| Съём одной позиции в выдаче | serp_position | 1 |
| Отправка одной страницы на индексацию | index_submit | 2 |
Позиции и отправка на индексацию описаны в справочнике SEO; здесь только их цена.
Резерв, потом списание. Перед работой действие резервирует свою цену. Не хватает доступного остатка — отказ сразу, до всякой работы: 402 insufficient_credits с required (сколько нужно) и available (сколько свободно), плюс action и quantity. После успеха резерв списывается, при сбое снимается, ничего не потратив. Доступный остаток — это баланс минус открытые резервы.
Баланс, прайс и пределы пополнения
Ответ — баланс, прайс, пределы пополнения и последние 10 движений.
curl -s "https://onpress.pro/api/v2/me/credits" -H "Authorization: Bearer op_XXXX"
{
"success": true,
"balance": 20,
"held": 0,
"available": 20,
"prices": { "github_ai": 5, "news": 5, "news_image": 20, "serp_position": 1, "index_submit": 2 },
"transactions": [ { "id": 31, "type": "spend", "delta": -20, "balance_after": 5, "action": "news_image", "site_id": "SITE_ID", "site_domain": "example.com", "job_id": 15, "note": "news_image", "created_at": "2026-10-02T11:42:04Z" } ],
"topup": { "min": 100, "max": 100000, "rub_per_credit": 1, "suggested": [100, 500, 1000, 5000] },
"packages": [
{ "id": "pack_100", "credits": 100, "price_rub": 100, "title": "100 кредитов" },
{ "id": "pack_500", "credits": 500, "price_rub": 500, "title": "500 кредитов" },
{ "id": "pack_1000", "credits": 1000, "price_rub": 1000, "title": "1000 кредитов" },
{ "id": "pack_5000", "credits": 5000, "price_rub": 5000, "title": "5000 кредитов" }
]
}
balance — всё начисленное минус списанное, held — открытые резервы, available — сколько можно потратить сейчас. topup — пределы пополнения: min и max в кредитах, rub_per_credit — рублей за кредит, suggested — суммы для быстрого выбора. packages — фиксированные пакеты, устаревший способ пополнения: пока принимаются, но новые клиенты пусть шлют amount. Пакет с "popular": true — самый ходовой, дашборд выделяет его в диалоге пополнения.
История движений
Свежие сверху. limit — от 1 до 200, по умолчанию 50; before — id последней виденной записи, для следующей порции берите next из ответа (null — дальше пусто). direction — in только начисления (сумма больше нуля), out только списания, all или без параметра — всё; со следующей порцией передавайте тот же direction.
curl -s "https://onpress.pro/api/v2/me/credits/transactions?limit=2" -H "Authorization: Bearer op_XXXX"
{
"success": true,
"transactions": [
{ "id": 32, "type": "grant", "delta": 15, "balance_after": 20, "action": null, "site_id": null, "site_domain": null, "job_id": null, "note": "…", "created_at": "2026-10-02T11:42:24Z" },
{ "id": 31, "type": "spend", "delta": -20, "balance_after": 5, "action": "news_image", "site_id": "SITE_ID", "site_domain": "example.com", "job_id": 15, "note": "news_image", "created_at": "2026-10-02T11:42:04Z" }
],
"next": 31
}
type: bonus — бонус от платформы, topup — оплата пополнения, grant и adjust — начисление и коррекция администратором платформы, spend — списание за действие, refund — возврат. balance_after — баланс сразу после этой записи (без учёта резервов, которые были открыты в тот момент). site_id и site_domain — сайт, за который списано, у начислений null. job_id ведёт в задачи ИИ, когда списание было за задачу.
Ошибка: 400 invalid_direction — direction не all, in или out.
Пополнение
Создаёт заказ на amount кредитов. amount — целое число от topup.min до topup.max из GET /me/credits (сейчас от 100 до 100 000), к оплате amount × rub_per_credit рублей. Устаревший вариант — {"package": "pack_500"} с id пакета из packages; если переданы оба поля, берётся amount. Деньги по этому вызову не двигаются. Способ оплаты задаёт flow:
widget — оплата окном CloudPayments поверх своей страницы, без перехода. Ответ несёт widget — всё, что нужно передать виджету (cp.CloudPayments().pay('charge', …)): public_id в publicId, invoice_id в invoiceId, amount, currency, description, account_id в accountId, email, data. Номер счёта менять нельзя: по нему платёж находит заказ.
link (по умолчанию) — ссылка на страницу оплаты CloudPayments в payment_url. После оплаты человек возвращается в дашборд на return_path (путь дашборда вида /pages, без хоста; по умолчанию /settings/credits) с ?topup=ID, после неуспешной — ещё и с topup_failed=1. Дашборд по этим параметрам сам открывает ожидание зачисления.
Кредиты зачисляются, когда платёж подтверждён платёжным сервисом; повторное уведомление о том же платеже ничего не удваивает. Ждать зачисления — опросом состояния пополнения.
curl -s -X POST "https://onpress.pro/api/v2/me/credits/topup" -H "Authorization: Bearer op_XXXX" \
-H "Content-Type: application/json" -d '{"amount":500,"flow":"widget"}'
{
"success": true, "topup_id": 41, "invoice_id": "cr_41", "credits": 500, "price_rub": 500,
"widget": {
"public_id": "pk_XXXX", "invoice_id": "cr_41", "amount": 500, "currency": "RUB",
"description": "OnPress: 500 кредитов", "account_id": "user@example.com", "email": "user@example.com",
"data": { "kind": "credits", "topup_id": 41, "package": "custom" }
}
}
Со "flow": "link" вместо widget приходит payment_url:
{ "success": true, "topup_id": 42, "invoice_id": "cr_42", "credits": 500, "price_rub": 500, "payment_url": "https://…" }
Ошибки: 400 invalid_amount — amount не целое или вне пределов, пределы в полях min и max; 400 unknown_package — не передан amount, а пакета нет в списке (допустимые в поле packages); 502 payment_link_failed — платёжный сервис не выдал ссылку (только link); 503 payments_not_configured — оплата на сервере не подключена.
{ "success": false, "error": "invalid_amount", "message": "amount must be an integer from 100 to 100000", "min": 100, "max": 100000 }
Состояние пополнения
GET /me/credits/topups/{id} — заказ из ответа пополнения, только свой. status: new — не оплачен или подтверждение ещё не пришло, paid — кредиты зачислены (paid_at), failed — ссылку создать не удалось. С ?verify=1 неоплаченный заказ младше 48 часов сверяется с платёжным сервисом напрямую, не дожидаясь его уведомления: прошедший платёж зачисляется тут же, в ответе provider — что сервис знает о последней попытке (status: Completed, Declined, NotFound и другие статусы CloudPayments; message — причина отказа банка для человека). Сверка идёт не чаще раза в 4 секунды на заказ, чаще — ответ без provider. Опрашивать раз в 2–3 секунды; обычно зачисление занимает несколько секунд.
curl -s "https://onpress.pro/api/v2/me/credits/topups/41?verify=1" -H "Authorization: Bearer op_XXXX"
{ "success": true, "topup_id": 41, "invoice_id": "cr_41", "status": "new", "credits": 500, "price_rub": 500,
"created_at": "2026-10-06T09:22:05.000Z", "paid_at": null,
"provider": { "status": "Declined", "reason": "InsufficientFunds", "message": "Недостаточно средств на карте", "credited": 0 } }
Ошибки: 404 topup_not_found — заказа нет или он чужой; 409 payment_mismatch — сумма или счёт оплаты не совпали с заказом, зачисления нет, нужен разбор в поддержке.
Начисление и коррекция
Только суперадмин сети. amount — целое, не ноль, по модулю не больше 1 000 000; положительное — начисление, отрицательное — коррекция, которая не может увести доступный остаток ниже нуля (409 insufficient_credits). note — подпись в истории, idempotency_key — повтор с тем же ключом не начислит второй раз. Ответ — ledgerId, reused и новые balance, held, available.
Ошибки: 403 insufficient_role — не суперадмин; 400 invalid_amount, invalid_user.
Промпты
| Пункт | Ручка | Тело |
|---|---|---|
| Все промпты сайта | GET /site/{siteId}/ai/prompts | — |
| Один промпт | GET /site/{siteId}/ai/prompts/{key}PUT /site/{siteId}/ai/prompts/{key} | {"text": "…", "model": "google/gemini-2.5-flash"} |
| Сброс к умолчанию | DELETE /site/{siteId}/ai/prompts/{key} | — |
Промпт — шаблон текста, по которому ИИ пишет для сайта, и модель, которая его исполняет. У каждого сайта свой текст; пока его не меняли, действует умолчание платформы.
| Ключ | Для чего | Плейсхолдеры |
|---|---|---|
github_changelog | запись чейнджлога из релиза | {{site_name}} {{repo}} {{tag}} {{date}} {{commits}} {{lang}} |
news_article | текст новости | {{site_name}} {{site_description}} {{lang}} {{topic}} {{category}} {{recent_titles}} {{tone}} {{format}} |
news_image | картинка к новости | {{site_name}} {{title}} {{excerpt}} {{category}} {{topic}} {{lang}} |
Плейсхолдер {{имя}} подставляется один раз; неизвестное имя становится пустой строкой. {{format}} в news_article служебный: в него приходят требования к форме ответа и причины, по которым прошлый ответ отклонён, — уберёте его, и новости начнут отклоняться проверкой. Модели по умолчанию: текст — google/gemini-2.5-flash, картинка — google/gemini-3.1-flash-image.
Все промпты сайта
Список всех ключей в форме одного промпта.
Один промпт
GET отдаёт промпт:
{
"success": true,
"prompt": {
"key": "github_changelog",
"title": "GitHub → changelog",
"description": "Превращает коммиты и релиз в запись changelog в markdown.",
"kind": "text",
"variables": [ { "name": "site_name", "description": "Название сайта" }, { "name": "repo", "description": "Репозиторий, owner/name" } ],
"model": "google/gemini-2.5-pro",
"default_model": "google/gemini-2.5-flash",
"text": "Write a release note in {{lang}} for {{repo}}:\n{{commits}}",
"default_text": "You write release notes for the product …",
"custom": true,
"updated_at": "2026-10-02T16:55:27Z"
}
}
kind — text или image; custom: true — у сайта свой текст или модель, default_text и default_model — умолчание платформы.
PUT сохраняет свой текст и, если нужно, модель. text — непустая строка до 20 000 символов; model — идентификатор модели OpenRouter вида провайдер/имя, пусто или не передано — модель по умолчанию. Текст и модель, совпавшие с умолчанием, снимают настройку сайта (custom: false). Ответ — промпт в той же форме. Новый текст действует со следующей задачи.
curl -s -X PUT "https://onpress.pro/api/v2/site/SITE_ID/ai/prompts/github_changelog" \
-H "Authorization: Bearer op_XXXX" -H "Content-Type: application/json" \
-d '{"text":"Write a release note in {{lang}} for {{repo}}:\n{{commits}}","model":"google/gemini-2.5-pro"}'
Ошибки: 404 prompt_not_found — нет такого ключа, известные перечислены в message; 400 invalid_prompt — пустой текст, prompt_too_long — длиннее 20 000, invalid_model — модель не похожа на провайдер/имя.
Сброс к умолчанию
Удаляет текст и модель сайта, ответ — промпт с custom: false. Повторный сброс безопасен.
Задачи ИИ
| Пункт | Ручка | Тело |
|---|---|---|
| Список задач | GET /site/{siteId}/ai/jobs | ?limit=50&before=ID&status=done |
| Одна задача | GET /site/{siteId}/ai/jobs/{id} | — |
| Поставить задачу | POST /site/{siteId}/ai/jobs | {"action": "news"} |
| Снять из очереди | POST /site/{siteId}/ai/jobs/{id}/cancel | — |
Всё, что ИИ делает для сайта, — задача: запись чейнджлога, новость, картинка. Задачи идут в очереди по две одновременно. Статусы: queued — ждёт, running — выполняется, done — готово и оплачено, failed — сбой, кредиты не списаны, cancelled — снята из очереди. Задача, которую оборвал перезапуск сервиса, закрывается как failed с возвратом резерва.
Список задач
Свежие сверху, по сайту. limit — от 1 до 200, по умолчанию 50; before — id для следующей порции (next в ответе); status — фильтр.
{
"success": true,
"jobs": [
{ "id": 15, "action": "news_image", "status": "done", "credits": 20, "error": null, "result_url": "https://example.com/news/…/", "model": "google/gemini-2.5-flash", "cost_usd": 0.0731, "created_at": "2026-10-02T11:40:12Z", "started_at": "2026-10-02T11:40:12Z", "finished_at": "2026-10-02T11:42:04Z" }
],
"next": null
}
credits — цена задачи, result_url — что получилось (страница, черновик), cost_usd — себестоимость вызовов модели.
Одна задача
То же плюс input (с чем запущена), output (что вернула; картинки — только mime и размер в байтах, без данных) и steps — каждый вызов модели: шаг, модель, токены, время. 404 job_not_found — на этом сайте такой задачи нет.
Поставить задачу
action — github_ai, news или news_image; vars — значения плейсхолдеров промпта; idempotency_key — повтор с тем же ключом вернёт уже созданную задачу (reused: true) и не возьмёт кредиты второй раз. Кредиты резервируются сразу, ответ приходит, не дожидаясь результата: {job, hold_id, reused}, дальше задачу смотрят по id.
Эта ручка исполняет действие по умолчанию — генерирует текст или картинку и кладёт в output, ничего не публикуя. Для чейнджлога и новостей с публикацией есть свои ручки: GitHub и автоновости.
Ошибки: 400 unknown_action — нет такого действия, известные в message; 402 insufficient_credits — не хватает кредитов, задача не создана.
{ "success": false, "error": "unknown_action", "message": "unknown ai action \"translate\"; known: github_ai, news, news_image" }
Снять из очереди
Только задачу в queued; резерв возвращается, ответ — задача со статусом cancelled. Уже выполняемую не снять: 409 job_not_cancellable.
GitHub → чейнджлог
| Пункт | Ручка | Тело |
|---|---|---|
| Подключение | GET /site/{siteId}/integrations/githubPUT /site/{siteId}/integrations/github | {"repo": "owner/name", "mode": "asis", "auto": true} |
| Отключить | DELETE /site/{siteId}/integrations/github | — |
| Релизы репозитория | GET /site/{siteId}/integrations/github/releases | ?page=1&per_page=20&refresh=1 |
| Опубликовать выбранные | POST /site/{siteId}/integrations/github/releases/publish | {"release_ids": [123], "mode": "ai", "confirm": true, "expected_cost": 5} |
| Забрать новые сейчас | POST /site/{siteId}/integrations/github/sync | {"confirm": true} |
| Журнал публикаций | GET /site/{siteId}/integrations/github/history | ?page=1&per_page=20 |
| Снять запись | DELETE /site/{siteId}/integrations/github/releases/{releaseId} | ?remove_page=0 |
Релизы репозитория становятся записями чейнджлога сайта: страница /changelog/<слаг>/ на фрейме changelog__post и строка набора changelog в ленте, с пагинацией; кэш обеих страниц сбрасывается сразу. Слаг — тег релиза (v15.5.4 → v15-5-4). Чтобы лента что-то показывала, на сайте нужна страница /changelog/.
Два режима. asis — «как есть»: текст релиза публикуется без переписывания, заголовок — имя релиза или тег, дата — дата релиза, метка (Feature, Fix или Improvement) подбирается по тексту. Бесплатно. ai — «через ИИ», 5 кредитов за релиз: модель получает текст релиза, влитые pull request’ы и коммиты с прошлого релиза и пишет запись для пользователей по промпту github_changelog. Кредиты списываются только после того, как страница опубликована; сбой ничего не стоит. Платит тот, кто нажал, а при публикации по расписанию — тот, кто подключил репозиторий.
Доступ. Публичный репозиторий подключается без токена. Приватный — с fine-grained токеном GitHub с правами только на чтение Contents и Metadata. Токен хранится зашифрованным и наружу не отдаётся: только маска ••••abcd. Токен полезен и для публичного репозитория: без него GitHub даёт 60 запросов в час на адрес сервера, с ним — 5000.
Один релиз — одна запись. Релиз узнаётся по своему id на GitHub: повторная публикация опубликованного релиза ничего не трогает и ничего не стоит (skipped: "already_published"), релиз в процессе отвечает skipped: "in_progress". Неудачную попытку можно повторить.
Подключение
GET отдаёт состояние. Без подключения — {"connected": false, "providers": ["token", "app"], "ai_price": 5}. С подключением:
{
"success": true,
"providers": ["token", "app"],
"ai_price": 5,
"connected": true,
"provider": "token",
"repo": "vercel/next.js",
"private": false,
"token": null,
"mode": "asis",
"auto": false,
"ai_limit": 0,
"ai_spent_month": 0,
"prereleases": false,
"lang": null,
"site_lang": "en",
"auto_since": "2026-10-02T16:55:40Z",
"last_sync": null,
"counts": { "published": 0, "failed": 0, "pending": 0 },
"cron": { "interval": "hourly", "contour": "production" }
}
PUT подключает или меняет подключение; перед сохранением репозиторий проверяется на GitHub. Поля:
repo — owner/name или адрес на github.com, обязателен при первом подключении. token — fine-grained токен; не передан — для того же репозитория остаётся сохранённый, "" — снять токен. mode — asis (по умолчанию) или ai. auto — публиковать новые релизы раз в час сами, по умолчанию true. ai_limit — потолок кредитов в календарный месяц для публикации по расписанию через ИИ, целое от 0. prereleases — брать ли пре-релизы, по умолчанию нет. lang — язык записей, по умолчанию язык сайта по умолчанию. confirm — подтверждение трат.
mode: "ai" вместе с auto: true требует ai_limit больше нуля (400 ai_limit_required) и confirm: true — иначе 409 confirmation_required с ценой и лимитом:
{ "success": false, "error": "confirmation_required", "message": "automatic publishing through AI spends credits (5 per release, up to 50 per month); repeat the request with \"confirm\": true", "price": 5, "ai_limit": 50 }
По расписанию берутся только релизы новее auto_since — момента подключения или включения auto: старые релизы разом не публикуются. Расписание работает раз в час на боевом сервере. Релиз, который не влезает в месячный лимит, пропускается без списания.
curl -s -X PUT "https://onpress.pro/api/v2/site/SITE_ID/integrations/github" \
-H "Authorization: Bearer op_XXXX" -H "Content-Type: application/json" \
-d '{"repo":"https://github.com/vercel/next.js","mode":"asis","auto":false}'
Отключить
Снимает подключение и токен. Опубликованные записи и журнал остаются. Ответ — {"connected": false, "removed": true}.
Релизы репозитория
Последние 100 релизов (черновики не показываются, пре-релизы — если включены или с all=1), кэш — минута, refresh=1 — свежий список. per_page — до 100, по умолчанию 20.
{
"success": true,
"repo": "vercel/next.js",
"page": 1,
"per_page": 1,
"more": true,
"total": 14,
"releases": [
{ "id": 399923971, "tag": "v16.3.8", "name": "v16.3.8", "published_at": "2026-09-30T16:13:46Z", "prerelease": false, "url": "https://github.com/vercel/next.js/releases/tag/v16.3.8", "author": "…", "excerpt": "This release contains security fixes…", "published": null, "failed": null }
]
}
published у опубликованного — {status, mode, url, label, credits}, failed у неудачного — {error, attempts}.
Опубликовать выбранные
release_ids — id из списка релизов: до 30 за раз «как есть», до 5 через ИИ. mode — по умолчанию режим подключения. Через ИИ без confirm: true ответ 409 confirmation_required с ценой за ещё не опубликованные релизы; expected_cost ниже реальной цены — 409 expected_cost_too_low. Так цену можно узнать, ничего не потратив.
{ "success": false, "error": "confirmation_required", "message": "publishing through AI spends credits: 5 for 1 release(s); repeat with \"confirm\": true and \"expected_cost\": 5", "cost": 5, "price": 5, "releases": 1 }
Ответ — {success, mode, results, balance}: по строке на релиз (release_id, tag, status, skipped, mode, credits, url, slug, label, job_id, у сбоя — error) и остаток кредитов. На нехватке кредитов публикация останавливается, сделанное остаётся.
Забрать новые сейчас
То же, что расписание, но сразу: новые релизы после auto_since в режиме подключения. Через ИИ при найденных релизах нужен confirm: true, иначе 409 с ценой. Ответ — {success, repo, mode, found, published, skipped, failed, balance}; в skipped причина — monthly_limit, already_published или in_progress.
{ "success": true, "repo": "vercel/next.js", "mode": "asis", "found": 0, "published": [], "skipped": [], "failed": [], "balance": { "available": 20, "balance": 20, "held": 0 } }
Журнал публикаций
Каждый релиз, который проходил через интеграцию: release_id, tag, title, status (published, pending, failed), mode, trigger (manual — руками, auto — по расписанию), credits, job_id, url, label, error, attempts и даты. more: true — есть следующая страница.
Снять запись
Убирает страницу записи, её строку из ленты и отметку о публикации — релиз можно опубликовать заново. remove_page=0 — снять только отметку, страницу и строку оставить. Кредиты не возвращаются.
Ошибки GitHub
| Код | error | Когда |
|---|---|---|
| 400 | invalid_repo, invalid_token, invalid_mode, invalid_ai_limit, invalid_lang | неверное поле подключения |
| 400 | repo_required, release_ids_required, too_many_releases, ai_limit_required | не хватает репозитория, списка релизов, лимита или список длиннее допустимого (max) |
| 402 | insufficient_credits | не хватает кредитов на режим ИИ |
| 404 | github_not_connected | репозиторий не подключён |
| 404 | release_not_found | релиза нет среди последних 100 |
| 404 | release_record_not_found | релиз не публиковался через интеграцию |
| 404 / 401 / 403 | github_repo_not_found, github_token_invalid, github_forbidden | GitHub не видит репозиторий, отверг токен или не дал доступа |
| 409 | confirmation_required, expected_cost_too_low | трата кредитов не подтверждена или подтверждена не той суммой |
| 409 | release_in_progress, publish_busy | релиз или чейнджлог сайта сейчас пишется — повторите позже |
| 429 | github_rate_limited | исчерпан лимит GitHub, reset_at — когда восстановится |
| 501 | provider_not_supported | провайдер app (приложение GitHub) пока недоступен |
| 502 | github_unreachable, github_error, ai_job_failed, ai_empty | GitHub или модель не ответили как надо; кредиты не списаны |
Автоновости
| Пункт | Ручка | Тело |
|---|---|---|
| Настройки и расписание | GET /site/{siteId}/news/autoPUT /site/{siteId}/news/auto | {"enabled": true, "per_week": 3, "monthly_limit": 300} |
| Запустить сейчас | POST /site/{siteId}/news/auto/run | {"topic": "…", "mode": "draft"} |
| Сделанные новости | GET /site/{siteId}/news/auto/items | ?limit=50&before=ID |
| Опубликовать черновик | POST /site/{siteId}/news/auto/items/{id}/publish | — |
| Убрать черновик или сбой | DELETE /site/{siteId}/news/auto/items/{id} | — |
| Пересобрать ленту | POST /site/{siteId}/news/auto/feed | {"lang": "en"} |
ИИ пишет новость по теме сайта и кладёт её в раздел /news/: страница на фрейме news__post, дочерняя к странице раздела, с рубрикой. Цена — news 5 кредитов или news_image 20 с картинкой 16:9 (всё вместе). Кредиты списываются только когда страница создана; любой сбой возвращает резерв.
Что делает задача. Читает сайт — название, описание, раздел новостей, рубрики, заголовки последних новостей, — пишет новость по промпту news_article и проверяет её: длина заголовка, лида и текста (150–750 слов, от трёх абзацев), язык, нет H1, ссылок, картинок, таблиц, цитат, процентов, выдуманных фактов о продукте. Не прошло — модель получает причины и пишет заново, до трёх попыток; после третьей задача падает с news_format_rejected без списания. С картинкой — генерирует её по промпту news_image, кладёт в медиатеку с заголовком в alt и ставит превью страницы. Слаг уникален внутри раздела.
Публикация. mode: "publish" публикует страницу и пересобирает ленту из живых новостей раздела: список новостей, три свежих на главной, рубрики со счётчиками, пагинацию, «ещё новости». Страницы, которые показывают эти наборы, сразу собираются по шаблону заново со сбросом кэша, так что новость видна в /news/, в рубрике и на главной сразу. mode: "draft" сохраняет черновик со ссылкой на предпросмотр, лента не меняется; кредиты списываются за генерацию, публикация черновика потом бесплатна.
Настройки и расписание
GET отдаёт настройки, варианты, цены, баланс и состояние расписания:
{
"success": true,
"settings": { "enabled": false, "per_week": 2, "categories": [], "with_image": true, "tone": "neutral", "lang": "en", "monthly_limit": 100, "auto_publish": true, "topics": "" },
"saved": false,
"owner_id": null,
"options": { "languages": [ { "slug": "en", "name": "English" }, { "slug": "ru", "name": "Русский" } ], "default_lang": "en", "lang": "en", "ready": false, "section": null, "categories": [], "tones": ["neutral", "friendly", "expert", "concise"] },
"prices": { "news": 5, "news_image": 20 },
"credits": { "available": 20, "balance": 20, "topup_path": "/settings/credits" },
"schedule": { "week_count": 0, "month_spent": 0, "month_limit": 100, "blocked": "disabled", "next_run_at": null, "interval_hours": 84, "last_run_at": null, "last_error": "" }
}
options.ready — есть ли у сайта раздел /news/ на этом языке; options.categories — рубрики раздела (slug, title, url). schedule.blocked — почему расписание сейчас не запустится: disabled — выключено, week_quota — недельная норма сделана, monthly_limit — месячный лимит исчерпан, backoff — после сбоя пауза 6 часов, null — ничего не мешает; next_run_at — ближайший запуск.
PUT принимает любые из полей, остальные остаются:
enabled — расписание включено. per_week — сколько новостей в неделю, 1–14, по умолчанию 2. categories — список слагов рубрик; пусто — все, по очереди: берётся рубрика, где за 28 дней меньше всего новостей. with_image — с картинкой, по умолчанию да. tone — neutral, friendly, expert или concise. lang — язык новостей, по умолчанию язык сайта по умолчанию. monthly_limit — потолок кредитов в календарный месяц на новости по расписанию, 0–100 000, по умолчанию 100; 0 — расписание ничего не запустит. auto_publish — публиковать сразу, false — складывать в черновики. topics — темы, которые ИИ предпочитает, до 400 символов.
Платит тот, кто сохранил настройки, и он должен оставаться администратором сайта. Расписание работает на боевом сервере раз в час с 05:00 до 18:00 UTC: сайт в очереди, когда за 7 дней сделано меньше per_week новостей по расписанию и с прошлой прошло не меньше 90% интервала 7 дней / per_week. Ручные запуски в недельную норму и месячный лимит не входят.
Включить расписание без раздела /news/ на языке нельзя: 409 news_section_missing; рубрика, которой нет в разделе, — 409 news_category_missing.
curl -s -X PUT "https://onpress.pro/api/v2/site/SITE_ID/news/auto" \
-H "Authorization: Bearer op_XXXX" -H "Content-Type: application/json" \
-d '{"enabled":true,"per_week":3,"categories":["guides"],"with_image":true,"monthly_limit":300}'
Запустить сейчас
Ставит одну новость в очередь, кредиты резервируются сразу. Поля: topic — тема до 300 символов, без неё ИИ выбирает сам по теме сайта и topics; category — слаг рубрики, без неё — наименее заполненная из рубрик расписания, "none" — без рубрики; lang, tone, with_image — по умолчанию из настроек; mode — draft (по умолчанию) или publish; idempotency_key — повтор с тем же ключом не запустит вторую новость.
Ответ — {job, reused, with_image, mode, category}; ход задачи — в задачах ИИ и в списке сделанных новостей. Отказы до всякой траты: 402 insufficient_credits, 409 news_section_missing, 409 news_category_missing, 400 invalid_topic.
curl -s -X POST "https://onpress.pro/api/v2/site/SITE_ID/news/auto/run" \
-H "Authorization: Bearer op_XXXX" -H "Content-Type: application/json" \
-d '{"topic":"How to brief an assistant","category":"guides","with_image":false,"mode":"draft"}'
Сделанные новости
Свежие сверху; limit до 200, по умолчанию 50; before и next — как в истории кредитов. У записи: id, job_id, status (queued, running, draft, published, failed), trigger (manual или cron), with_image, lang, category, title, url, preview_url (у черновика), credits, error (у сбоя), created_at, published_at.
Опубликовать черновик
Бесплатно: кредиты взяты при генерации. Публикует страницу с текущей датой и пересобирает ленту. Ответ — {item, link}. Ошибки: 404 news_item_not_found, 409 news_already_published, news_not_a_draft, news_draft_empty; 400 invalid_item — id не целое число.
Убрать черновик или сбой
Удаляет черновик вместе со страницей или запись о сбое из списка; ответ — {id}. Опубликованная новость убирается как страница — DELETE /pages/{ref}, здесь 409 news_item_published.
Пересобрать ленту
Собирает наборы ленты заново из живых страниц раздела — после того как новость удалили или поправили руками. Бесплатно. Ответ — {lang, section, posts, categories, written, rebaked}: сколько новостей и рубрик в ленте, какие наборы записаны и какие страницы собраны заново. Ошибки: 409 news_section_missing — нет раздела /news/, 409 news_dataset_missing — у сайта нет набора ленты новостей.
Ошибки автоновостей
| Код | error | Когда |
|---|---|---|
| 400 | invalid_per_week, invalid_monthly_limit, invalid_tone, invalid_lang, invalid_categories, invalid_topic, invalid_item | неверное поле |
| 402 | insufficient_credits | не хватает кредитов; required, available |
| 404 | news_item_not_found | нет такой записи |
| 409 | news_section_missing, news_category_missing, news_dataset_missing | нет раздела, рубрики или набора ленты |
| 409 | news_already_published, news_not_a_draft, news_item_published, news_draft_empty | запись не в том состоянии |
| 422 | news_format_rejected | в задаче: три ответа модели не прошли проверку, кредиты не списаны |
{ "success": false, "error": "invalid_per_week", "message": "per_week must be an integer from 1 to 14" }
Раздел «Автоматизация» в дашборде
Раздел — пункт «Автоматизация» в боковом меню дашборда рядом с фреймами, данными и SEO; баланс виден в меню пользователя и ведёт на страницу «Кредиты» в настройках, рядом пункт «Пополнить кредиты». Страницы раздела работают на тех же ручках:
«Промпты» (/dashboard/automation/prompts) — тексты и модели промптов сайта: промпты. «Задачи ИИ» (/dashboard/automation/jobs) — очередь и результаты: задачи ИИ. «GitHub» (/dashboard/automation/github) — подключение репозитория, релизы и журнал: GitHub → чейнджлог. «Новости» (/dashboard/automation/news) — настройки расписания, ручной запуск и сделанные новости: автоновости.
Кредиты в настройках. Страница «Кредиты» — в настройках, группа «Подписка» (/dashboard/settings/credits; старый адрес /dashboard/automation/credits переадресует туда). Наверху доступный баланс и «Пополнить», ниже история операций с вкладками «Все», «Начисления», «Списания»: дата, операция («Отправка на индексацию», «Пополнение», «Новость ИИ»), сайт, сумма и баланс после — кредиты.
Пополнение в дашборде. Один диалог «Пополнить кредиты» открывается из меню пользователя, со страницы «Кредиты», из отказа «Не хватает кредитов» у отправки на индексацию в «Страницах», у позиций, новостей и публикации релизов через ИИ. В нём текущий баланс, четыре пакета (ходовой помечен), своя сумма от минимума и итог «получите N кредитов». Оплата — окно CloudPayments поверх страницы; если оно не загрузилось (блокировщик), открывается страница оплаты и после неё человек возвращается туда же. После оплаты диалог показывает «Ожидаем подтверждения…» и опрашивает состояние пополнения до полутора минут, затем сообщает «Зачислено N кредитов»; не дождался — говорит, что кредиты придут сами, и сообщает о зачислении позже. Пополнение из отправки на индексацию после зачисления продолжает отправку: снова показывает подтверждение с ценой, а если стоит «Не спрашивать», отправляет сразу. Закрытое окно оплаты и отказ банка показываются в диалоге текстом с причиной.
Общий обзор дашборда — дашборд.