Проект, размещения и усиление через API
Один проект от черновика до отчёта и отдельной покупки усиления. На каждом шаге видно, какие данные взять из ответа для следующего запроса.
Подключитесь к API Zapost.im
Запросите у поддержки рабочий ключ zp_live_. Для полного цикла нужны read, projects:write и projects:pay. В черновике замените демонстрационный URL на страницу своего проекта. Запускайте команды по порядку в одном сеансе Bash с curl, jq и Node.js 24.
set -o pipefail
API_BASE='https://zapost.im/api/v2'
read -rsp 'API key: ' API_KEY
printf '\n'
api() {
local path=$1
shift
curl --silent --show-error --fail-with-body \
-H "Authorization: Bearer $API_KEY" "$@" "$API_BASE$path"
}
post() {
api "$1" -H "Idempotency-Key: $2" \
-H 'Content-Type: application/json' --data "$3"
}
new_key() { node -p 'crypto.randomUUID()'; }
api /packages | jq '.data[] | {code, name, price, placements, page_limit}'
api /balance | jq '.data | {available, currency}'Выберите code из каталога. В примере используется пакет start. Все суммы в ответах указаны в целых копейках.
Создайте проект
Передайте пакет, целевую страницу, описание сайта и требования к сообщению. Сохраните id проекта и его revision из ответа. Усиление купим отдельно после получения размещений.
PACKAGE_CODE='start'
CREATE_KEY=$(new_key)
DRAFT=$(jq -cn --arg package "$PACKAGE_CODE" --arg ref "demo-$CREATE_KEY" '{
package_code: $package, external_id: $ref,
urls: ["https://example.test/catalog"],
brief: "Online shop for camping equipment",
notes: "Link to the catalog in a relevant discussion",
amplification_level: null
}')
PROJECT=$(post /projects "$CREATE_KEY" "$DRAFT")
PROJECT_ID=$(jq -er '.data.id' <<< "$PROJECT")
REVISION=$(jq -er '.data.revision' <<< "$PROJECT")
jq '.data | {id, revision, status}' <<< "$PROJECT"Для каждого нового действия создавайте отдельный Idempotency-Key. Если результат запроса неизвестен, повторите только строку с post с теми же ключом и телом. Сохраните эти значения, если повторять будете в другом сеансе.
Проверьте цену пакета и баланс
Возьмите цену выбранного пакета из каталога и проверьте доступный баланс. Покажите цену человеку перед оплатой. В этом примере усиление покупается отдельно.
EXPECTED_AMOUNT=$(api /packages | jq -er --arg code "$PACKAGE_CODE" \
'.data[] | select(.code == $code) | .price')
jq -n --argjson amount "$EXPECTED_AMOUNT" '{expected_amount: $amount}'
api /balance | jq '.data | {available, currency}'Подтвердите оплату проекта
После подтверждения отправьте revision проекта и expected_amount в копейках. Этот запрос списывает средства с баланса аккаунта. Проверьте результат по payment_id.
PAY_KEY=$(new_key)
PAY_BODY=$(jq -cn --argjson revision "$REVISION" --argjson amount "$EXPECTED_AMOUNT" \
'{revision: $revision, expected_amount: $amount}')
PAYMENT=$(post "/projects/$PROJECT_ID/payments" "$PAY_KEY" "$PAY_BODY")
PAYMENT_ID=$(jq -er '.data.id' <<< "$PAYMENT")
api "/projects/$PROJECT_ID/payments/$PAYMENT_ID" |
jq '.data | {id, status, amount, currency}'При 409 revision_conflict или amount_changed списания нет. Перечитайте проект и каталог и снова покажите сумму человеку. При нехватке средств пополните баланс вручную. После подтверждённого отказа используйте новый ключ для новой попытки оплаты.
Получите прогресс и размещения
После оплаты читайте статус и прогресс проекта. Отчёт может быть пустым сразу после покупки. Ссылка появляется в API, когда менеджер вносит её в отчёт. Менеджер завершает проект отдельно. Для примера используйте limit=1, чтобы увидеть переход на следующую страницу.
api "/projects/$PROJECT_ID" | jq '.data | {status, progress}'
PLACEMENTS="/projects/$PROJECT_ID/placements"
PAGE=$(api "$PLACEMENTS?limit=1")
jq '{data, progress, revision, pagination}' <<< "$PAGE"
NEXT=$(jq -r '.pagination.next_cursor // empty' <<< "$PAGE")
REPORT_REVISION=$(jq -er '.revision' <<< "$PAGE")
if [ -n "$NEXT" ]; then
PAGE=$(api "$PLACEMENTS" --get --data-urlencode 'limit=1' \
--data-urlencode "cursor=$NEXT" \
--data-urlencode "revision=$REPORT_REVISION")
jq '{data, progress, revision, pagination}' <<< "$PAGE"
fi{
"id": "10000000-0000-4000-8000-000000000001",
"url": "https://forum.example.test/topic/1#message-7",
"target_url": "https://example.test/catalog",
"recorded_at": "2026-11-06T12:00:00Z",
"verification_status": "unchecked"
}Сохраняйте id каждого размещения. Если пара url и target_url меняется, размещение получает новый id. recorded_at показывает время внесения ссылки в отчёт. Для остальных страниц берите next_cursor из последнего ответа и сохраняйте revision и limit. При 409 placements_changed начните заново. Заменяйте локальный список только после успешного обхода до next_cursor=null.
Выберите уровень усиления
Используйте тот же PROJECT_ID. Проверьте amplification.can_purchase в свежей карточке проекта. Выберите доступный уровень из каталога усиления для купленного пакета. В примере это basic. Проверьте цену этого уровня перед оплатой.
PROJECT=$(api "/projects/$PROJECT_ID")
REVISION=$(jq -er '.data.revision' <<< "$PROJECT")
jq '.data.amplification | {can_purchase, unavailable_reason}' <<< "$PROJECT"
LEVEL='basic'
AMP_AMOUNT=$(api /amplification-packages | jq -er \
--arg code "$PACKAGE_CODE" --arg level "$LEVEL" \
'.data[] | select(.package_code == $code) | .levels[] | select(.level == $level) | .price')
jq -n --argjson amount "$AMP_AMOUNT" '{expected_amount: $amount}'Оплатите усиление и проверьте его статус
После отдельного подтверждения передайте level, revision проекта и expected_amount за усиление в копейках. Платёж покрывает только усиление. Проверьте результат оплаты и прочитайте состояние усиления в карточке проекта.
AMP_PAY_KEY=$(new_key)
AMP_PAY_BODY=$(jq -cn --argjson revision "$REVISION" --arg level "$LEVEL" \
--argjson amount "$AMP_AMOUNT" '{revision: $revision, level: $level, expected_amount: $amount}')
AMP_PATH="/projects/$PROJECT_ID/amplification"
AMP_PAYMENT=$(post "$AMP_PATH/payments" "$AMP_PAY_KEY" "$AMP_PAY_BODY")
AMP_PAYMENT_ID=$(jq -er '.data.id' <<< "$AMP_PAYMENT")
api "/projects/$PROJECT_ID/payments/$AMP_PAYMENT_ID" |
jq '.data | {id, purpose, status, amount, currency}'
api "/projects/$PROJECT_ID" |
jq '.data.amplification | {purchase, current}'В результате оплаты purpose=amplification. Успешная оплата подтверждает покупку. Ожидание публикаций и фактический запуск отслеживайте по current.status и current.started_at.