Публикации
Опубликовать публикацию
Live-приложения публикуют сразу, планируют по дате или сохраняют черновик; тестовые только имитируют. С ?dry_run=true всё проверяется, ничего не записывается.
Публикация принадлежит заведению и уходит в одну или несколько сетей — свои цели. У каждой цели свой текст, медиа, формат и состояние.
Тип публикации: сейчас, запланированная или черновик
Два поля тела определяют, когда и уйдёт ли публикация:
| Случай | Тело | Поведение |
|---|---|---|
| Сейчас | без scheduledAt | Публикация уходит сразу. |
| Запланирована | scheduledAt: будущие дата и время в ISO 8601 | Уйдёт в scheduledAt. |
| Черновик | "status": "draft", без scheduledAt | Сохраняется и не уходит. |
Тело публикации
| Поле | Значение |
|---|---|
establishmentId | Заведение, которое публикует (GET /v1/establishments) |
targets[] | По записи на сеть: platform, text и, по желанию, media, format и accountId |
targets[].media[] | Медиа из медиатеки по его id или публичный https url с его type (image или video) |
targets[].accountId | Аккаунт для использования, когда у заведения их несколько в этой сети |
scheduledAt | Будущие дата и время в ISO 8601; если поля нет, публикация уходит сразу |
status | draft, чтобы сохранить черновик, который не уходит (тогда без scheduledAt) |
Медиа цели
Каждая запись в targets[].media указывает медиа из медиатеки по его id или публичный https url с его type (image или video). Instagram и TikTok требуют фото или видео. Чтобы добавить медиа в медиатеку, см. Импорт медиа.
Дублирование публикации
Отдельного endpoint для дублирования публикации нет: прочитайте её через `GET /v1/posts/{id}`, затем отправьте её содержимое в новом запросе POST /v1/posts.
Перед повторной отправкой уберите поля, которые Sofia заполняет сама. Как минимум:
idиcreatedAtпубликации;statusпрочитанной публикации (он обобщает состояние отправки): задайте нужный или опустите его;- в каждой цели:
state,publishedAt,permalinkиerror.
Оставьте establishmentId, а для каждой цели — platform и accountId. Чтение не возвращает текст целей и их медиа: передайте их заново. Наконец, задайте новый scheduledAt (или опустите его, чтобы опубликовать сразу, или отправьте "status": "draft").
Ваша первая публикация
1. Проверьте подключённые сети
Публикация уходит через аккаунты, подключённые к заведению. Перечислите их; если какого-то не хватает, создайте ссылку для подключения. См. Подключённые аккаунты.
2. Добавьте медиа
Instagram и TikTok требуют фото или видео. Импортируйте его с публичного https URL; Sofia скачает его в медиатеку и вернёт его id. См. Импорт медиа.
3. Проверьте симуляцией
Добавьте ?dry_run=true: Sofia оценивает каждую сеть по её реальным правилам и подключённому аккаунту и ничего не записывает.
curl -X POST 'https://api.sofia-post.com/api/v1/posts?dry_run=true' \
-H "Authorization: Bearer $SOFIA_API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"establishmentId": "'$ESTABLISHMENT_ID'",
"targets": [
{ "platform": "instagram", "text": "Tarte tatin du jour", "media": [{ "id": "'$MEDIA_ID'" }] },
{ "platform": "facebook", "text": "Tarte tatin du jour", "media": [{ "id": "'$MEDIA_ID'" }] }
]
}'{
"status": "ready",
"dryRun": true,
"targets": [
{ "platform": "instagram", "accountId": "fecd0904-…", "handle": "sof_ia_officiel", "state": "ready" },
{ "platform": "facebook", "accountId": "a423b3a4-…", "handle": "Sofia post", "state": "ready" }
]
}4. Опубликуйте
Отправьте то же тело без dry_run с Idempotency-Key, чтобы повторная попытка никогда не публиковала дважды. Без scheduledAt публикация уходит сразу; с будущим scheduledAt она запланирована.
curl -X POST https://api.sofia-post.com/api/v1/posts \
-H "Authorization: Bearer $SOFIA_API_KEY" \
-H 'Content-Type: application/json' \
-H "Idempotency-Key: $(uuidgen)" \
-d @post.json5. Следите за ней
Публикация отвечает publishing, затем каждая сеть переходит в published со своей постоянной ссылкой или в failed с причиной. Читайте её через `GET /v1/posts/{id}` или зарегистрируйте вебхук, чтобы получать уведомления.
Симуляция (dry run)
POST /v1/posts?dry_run=true выполняет проверки настоящей публикации: правила каждой сети, подключённый аккаунт, медиа, дату и ваш тариф. Ничего не сохраняет и не отправляет.
Готова
Когда каждая сеть приняла бы публикацию, ответ — 200 с status: "ready" и для каждой цели — аккаунт, который опубликовал бы.
Отклонена
Иначе ответ — 422 post_refused с подробностью по каждой причине. Каждая подробность называет свою сеть и code и говорит, что исправить.
{
"error": {
"code": "post_refused",
"message": "The post would not be published: x: the text is too long (300 characters, at most 280)",
"details": [
{
"platform": "x",
"code": "caption_too_long",
"max": 280,
"actual": 300,
"message": "x: the text is too long (300 characters, at most 280)"
}
],
"docUrl": "https://www.sofia-post.com/developers/errors#post_refused"
}
}Каждая причина перечислена в ошибках.
О тестовом режиме приложений см. Тестовый режим и симуляция. Idempotency-Key защищает и POST /v1/posts: см. Идемпотентность.
Авторизации
AuthorizationstringheaderобязательноВаш личный ключ или токен доступа OAuth, отправляется как
Bearer <token>.
Параметры запроса
dry_runstringtrue: выполняет все проверки отправки (правила сетей, аккаунты, медиа, создание, live-подписка) и ничего не записывает. Возвращает 200readyили 422post_refused.Допустимые значения:
truefalse
Заголовки
Idempotency-KeystringПри повторе с тем же телом запрос возвращает тот же ответ и не создаёт вторую публикацию. Пробный запуск не расходует ключ.
Тело
establishmentIdstringобязательноЗаведение в Workspace авторизации токена (
GET /v1/establishments)targetsobject[]обязательноОдна сеть на цель
Показать дочерние атрибуты
platformstringобязательноЦелевая сеть
Допустимые значения:
instagramfacebookxlinkedintiktoktextstringобязательноПодпись, публикуемая в этой сети
mediaobject[]Прикреплённые медиа
Показать дочерние атрибуты
idstringИдентификатор медиа из медиатеки заведения (иначе
urlиtype)urlstringПубличный адрес медиа (https в live); без идентификатора
typestringТип медиа, заданного адресом
Допустимые значения:
imagevideo
formatstringФормат (
post,reel,story,carousel...); по умолчанию тот, что выдала бы сетьaccountIdstringLive: подключённый аккаунт, который публикует, если у заведения их несколько в этой сети (
GET /v1/establishments/:id/accounts)
scheduledAtstring<date-time>Дата планирования (ISO 8601), в будущем; не указана: публиковать сразу. Недопустима вместе с
statusdraftstatusstringdraft: черновик (только live), создаётся без даты, ничего не отправляется;PATCH /v1/posts/:idпланирует егоДопустимые значения:
draft
Ответ
Пробный запуск: все проверки пройдены.
statusstringобязательноВсегда
readyДопустимые значения:
readydryRunbooleanобязательноВсегда
trueДопустимые значения:
truetargetsobject[]обязательноПроверенные цели
Показать дочерние атрибуты
platformstringобязательноСеть цели
statestringобязательноВсегда
readyДопустимые значения:
readyaccountIdstringLive: аккаунт, который опубликовал бы
handlestringLive: его отображаемый handle