TAŇBA-OOH Разработчикам

Передача заявленных показов биржи

POST /api/v1/plays/claims

https://app.tanba-ooh.kz/api/v1/plays/claims

Право write:plays. Только рекламные организации (администратор рекламной платформы); сессия консоли тоже подходит. Тело это JSON, объект с массивом rows, не больше 5 МБ или 50 000 строк.

Заявка это то, что платформа утверждает, что показала. Платформа не участвует в торгах и не хранит заказы: она только сверяет заявку с показами, которые подтвердили плееры (см. GET /api/v1/plays/claims/verification). Заявки хранятся отдельно от показов плееров и никогда не тарифицируются.

Каждая строка называет конструкцию (structure_id или structure_code, но не оба), согласование (approval_number) или файл материала (creative_sha256, но не оба), целый час и число показов в этот час. deal_id (сделка) и seller_account_id (ваш аккаунт на бирже, как в source.schain) необязательны. Строка принимается только если оператор конструкции разрешил вашей организации продавать ее в этот день (и этот аккаунт). Строка хранится под ключом (организация, конструкция, согласование, час, сделка); повторная отправка заменяет прежнее значение. Строки оцениваются по одной, принятые сохраняются даже при отказе других. Причины:

ПричинаЗначение
structure_missing, structure_ambiguous, structure_not_foundНе указана конструкция, указаны обе формы, или такой конструкции нет.
approval_missing, approval_ambiguousНе указано ни согласование, ни файл, либо указаны оба.
approval_not_found, approval_not_for_structureНет подписанного согласования с таким номером или оно не покрывает конструкцию.
creative_not_found, creative_ambiguousНет согласования с таким файлом для этой конструкции в этот час, либо их несколько (назовите номер).
seller_not_authorisedОператор не разрешил вашей организации (и аккаунту) продавать эту конструкцию в этот день.
hour_invalid, hour_not_whole, hour_in_future, hour_too_oldНе час ISO 8601, не ровно на час, еще не начался или начался больше 62 дней назад.
plays_invalidНе целое число, не меньше 0.
deal_id_invalid, seller_account_invalidНедопустимые символы или длина.
duplicate_rowТакая же строка уже была в этом пакете.

Аутентификация

Ключ API в заголовке Authorization или сессия консоли.

Право доступа: write:plays

Тело запроса

application/json

ИмяТипОбязательныйОписаниеПример
rowsarray of objectдаСтроки заявки: по одной на конструкцию, согласование, час и сделку.
rows[].structure_idstring (uuid)Идентификатор конструкции; укажите его или structure_code, но не оба."b7e4a2c9-0d1f-4a68-8e35-91c7f2d40b16"
rows[].structure_codestringКод конструкции; укажите его или structure_id, но не оба."ALM-0012"
rows[].approval_numberstringНомер согласования; укажите его или creative_sha256."TNB-2026-000123"
rows[].creative_sha256stringSHA-256 файла; согласование это то, что покрывает конструкцию в этот час."2419fe2d001c9185b3b903283894a5d955f45a57d1eaf1c6b787759650f00a17"
rows[].hourstringISO 8601, ровно на час; час без смещения читается как время Asia/Almaty."2026-10-06T14:00:00+05:00"
rows[].playsintegerЧисло показов, которые, по заявлению платформы, она показала в этот час.118
rows[].deal_idstringСделка, в рамках которой шли показы, символы A-Za-z0-9._:-; входит в идентичность строки."deal-4411"
rows[].seller_account_idstringВаш аккаунт на бирже; оператор должен был его разрешить."acc-77"

Пример

{
  "rows": [
    {
      "structure_code": "ALM-0012",
      "approval_number": "TNB-2026-000123",
      "hour": "2026-10-06T14:00:00+05:00",
      "plays": 118,
      "deal_id": "deal-4411"
    },
    {
      "structure_code": "ALM-0012",
      "creative_sha256": "2419fe2d001c9185b3b903283894a5d955f45a57d1eaf1c6b787759650f00a17",
      "hour": "2026-10-06T15:00:00+05:00",
      "plays": 120
    }
  ]
}

