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

Регистрация устройства по одноразовому токену и запросу сертификата

POST /d/v1/enroll

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

Первый вызов плеера. Администратор выпускает токен регистрации в консоли (действует 24 часа, одноразовый). Плеер создает ключ ECDSA P-256, отправляет запрос сертификата для него вместе с токеном и получает сертификат устройства на один год и цепочку до центра сертификации устройств. Дальше все вызовы, кроме этого и чтения списков отзыва, предъявляют этот сертификат. Единственные учетные данные этого вызова это токен. Число вызовов с одного адреса ограничено.

Протокол устройства находится в статусе «бета»: идентификаторы (OID) подписанных атрибутов конверта пока лежат в тестовой дуге 1.3.6.1.4.1.59999.1. Зарегистрированная дуга заменит ее до того, как протокол будет объявлен стабильным.

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

Открытый вызов: учетными данными служит одноразовый токен регистрации в теле запроса.

Тело запроса

application/json

ИмяТипОбязательныйОписаниеПример
tokenstringдаОдноразовый токен регистрации из консоли."tdt_4f9c2a71b86e3d05"
csrstringдаЗапрос сертификата для ключа устройства, PEM или base64 от DER; ECDSA P-256."MIIBEjCBuAIBADAZMRcwFQYDVQQDEw5leGFtcGxlLXBsYXllcjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABA"
modelstringМодель плеера."XP-100"
firmwarestringВерсия прошивки плеера."4.2.1"
serial_nostringСерийный номер плеера."XP100-0042"
spec_versionstringВерсия спецификации соответствия, которую заявляет плеер."1.1"

Пример

{
  "token": "tdt_4f9c2a71b86e3d05",
  "csr": "MIIBEjCBuAIBADAZMRcwFQYDVQQDEw5leGFtcGxlLXBsYXllcjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABA",
  "model": "XP-100",
  "firmware": "4.2.1",
  "serial_no": "XP100-0042",
  "spec_version": "1.1"
}

Ответы

200 Устройство зарегистрировано.

application/json

ИмяТипОбязательныйОписаниеПример
device_idstring (uuid)даИдентификатор устройства; он есть в сертификате."5c0e8f3a-71d2-4b6e-9a14-d8e2f7b30c59"
certificate_pemstringдаСертификат устройства в формате PEM."-----BEGIN CERTIFICATE-----\nMIIB...\n-----END CERTIFICATE-----\n"
chain_pemstringдаЦепочка до центра сертификации устройств в формате PEM."-----BEGIN CERTIFICATE-----\nMIIB...\n-----END CERTIFICATE-----\n"
noncestringдаОдноразовое число для первого heartbeat."3b9f0c6e2a7d41f85e0b9a3c7d2e1f60"
not_afterstring (date-time)даКогда истекает сертификат."2027-10-14T09:00:00Z"
revocation_listobject | nullНовейший список отзыва: его версия и адрес.
revocation_list.versionintegerВерсия списка.42
revocation_list.urlstringАдрес списка."https://devices.tanba-ooh.kz/d/v1/revocations/42"

Пример

{
  "device_id": "5c0e8f3a-71d2-4b6e-9a14-d8e2f7b30c59",
  "certificate_pem": "-----BEGIN CERTIFICATE-----\nMIIB...\n-----END CERTIFICATE-----\n",
  "chain_pem": "-----BEGIN CERTIFICATE-----\nMIIB...\n-----END CERTIFICATE-----\n",
  "nonce": "3b9f0c6e2a7d41f85e0b9a3c7d2e1f60",
  "not_after": "2027-10-14T09:00:00Z",
  "revocation_list": {
    "version": 42,
    "url": "https://devices.tanba-ooh.kz/d/v1/revocations/42"
  }
}

Ошибки

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

СтатусЗначение
403Токен неизвестен, уже использован или просрочен (invalid_token).
422Ошибки полей (validation_failed).
429Превышен предел частоты; см. Retry-After.
503Канал устройств выключен (device_channel_disabled).
defaultОшибка в виде документа problem.

Примеры кода

curl

curl -X POST 'https://devices.tanba-ooh.kz/d/v1/enroll' \
  -H 'Content-Type: application/json' \
  -d '{
  "token": "tdt_4f9c2a71b86e3d05",
  "csr": "MIIBEjCBuAIBADAZMRcwFQYDVQQDEw5leGFtcGxlLXBsYXllcjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABA",
  "model": "XP-100",
  "firmware": "4.2.1",
  "serial_no": "XP100-0042",
  "spec_version": "1.1"
}'
Python
import requests

response = requests.post(
    "https://devices.tanba-ooh.kz/d/v1/enroll",
    headers={
        "Content-Type": "application/json",
    },
    json={
        "token": "tdt_4f9c2a71b86e3d05",
        "csr": "MIIBEjCBuAIBADAZMRcwFQYDVQQDEw5leGFtcGxlLXBsYXllcjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABA",
        "model": "XP-100",
        "firmware": "4.2.1",
        "serial_no": "XP100-0042",
        "spec_version": "1.1",
    },
)
print(response.status_code, response.text)
Go
package main

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

func main() {
	body := strings.NewReader(`{
  "token": "tdt_4f9c2a71b86e3d05",
  "csr": "MIIBEjCBuAIBADAZMRcwFQYDVQQDEw5leGFtcGxlLXBsYXllcjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABA",
  "model": "XP-100",
  "firmware": "4.2.1",
  "serial_no": "XP100-0042",
  "spec_version": "1.1"
}`)
	req, err := http.NewRequest("POST", "https://devices.tanba-ooh.kz/d/v1/enroll", body)
	if err != nil {
		panic(err)
	}
	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))
}