TAŇBA-OOH Әзірлеушілерге

Hash-chained log segment, in answer to an audit_export command

POST /d/v1/logs

https://devices.tanba-ooh.kz/d/v1/logs

Анықтамалықтың техникалық мәтіні ағылшын тілінде жазылған.

Body (signed like telemetry): {command_id, entries: [{seq, at, kind, data, prev, hash}]}. The platform checks the chain, that it continues from the last export and that it contains the head hash last reported in a heartbeat. The answer holds the verdict; a segment that does not verify raises the city event device_log_tampered. One answer per command; a repeat returns the stored one.

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

Құрылғының клиенттік сертификаты (өзара TLS) және құрылғы кілтімен жасалған дене қолтаңбасы.

Параметрлер

АтауыОрныТүріМіндеттіСипаттамаМысал
X-Tanba-SignatureтақырыпstringиәES256 signature of the exact bytes of the body by the device key, raw r||s (64 bytes), base64url without padding.q3J2y0uO8e1m4n7pXc5Zk9d2Wv6Tg0hLsB-aRfN1YjE6uHxPzD3oVtKiC8wMbQe2nSgA4rUl7yFhJ9XcT0dZaw

Сұраудың денесі

application/json

АтауыТүріМіндеттіСипаттамаМысал
command_idstring (uuid)иәThe audit_export command this segment answers."0b1c3a52-6f0e-4c2e-9d3a-2f5d1e7a9c10"
entriesarray of objectиәThe log lines since the last export, in order.
entries[].seqintegerиәNumber of the line.4021
entries[].atstring (date-time)иәWhen the line was written."2026-10-14T09:00:00Z"
entries[].kindstringиәKind of the line."play"
entries[].dataobjectContent of the line.
entries[].prevstringиәHash of the line before."9f2b6a41c7d83e05a1b4c6d7e8f90123456789abcdef0123456789abcdef0123"
entries[].hashstringиәHash of this line."4d7a1c0e9b3f58a26c4e1d07b9a3f5c8e2d60b14a7c93e5f8d1b2a6c0e4f7391"

Мысал

{
  "command_id": "0b1c3a52-6f0e-4c2e-9d3a-2f5d1e7a9c10",
  "entries": [
    {
      "seq": 4021,
      "at": "2026-10-14T09:00:00Z",
      "kind": "play",
      "data": {
        "approval_number": "TNB-2026-000123"
      },
      "prev": "9f2b6a41c7d83e05a1b4c6d7e8f90123456789abcdef0123456789abcdef0123",
      "hash": "4d7a1c0e9b3f58a26c4e1d07b9a3f5c8e2d60b14a7c93e5f8d1b2a6c0e4f7391"
    }
  ]
}

Жауаптар

200 The verdict.

application/json

АтауыТүріМіндеттіСипаттамаМысал
resultstringиәWhat the checks found. ok, chain_broken, continuity_broken, head_mismatch
okbooleanиәTrue when every check passed.true
entriesintegerиәNumber of lines in the segment.120
head_hashstringиәHash of the last line of the segment."4d7a1c0e9b3f58a26c4e1d07b9a3f5c8e2d60b14a7c93e5f8d1b2a6c0e4f7391"
duplicatebooleanиәTrue when this is a repeat and the stored verdict is returned.false

Мысал

{
  "result": "ok",
  "ok": true,
  "entries": 120,
  "head_hash": "4d7a1c0e9b3f58a26c4e1d07b9a3f5c8e2d60b14a7c93e5f8d1b2a6c0e4f7391",
  "duplicate": false
}

Қателер

Қателер problem құжаты (application/problem+json) түрінде, тұрақты code өрісімен келеді.

МәртебесіМағынасы
401The signature does not verify, or the device is unknown or revoked.
413The segment is over 4 MB.
defaultAn error as a problem document.

Код мысалдары

curl

curl -X POST 'https://devices.tanba-ooh.kz/d/v1/logs' \
  -H 'X-Tanba-Signature: q3J2y0uO8e1m4n7pXc5Zk9d2Wv6Tg0hLsB-aRfN1YjE6uHxPzD3oVtKiC8wMbQe2nSgA4rUl7yFhJ9XcT0dZaw' \
  -H 'Content-Type: application/json' \
  -d '{
  "command_id": "0b1c3a52-6f0e-4c2e-9d3a-2f5d1e7a9c10",
  "entries": [
    {
      "seq": 4021,
      "at": "2026-10-14T09:00:00Z",
      "kind": "play",
      "data": {
        "approval_number": "TNB-2026-000123"
      },
      "prev": "9f2b6a41c7d83e05a1b4c6d7e8f90123456789abcdef0123456789abcdef0123",
      "hash": "4d7a1c0e9b3f58a26c4e1d07b9a3f5c8e2d60b14a7c93e5f8d1b2a6c0e4f7391"
    }
  ]
}'
Python
import requests

response = requests.post(
    "https://devices.tanba-ooh.kz/d/v1/logs",
    headers={
        "X-Tanba-Signature": "q3J2y0uO8e1m4n7pXc5Zk9d2Wv6Tg0hLsB-aRfN1YjE6uHxPzD3oVtKiC8wMbQe2nSgA4rUl7yFhJ9XcT0dZaw",
        "Content-Type": "application/json",
    },
    json={
        "command_id": "0b1c3a52-6f0e-4c2e-9d3a-2f5d1e7a9c10",
        "entries": [
            {
                "seq": 4021,
                "at": "2026-10-14T09:00:00Z",
                "kind": "play",
                "data": {
                    "approval_number": "TNB-2026-000123",
                },
                "prev": "9f2b6a41c7d83e05a1b4c6d7e8f90123456789abcdef0123456789abcdef0123",
                "hash": "4d7a1c0e9b3f58a26c4e1d07b9a3f5c8e2d60b14a7c93e5f8d1b2a6c0e4f7391",
            },
        ],
    },
)
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",
  "entries": [
    {
      "seq": 4021,
      "at": "2026-10-14T09:00:00Z",
      "kind": "play",
      "data": {
        "approval_number": "TNB-2026-000123"
      },
      "prev": "9f2b6a41c7d83e05a1b4c6d7e8f90123456789abcdef0123456789abcdef0123",
      "hash": "4d7a1c0e9b3f58a26c4e1d07b9a3f5c8e2d60b14a7c93e5f8d1b2a6c0e4f7391"
    }
  ]
}`)
	req, err := http.NewRequest("POST", "https://devices.tanba-ooh.kz/d/v1/logs", 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))
}