Ответы

200 Пакет прочитан; что сохранено, видно по строкам.

application/json

ИмяТипОбязательныйОписаниеПример
batch_idstring (uuid)даИдентификатор пакета."0b1c3a52-6f0e-4c2e-9d3a-2f5d1e7a9c10"
receivedintegerдаЧисло строк, прочитанных из тела.2
acceptedintegerдаЧисло сохраненных строк.1
refusedintegerдаЧисло отклоненных строк.1
rowsarray of objectдаЗапись на каждую строку, в порядке тела.
rows[].rowintegerдаПозиция в теле, с 1.1
rows[].statusstringдаСохранена ли строка. accepted, refused
rows[].reasonstringЕсть у отклоненных строк."seller_not_authorised"

Пример

{
  "batch_id": "0b1c3a52-6f0e-4c2e-9d3a-2f5d1e7a9c10",
  "received": 2,
  "accepted": 1,
  "refused": 1,
  "rows": [
    {
      "row": 1,
      "status": "accepted"
    },
    {
      "row": 2,
      "status": "refused",
      "reason": "seller_not_authorised"
    }
  ]
}

Ошибки

Ошибки приходят документом problem (application/problem+json) со стабильным полем code.

СтатусЗначение
400Ошибка в виде документа problem.
401Нет действительной сессии или ключа API (unauthenticated, session_expired, invalid_api_key).
403Роль или право ключа этого не допускает (forbidden, key_scope_denied, key_route_denied).
413Ошибка в виде документа problem.
422Ошибки полей (validation_failed).
defaultОшибка в виде документа problem.

Примеры кода

curl

curl -X POST 'https://app.tanba-ooh.kz/api/v1/plays/claims' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
  "rows": [
    {
      "structure_code": "ALM-0012",
      "approval_number": "TNB-2026-000123",
      "hour": "2026-10-06T14:00:00+05:00",
      "plays": 118,
      "deal_id": "deal-4411"
    },
    {
      "structure_code": "ALM-0012",
      "creative_sha256": "2419fe2d001c9185b3b903283894a5d955f45a57d1eaf1c6b787759650f00a17",
      "hour": "2026-10-06T15:00:00+05:00",
      "plays": 120
    }
  ]
}'
Python
import requests

response = requests.post(
    "https://app.tanba-ooh.kz/api/v1/plays/claims",
    headers={
        "Authorization": "Bearer YOUR_API_KEY",
        "Content-Type": "application/json",
    },
    json={
        "rows": [
            {
                "structure_code": "ALM-0012",
                "approval_number": "TNB-2026-000123",
                "hour": "2026-10-06T14:00:00+05:00",
                "plays": 118,
                "deal_id": "deal-4411",
            },
            {
                "structure_code": "ALM-0012",
                "creative_sha256": "2419fe2d001c9185b3b903283894a5d955f45a57d1eaf1c6b787759650f00a17",
                "hour": "2026-10-06T15:00:00+05:00",
                "plays": 120,
            },
        ],
    },
)
print(response.status_code, response.text)
Go
package main

import (
	"fmt"
	"io"
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{
  "rows": [
    {
      "structure_code": "ALM-0012",
      "approval_number": "TNB-2026-000123",
      "hour": "2026-10-06T14:00:00+05:00",
      "plays": 118,
      "deal_id": "deal-4411"
    },
    {
      "structure_code": "ALM-0012",
      "creative_sha256": "2419fe2d001c9185b3b903283894a5d955f45a57d1eaf1c6b787759650f00a17",
      "hour": "2026-10-06T15:00:00+05:00",
      "plays": 120
    }
  ]
}`)
	req, err := http.NewRequest("POST", "https://app.tanba-ooh.kz/api/v1/plays/claims", body)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
	req.Header.Set("Content-Type", "application/json")
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	data, _ := io.ReadAll(resp.Body)
	fmt.Println(resp.Status, string(data))
}