Подтверждение подписанной команды
POST /d/v1/commands/{id}/ack
https://devices.tanba-ooh.kz/d/v1/commands/{id}/ack
Подпись покрывает только тело, поэтому тело называет команду, на которую отвечает. command_id должен совпадать с идентификатором в пути, иначе ответ 400 command_id_mismatch; так подписанное подтверждение одной команды нельзя отправить на другую. Подтверждение без command_id пока принимается и считается, потом будет отклоняться.
Аутентификация
Клиентский сертификат устройства (взаимный TLS) и подпись тела ключом устройства.
Параметры
| Имя | Где | Тип | Обязательный | Описание | Пример |
|---|---|---|---|---|---|
X-Tanba-Signature | заголовок | string | да | Подпись ES256 точных байтов тела ключом устройства, сырые r||s (64 байта), base64url без заполнения. | q3J2y0uO8e1m4n7pXc5Zk9d2Wv6Tg0hLsB-aRfN1YjE6uHxPzD3oVtKiC8wMbQe2nSgA4rUl7yFhJ9XcT0dZaw |
id | путь | string (uuid) | да | Идентификатор подтверждаемой команды. | 0b1c3a52-6f0e-4c2e-9d3a-2f5d1e7a9c10 |
Тело запроса
application/json
| Имя | Тип | Обязательный | Описание | Пример |
|---|---|---|---|---|
command_id | string (uuid) | Подтверждаемая команда; она должна совпадать с идентификатором в пути. | "0b1c3a52-6f0e-4c2e-9d3a-2f5d1e7a9c10" | |
ok | boolean | да | True, если плеер выполнил команду. | true |
state_snapshot | object | Состояние плеера после команды. |
Пример
{
"command_id": "0b1c3a52-6f0e-4c2e-9d3a-2f5d1e7a9c10",
"ok": true,
"state_snapshot": {
"state": "cutoff"
}
}
Ответы
200 Записано.
application/json
| Имя | Тип | Обязательный | Описание | Пример |
|---|---|---|---|---|
status | string | да | Всегда recorded. recorded |
Пример
{
"status": "recorded"
}
Ошибки
Ошибки приходят документом problem (application/problem+json) со стабильным полем code.
| Статус | Значение |
|---|---|
| 400 | Тело не JSON (invalid_json) либо command_id отличается от пути (command_id_mismatch). |
| 404 | Ничего нет или вызывающему это не видно. |
| default | Ошибка в виде документа problem. |
Примеры кода
curl
curl -X POST 'https://devices.tanba-ooh.kz/d/v1/commands/0b1c3a52-6f0e-4c2e-9d3a-2f5d1e7a9c10/ack' \
-H 'X-Tanba-Signature: q3J2y0uO8e1m4n7pXc5Zk9d2Wv6Tg0hLsB-aRfN1YjE6uHxPzD3oVtKiC8wMbQe2nSgA4rUl7yFhJ9XcT0dZaw' \
-H 'Content-Type: application/json' \
-d '{
"command_id": "0b1c3a52-6f0e-4c2e-9d3a-2f5d1e7a9c10",
"ok": true,
"state_snapshot": {
"state": "cutoff"
}
}'
Python
import requests
response = requests.post(
"https://devices.tanba-ooh.kz/d/v1/commands/0b1c3a52-6f0e-4c2e-9d3a-2f5d1e7a9c10/ack",
headers={
"X-Tanba-Signature": "q3J2y0uO8e1m4n7pXc5Zk9d2Wv6Tg0hLsB-aRfN1YjE6uHxPzD3oVtKiC8wMbQe2nSgA4rUl7yFhJ9XcT0dZaw",
"Content-Type": "application/json",
},
json={
"command_id": "0b1c3a52-6f0e-4c2e-9d3a-2f5d1e7a9c10",
"ok": True,
"state_snapshot": {
"state": "cutoff",
},
},
)
print(response.status_code, response.text)
Go
package main
import (
"fmt"
"io"
"net/http"
"strings"
)
func main() {
body := strings.NewReader(`{
"command_id": "0b1c3a52-6f0e-4c2e-9d3a-2f5d1e7a9c10",
"ok": true,
"state_snapshot": {
"state": "cutoff"
}
}`)
req, err := http.NewRequest("POST", "https://devices.tanba-ooh.kz/d/v1/commands/0b1c3a52-6f0e-4c2e-9d3a-2f5d1e7a9c10/ack", body)
if err != nil {
panic(err)
}
req.Header.Set("X-Tanba-Signature", "q3J2y0uO8e1m4n7pXc5Zk9d2Wv6Tg0hLsB-aRfN1YjE6uHxPzD3oVtKiC8wMbQe2nSgA4rUl7yFhJ9XcT0dZaw")
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))
}