DokumentasiENarsa.technology

Dokumentasi / AI Box Dan Software Analitik Video / Referensi API

API Platform AI Box

Bagian dasbor ARSA AI Box Series yang sama di setiap produk: lokasi dan zonanya, kamera dan apa yang digambar di atasnya, video langsung dan rekaman, peringatan, kontak dan webhook peringatan, sirene dan relai, laporan, serta webhook untuk integrator. Setiap produk menambahkan API-nya sendiri di samping API ini, di bawah /api/<product>/v1.

Memanggil API

Kirim token akun API di header Authorization: Authorization: Bearer <API_KEY>. Admin membuat akun di dasbor (Akun API); token ditampilkan satu kali. Token hanya melihat lokasi tempat akunnya memiliki peran, dan hanya apa yang diizinkan cakupannya (read, write, export, personal_data). Setiap operasi menyebutkan siapa yang dapat memanggilnya dan cakupan yang diperlukan. Dasbor melayani HTTPS dengan sertifikat milik perangkat: Admin mengunduh salinannya (box.pem) di dasbor (Sistem, lalu Akun API, lalu Unduh sertifikat perangkat) beserta sidik jari SHA-256-nya, dan token dengan read dapat mengambilnya dengan getBoxCertificate. Periksa sidik jarinya sebelum klien Anda memercayai berkas itu.

Galat berupa problem details RFC 9457 (application/problem+json) dengan code yang tetap. Waktu memakai RFC 3339; angka per jam dan per hari mengikuti zona waktu lokasi. Daftar panjang dibagi per halaman: berikan limit, lalu next_before dari jawaban sebagai before. Panggilan dibatasi per akun API (bawaan 600 per menit; setelah itu 429 dengan Retry-After).

Webhook untuk Integrator

Akun API dapat mendaftarkan penerimanya sendiri (/webhook-subscriptions): peristiwa deteksi dalam batch, ringkasan berkala dan peringatan, ditandatangani dengan cara Standard Webhooks. Panduan webhook menjelaskan isi kiriman, tanda tangan dan percobaan ulang.

1.0.0

Lokasi Dan Zona

Lokasi (pabrik, toko, koridor) dan zona di dalamnya.

Lokasi Tempat Akun API Memiliki Peran

GET/sites

Siapa yang dapat memanggil: Setiap akun API. Cakupan token: read.

Respons

StatusArti
200OK
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)

Permintaan

curl -s -X GET "https://<BOX_HOST>/api/v1/sites" \
  -H "Authorization: Bearer <API_KEY>"
import requests

r = requests.get(
    "https://<BOX_HOST>/api/v1/sites",
    headers={"Authorization": "Bearer <API_KEY>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/sites", {
  method: "GET",
  headers: { "Authorization": "Bearer <API_KEY>" },
});
console.log(r.status, await r.text());

Respons 200

{
  "items": [
    {
      "id": 1,
      "name": "North Plant",
      "timezone": "Asia/Jakarta",
      "created": "2026-10-01T02:00:00Z",
      "version": 4,
      "my_role": "viewer",
      "location": {
        "lat": -6.2,
        "lon": 106.8
      },
      "area": null,
      "zones": 3
    },
    {
      "id": 2,
      "name": "Warehouse B",
      "timezone": "Asia/Jakarta",
      "created": "2026-10-03T02:00:00Z",
      "version": 1,
      "my_role": "admin",
      "location": null,
      "area": null,
      "zones": 0
    }
  ]
}

Satu Lokasi

GET/sites/{id}

Siapa yang dapat memanggil: Akun dengan peran (Pemantau atau Admin) di lokasi tersebut. Cakupan token: read.

Parameter

KolomTipeDeskripsi
idwajib pathinteger

Respons

StatusArti
200OK
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)

Permintaan

curl -s -X GET "https://<BOX_HOST>/api/v1/sites/1" \
  -H "Authorization: Bearer <API_KEY>"
import requests

r = requests.get(
    "https://<BOX_HOST>/api/v1/sites/1",
    headers={"Authorization": "Bearer <API_KEY>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/sites/1", {
  method: "GET",
  headers: { "Authorization": "Bearer <API_KEY>" },
});
console.log(r.status, await r.text());

Respons 200

{
  "id": 1,
  "name": "North Plant",
  "timezone": "Asia/Jakarta",
  "created": "2026-10-01T02:00:00Z",
  "version": 4,
  "my_role": "viewer",
  "location": {
    "lat": -6.2,
    "lon": 106.8
  },
  "area": null,
  "zones": 3
}

Ganti Nama Lokasi, Ubah Zona Waktunya, Atau Tempatkan Di Peta (Titik, Batas)

PATCH/sites/{id}

Siapa yang dapat memanggil: Akun yang menjadi Admin di lokasi tersebut. Cakupan token: write.

Parameter

KolomTipeDeskripsi
idwajib pathinteger

Body

KolomTipeDeskripsi
namestring
timezonestring
locationone ofTitik lokasi; null menghapusnya.
areaone ofBatas wilayah; null menghapusnya.

Respons

StatusArti
200OK
400Permintaan tidak valid
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)
409Konflik
413Isi permintaan terlalu besar
415Bukan JSON
422Isi permintaan tidak valid

Permintaan

curl -s -X PATCH "https://<BOX_HOST>/api/v1/sites/1" \
  -H "Authorization: Bearer <API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{"name":"Main gate","timezone":"Asia/Jakarta","location":{"lat":-6.2,"lon":106.8},"area":[[12,12],[12,12],[12,12]]}'
import requests

r = requests.patch(
    "https://<BOX_HOST>/api/v1/sites/1",
    headers={"Authorization": "Bearer <API_KEY>"},
    json={
      "name": "Main gate",
      "timezone": "Asia/Jakarta",
      "location": {
        "lat": -6.2,
        "lon": 106.8
      },
      "area": [
        [
          12,
          12
        ],
        [
          12,
          12
        ],
        [
          12,
          12
        ]
      ]
    },
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/sites/1", {
  method: "PATCH",
  headers: { "Authorization": "Bearer <API_KEY>", "Content-Type": "application/json" },
  body: JSON.stringify({
    "name": "Main gate",
    "timezone": "Asia/Jakarta",
    "location": {
      "lat": -6.2,
      "lon": 106.8
    },
    "area": [
      [
        12,
        12
      ],
      [
        12,
        12
      ],
      [
        12,
        12
      ]
    ]
  }),
});
console.log(r.status, await r.text());

Respons 200

{
  "id": 1,
  "name": "Main gate",
  "timezone": "Asia/Jakarta",
  "created": "2026-11-02T08:00:00Z",
  "version": 3,
  "my_role": "admin",
  "location": {
    "lat": -6.2,
    "lon": 106.8
  },
  "area": [
    [
      12,
      12
    ],
    [
      12,
      12
    ],
    [
      12,
      12
    ]
  ],
  "zones": 12
}

Zona Lokasi

GET/sites/{id}/zones

Siapa yang dapat memanggil: Akun dengan peran (Pemantau atau Admin) di lokasi tersebut. Cakupan token: read.

Parameter

KolomTipeDeskripsi
idwajib pathinteger

Respons

StatusArti
200OK
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)

Permintaan

curl -s -X GET "https://<BOX_HOST>/api/v1/sites/1/zones" \
  -H "Authorization: Bearer <API_KEY>"
import requests

r = requests.get(
    "https://<BOX_HOST>/api/v1/sites/1/zones",
    headers={"Authorization": "Bearer <API_KEY>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/sites/1/zones", {
  method: "GET",
  headers: { "Authorization": "Bearer <API_KEY>" },
});
console.log(r.status, await r.text());

Respons 200

{
  "items": [
    {
      "id": 1,
      "site_id": 1,
      "name": "Main gate",
      "area": [
        [
          12,
          12
        ],
        [
          12,
          12
        ],
        [
          12,
          12
        ]
      ],
      "created": "2026-11-02T08:00:00Z",
      "version": 3
    }
  ]
}

Tambahkan Zona Ke Lokasi

POST/sites/{id}/zones

Siapa yang dapat memanggil: Akun yang menjadi Admin di lokasi tersebut. Cakupan token: write.

Parameter

KolomTipeDeskripsi
idwajib pathinteger

Body

KolomTipeDeskripsi
namewajibstring
areaone of

Respons

StatusArti
201Dibuat
400Permintaan tidak valid
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)
409Konflik
413Isi permintaan terlalu besar
415Bukan JSON
422Isi permintaan tidak valid

Permintaan

curl -s -X POST "https://<BOX_HOST>/api/v1/sites/1/zones" \
  -H "Authorization: Bearer <API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{"name":"Main gate","area":[[12,12],[12,12],[12,12]]}'
import requests

r = requests.post(
    "https://<BOX_HOST>/api/v1/sites/1/zones",
    headers={"Authorization": "Bearer <API_KEY>"},
    json={
      "name": "Main gate",
      "area": [
        [
          12,
          12
        ],
        [
          12,
          12
        ],
        [
          12,
          12
        ]
      ]
    },
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/sites/1/zones", {
  method: "POST",
  headers: { "Authorization": "Bearer <API_KEY>", "Content-Type": "application/json" },
  body: JSON.stringify({
    "name": "Main gate",
    "area": [
      [
        12,
        12
      ],
      [
        12,
        12
      ],
      [
        12,
        12
      ]
    ]
  }),
});
console.log(r.status, await r.text());

Respons 201

{
  "id": 1,
  "site_id": 1,
  "name": "Main gate",
  "area": [
    [
      12,
      12
    ],
    [
      12,
      12
    ],
    [
      12,
      12
    ]
  ],
  "created": "2026-11-02T08:00:00Z",
  "version": 3
}

Ganti Nama Zona Atau Ubah Garis Batasnya

PATCH/sites/{id}/zones/{zone}

Siapa yang dapat memanggil: Akun yang menjadi Admin di lokasi tersebut. Cakupan token: write.

Parameter

KolomTipeDeskripsi
idwajib pathinteger
zonewajib pathinteger

Body

KolomTipeDeskripsi
namestring
areaone ofGaris batas; null menghapusnya.

Respons

StatusArti
200OK
400Permintaan tidak valid
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)
409Konflik
413Isi permintaan terlalu besar
415Bukan JSON
422Isi permintaan tidak valid

Permintaan

curl -s -X PATCH "https://<BOX_HOST>/api/v1/sites/1/zones/1" \
  -H "Authorization: Bearer <API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{"name":"Main gate","area":[[12,12],[12,12],[12,12]]}'
import requests

r = requests.patch(
    "https://<BOX_HOST>/api/v1/sites/1/zones/1",
    headers={"Authorization": "Bearer <API_KEY>"},
    json={
      "name": "Main gate",
      "area": [
        [
          12,
          12
        ],
        [
          12,
          12
        ],
        [
          12,
          12
        ]
      ]
    },
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/sites/1/zones/1", {
  method: "PATCH",
  headers: { "Authorization": "Bearer <API_KEY>", "Content-Type": "application/json" },
  body: JSON.stringify({
    "name": "Main gate",
    "area": [
      [
        12,
        12
      ],
      [
        12,
        12
      ],
      [
        12,
        12
      ]
    ]
  }),
});
console.log(r.status, await r.text());

Respons 200

{
  "id": 1,
  "site_id": 1,
  "name": "Main gate",
  "area": [
    [
      12,
      12
    ],
    [
      12,
      12
    ],
    [
      12,
      12
    ]
  ],
  "created": "2026-11-02T08:00:00Z",
  "version": 3
}

Hapus Zona (Kameranya Tetap Di Lokasi, Tanpa Zona)

DELETE/sites/{id}/zones/{zone}

Siapa yang dapat memanggil: Akun yang menjadi Admin di lokasi tersebut. Cakupan token: write.

Parameter

KolomTipeDeskripsi
idwajib pathinteger
zonewajib pathinteger

Respons

StatusArti
204Dihapus
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)

Permintaan

curl -s -X DELETE "https://<BOX_HOST>/api/v1/sites/1/zones/1" \
  -H "Authorization: Bearer <API_KEY>"
import requests

r = requests.delete(
    "https://<BOX_HOST>/api/v1/sites/1/zones/1",
    headers={"Authorization": "Bearer <API_KEY>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/sites/1/zones/1", {
  method: "DELETE",
  headers: { "Authorization": "Bearer <API_KEY>" },
});
console.log(r.status, await r.text());

Kamera

Kamera, alirannya, apa yang digambar di atasnya (garis, zona, lajur) dan cuplikan gambar.

Kamera Di Lokasi Akun API

GET/cameras

Siapa yang dapat memanggil: Akun dengan peran (Pemantau atau Admin) di lokasi tersebut. Cakupan token: read.

Respons

StatusArti
200OK
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
502Mesin analitik menolak permintaan (engine_refused)
503Mesin analitik tidak menjawab (engine_unavailable); coba lagi setelah Retry-After

Permintaan

curl -s -X GET "https://<BOX_HOST>/api/v1/cameras" \
  -H "Authorization: Bearer <API_KEY>"
import requests

r = requests.get(
    "https://<BOX_HOST>/api/v1/cameras",
    headers={"Authorization": "Bearer <API_KEY>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/cameras", {
  method: "GET",
  headers: { "Authorization": "Bearer <API_KEY>" },
});
console.log(r.status, await r.text());

Respons 200

{
  "items": [
    {
      "id": 11,
      "name": "Gate 1",
      "site_id": 1,
      "zone_id": 2,
      "password_set": true,
      "over_licence": false,
      "status": {
        "running": true,
        "capture": "streaming"
      }
    },
    {
      "id": 12,
      "name": "Loading Bay",
      "site_id": 1,
      "zone_id": null,
      "password_set": true,
      "over_licence": false,
      "status": {
        "running": true,
        "capture": "streaming"
      }
    }
  ]
}

Tambahkan Kamera Ke Lokasi

POST/cameras

Siapa yang dapat memanggil: Akun yang menjadi Admin di lokasi tersebut. Cakupan token: write.

Parameter

KolomTipeDeskripsi
Idempotency-Key headerstring

Body

KolomTipeDeskripsi
site_idwajibinteger
namewajibstring
rtsp_urlwajibstring
hoststring
usernamestring
passwordstring
widthinteger
heightinteger
fpsinteger

Respons

StatusArti
201Dibuat
400Permintaan tidak valid
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)
409Konflik
413Isi permintaan terlalu besar
415Bukan JSON
422Isi permintaan tidak valid
502Mesin analitik menolak permintaan (engine_refused)
503Mesin analitik tidak menjawab (engine_unavailable); coba lagi setelah Retry-After

Permintaan

curl -s -X POST "https://<BOX_HOST>/api/v1/cameras" \
  -H "Authorization: Bearer <API_KEY>" \
  -H "Idempotency-Key: <IDEMPOTENCY_KEY>" \
  -H "Content-Type: application/json" \
  -d '{"site_id":1,"name":"Main gate","rtsp_url":"https://<RECEIVER_HOST>/hooks/arsa","host":"<host>","username":"<username>","password":"<password>","width":12,"height":12,"fps":12}'
import requests

r = requests.post(
    "https://<BOX_HOST>/api/v1/cameras",
    headers={"Authorization": "Bearer <API_KEY>", "Idempotency-Key": "<IDEMPOTENCY_KEY>"},
    json={
      "site_id": 1,
      "name": "Main gate",
      "rtsp_url": "https://<RECEIVER_HOST>/hooks/arsa",
      "host": "<host>",
      "username": "<username>",
      "password": "<password>",
      "width": 12,
      "height": 12,
      "fps": 12
    },
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/cameras", {
  method: "POST",
  headers: { "Authorization": "Bearer <API_KEY>", "Idempotency-Key": "<IDEMPOTENCY_KEY>", "Content-Type": "application/json" },
  body: JSON.stringify({
    "site_id": 1,
    "name": "Main gate",
    "rtsp_url": "https://<RECEIVER_HOST>/hooks/arsa",
    "host": "<host>",
    "username": "<username>",
    "password": "<password>",
    "width": 12,
    "height": 12,
    "fps": 12
  }),
});
console.log(r.status, await r.text());

Respons 201

{
  "id": 1,
  "name": "Main gate",
  "rtsp_url": "https://<RECEIVER_HOST>/hooks/arsa",
  "password_set": true,
  "site_id": 1,
  "status": {},
  "over_licence": true,
  "zone_id": 1
}

Satu Kamera

GET/cameras/{id}

Siapa yang dapat memanggil: Akun dengan peran (Pemantau atau Admin) di lokasi tersebut. Cakupan token: read.

Parameter

KolomTipeDeskripsi
idwajib pathinteger

Respons

StatusArti
200OK
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)
502Mesin analitik menolak permintaan (engine_refused)
503Mesin analitik tidak menjawab (engine_unavailable); coba lagi setelah Retry-After

Permintaan

curl -s -X GET "https://<BOX_HOST>/api/v1/cameras/1" \
  -H "Authorization: Bearer <API_KEY>"
import requests

r = requests.get(
    "https://<BOX_HOST>/api/v1/cameras/1",
    headers={"Authorization": "Bearer <API_KEY>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/cameras/1", {
  method: "GET",
  headers: { "Authorization": "Bearer <API_KEY>" },
});
console.log(r.status, await r.text());

Respons 200

{
  "id": 1,
  "name": "Main gate",
  "rtsp_url": "https://<RECEIVER_HOST>/hooks/arsa",
  "password_set": true,
  "site_id": 1,
  "status": {},
  "over_licence": true,
  "zone_id": 1
}

Ubah Kamera (JSON Merge Patch, If-Match)

PATCH/cameras/{id}

Siapa yang dapat memanggil: Akun yang menjadi Admin di lokasi tersebut. Cakupan token: write.

Parameter

KolomTipeDeskripsi
idwajib pathinteger
If-Match headerstringETag yang dibaca sebelumnya; wajib untuk perubahan.

Respons

StatusArti
200OK
400Permintaan tidak valid
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)
412ETag di If-Match sudah usang
413Isi permintaan terlalu besar
415Bukan JSON
422Isi permintaan tidak valid
428If-Match wajib diisi
502Mesin analitik menolak permintaan (engine_refused)
503Mesin analitik tidak menjawab (engine_unavailable); coba lagi setelah Retry-After

Permintaan

curl -s -X PATCH "https://<BOX_HOST>/api/v1/cameras/1" \
  -H "Authorization: Bearer <API_KEY>" \
  -H "If-Match: <IF_MATCH>"
import requests

r = requests.patch(
    "https://<BOX_HOST>/api/v1/cameras/1",
    headers={"Authorization": "Bearer <API_KEY>", "If-Match": "<IF_MATCH>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/cameras/1", {
  method: "PATCH",
  headers: { "Authorization": "Bearer <API_KEY>", "If-Match": "<IF_MATCH>" },
});
console.log(r.status, await r.text());

Respons 200

{
  "id": 1,
  "name": "Main gate",
  "rtsp_url": "https://<RECEIVER_HOST>/hooks/arsa",
  "password_set": true,
  "site_id": 1,
  "status": {},
  "over_licence": true,
  "zone_id": 1
}

Hapus Kamera

DELETE/cameras/{id}

Siapa yang dapat memanggil: Akun yang menjadi Admin di lokasi tersebut. Cakupan token: write.

Parameter

KolomTipeDeskripsi
idwajib pathinteger
If-Match headerstringETag yang dibaca sebelumnya; wajib untuk perubahan.

Respons

StatusArti
204Dihapus
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)
412ETag di If-Match sudah usang
502Mesin analitik menolak permintaan (engine_refused)
503Mesin analitik tidak menjawab (engine_unavailable); coba lagi setelah Retry-After

Permintaan

curl -s -X DELETE "https://<BOX_HOST>/api/v1/cameras/1" \
  -H "Authorization: Bearer <API_KEY>" \
  -H "If-Match: <IF_MATCH>"
import requests

r = requests.delete(
    "https://<BOX_HOST>/api/v1/cameras/1",
    headers={"Authorization": "Bearer <API_KEY>", "If-Match": "<IF_MATCH>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/cameras/1", {
  method: "DELETE",
  headers: { "Authorization": "Bearer <API_KEY>", "If-Match": "<IF_MATCH>" },
});
console.log(r.status, await r.text());

Tempatkan Kamera Di Salah Satu Zona Lokasinya, Atau Tanpa Zona

PUT/cameras/{id}/zone

Siapa yang dapat memanggil: Akun yang menjadi Admin di lokasi tersebut. Cakupan token: write.

Parameter

KolomTipeDeskripsi
idwajib pathinteger

Body

KolomTipeDeskripsi
zone_idwajibintegerZona di lokasi kamera itu sendiri, atau null untuk tanpa zona.

Respons

StatusArti
200OK
400Permintaan tidak valid
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)
409Konflik
413Isi permintaan terlalu besar
415Bukan JSON
422Isi permintaan tidak valid

Permintaan

curl -s -X PUT "https://<BOX_HOST>/api/v1/cameras/1/zone" \
  -H "Authorization: Bearer <API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{"zone_id":1}'
import requests

r = requests.put(
    "https://<BOX_HOST>/api/v1/cameras/1/zone",
    headers={"Authorization": "Bearer <API_KEY>"},
    json={
      "zone_id": 1
    },
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/cameras/1/zone", {
  method: "PUT",
  headers: { "Authorization": "Bearer <API_KEY>", "Content-Type": "application/json" },
  body: JSON.stringify({
    "zone_id": 1
  }),
});
console.log(r.status, await r.text());

Respons 200

{
  "camera_id": 1,
  "site_id": 1,
  "zone_id": 1
}

Geometri Kamera (Garis, Zona, Lajur)

GET/cameras/{id}/geometry

Siapa yang dapat memanggil: Akun dengan peran (Pemantau atau Admin) di lokasi tersebut. Cakupan token: read.

Parameter

KolomTipeDeskripsi
idwajib pathinteger

Respons

StatusArti
200OK
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)
502Mesin analitik menolak permintaan (engine_refused)
503Mesin analitik tidak menjawab (engine_unavailable); coba lagi setelah Retry-After

Permintaan

curl -s -X GET "https://<BOX_HOST>/api/v1/cameras/1/geometry" \
  -H "Authorization: Bearer <API_KEY>"
import requests

r = requests.get(
    "https://<BOX_HOST>/api/v1/cameras/1/geometry",
    headers={"Authorization": "Bearer <API_KEY>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/cameras/1/geometry", {
  method: "GET",
  headers: { "Authorization": "Bearer <API_KEY>" },
});
console.log(r.status, await r.text());

Respons 200

{}

Ganti Geometri (If-Match)

PUT/cameras/{id}/geometry

Siapa yang dapat memanggil: Akun yang menjadi Admin di lokasi tersebut. Cakupan token: write.

Parameter

KolomTipeDeskripsi
idwajib pathinteger
If-Match headerstringETag yang dibaca sebelumnya; wajib untuk perubahan.

Respons

StatusArti
200OK
400Permintaan tidak valid
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)
412ETag di If-Match sudah usang
413Isi permintaan terlalu besar
415Bukan JSON
422Isi permintaan tidak valid
428If-Match wajib diisi
502Mesin analitik menolak permintaan (engine_refused)
503Mesin analitik tidak menjawab (engine_unavailable); coba lagi setelah Retry-After

Permintaan

curl -s -X PUT "https://<BOX_HOST>/api/v1/cameras/1/geometry" \
  -H "Authorization: Bearer <API_KEY>" \
  -H "If-Match: <IF_MATCH>" \
  -H "Content-Type: application/json" \
  -d '{}'
import requests

r = requests.put(
    "https://<BOX_HOST>/api/v1/cameras/1/geometry",
    headers={"Authorization": "Bearer <API_KEY>", "If-Match": "<IF_MATCH>"},
    json={},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/cameras/1/geometry", {
  method: "PUT",
  headers: { "Authorization": "Bearer <API_KEY>", "If-Match": "<IF_MATCH>", "Content-Type": "application/json" },
  body: JSON.stringify({}),
});
console.log(r.status, await r.text());

Respons 200

{}

Bingkai Kamera Saat Ini

GET/cameras/{id}/snapshot

Siapa yang dapat memanggil: Akun dengan peran (Pemantau atau Admin) di lokasi tersebut. Cakupan token: read, personal_data.

Parameter

KolomTipeDeskripsi
idwajib pathinteger

Respons

StatusArti
200JPEG
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)
502Mesin analitik menolak permintaan (engine_refused)
503Mesin analitik tidak menjawab (engine_unavailable); coba lagi setelah Retry-After

Permintaan

curl -s -X GET "https://<BOX_HOST>/api/v1/cameras/1/snapshot" \
  -H "Authorization: Bearer <API_KEY>"
import requests

r = requests.get(
    "https://<BOX_HOST>/api/v1/cameras/1/snapshot",
    headers={"Authorization": "Bearer <API_KEY>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/cameras/1/snapshot", {
  method: "GET",
  headers: { "Authorization": "Bearer <API_KEY>" },
});
console.log(r.status, await r.text());

Video Langsung Dan Rekaman

Tampilan langsung (WebRTC, HLS), segmen rekaman, ekspor MP4 dan klip peristiwa.

WHEP: Penawaran SDP Dari Peramban Untuk Siaran Langsung Kamera; Menjawab Dengan Jawaban SDP (RFC 9725)

POST/live/{camera}/whep

Siapa yang dapat memanggil: Akun dengan peran (Pemantau atau Admin) di lokasi kamera tersebut. Cakupan token: write, personal_data.

Parameter

KolomTipeDeskripsi
camerawajib pathinteger

Respons

StatusArti
201jawaban SDP
400Permintaan tidak valid
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)
413Isi permintaan terlalu besar
415Bukan JSON
422Isi permintaan tidak valid
502Mesin analitik menolak permintaan (engine_refused)
503Mesin analitik tidak menjawab (engine_unavailable); coba lagi setelah Retry-After

Permintaan

curl -s -X POST "https://<BOX_HOST>/api/v1/live/1/whep" \
  -H "Authorization: Bearer <API_KEY>"
import requests

r = requests.post(
    "https://<BOX_HOST>/api/v1/live/1/whep",
    headers={"Authorization": "Bearer <API_KEY>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/live/1/whep", {
  method: "POST",
  headers: { "Authorization": "Bearer <API_KEY>" },
});
console.log(r.status, await r.text());

Daftar Putar HLS Kamera (Cadangan Bila WebRTC Tidak Dapat Tersambung)

GET/live/{camera}/hls.m3u8

Siapa yang dapat memanggil: Akun dengan peran (Pemantau atau Admin) di lokasi kamera tersebut. Cakupan token: read, personal_data.

Parameter

KolomTipeDeskripsi
camerawajib pathinteger

Respons

StatusArti
200OK
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)
502Mesin analitik menolak permintaan (engine_refused)
503Mesin analitik tidak menjawab (engine_unavailable); coba lagi setelah Retry-After

Permintaan

curl -s -X GET "https://<BOX_HOST>/api/v1/live/1/hls.m3u8" \
  -H "Authorization: Bearer <API_KEY>"
import requests

r = requests.get(
    "https://<BOX_HOST>/api/v1/live/1/hls.m3u8",
    headers={"Authorization": "Bearer <API_KEY>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/live/1/hls.m3u8", {
  method: "GET",
  headers: { "Authorization": "Bearer <API_KEY>" },
});
console.log(r.status, await r.text());

Satu Segmen HLS

GET/live/{camera}/segments/{name}

Siapa yang dapat memanggil: Akun dengan peran (Pemantau atau Admin) di lokasi kamera tersebut. Cakupan token: read, personal_data.

Parameter

KolomTipeDeskripsi
camerawajib pathinteger
namewajib pathstring

Respons

StatusArti
200OK
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)
502Mesin analitik menolak permintaan (engine_refused)
503Mesin analitik tidak menjawab (engine_unavailable); coba lagi setelah Retry-After

Permintaan

curl -s -X GET "https://<BOX_HOST>/api/v1/live/1/segments/{name}" \
  -H "Authorization: Bearer <API_KEY>"
import requests

r = requests.get(
    "https://<BOX_HOST>/api/v1/live/1/segments/{name}",
    headers={"Authorization": "Bearer <API_KEY>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/live/1/segments/{name}", {
  method: "GET",
  headers: { "Authorization": "Bearer <API_KEY>" },
});
console.log(r.status, await r.text());

Segmen Rekaman Kamera (Satu Kamera Per Kueri)

GET/recordings

Siapa yang dapat memanggil: Akun dengan peran (Pemantau atau Admin) di lokasi kamera tersebut. Cakupan token: read, personal_data.

Parameter

KolomTipeDeskripsi
camerawajib queryinteger
from querystring
to querystring
cursor querystring
limit queryinteger

Respons

StatusArti
200OK
400Permintaan tidak valid
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)
502Mesin analitik menolak permintaan (engine_refused)
503Mesin analitik tidak menjawab (engine_unavailable); coba lagi setelah Retry-After

Permintaan

curl -s -X GET "https://<BOX_HOST>/api/v1/recordings?camera=1&from=2026-11-01T00%3A00%3A00%2B07%3A00&to=2026-11-02T00%3A00%3A00%2B07%3A00&limit=50" \
  -H "Authorization: Bearer <API_KEY>"
import requests

r = requests.get(
    "https://<BOX_HOST>/api/v1/recordings?camera=1&from=2026-11-01T00%3A00%3A00%2B07%3A00&to=2026-11-02T00%3A00%3A00%2B07%3A00&limit=50",
    headers={"Authorization": "Bearer <API_KEY>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/recordings?camera=1&from=2026-11-01T00%3A00%3A00%2B07%3A00&to=2026-11-02T00%3A00%3A00%2B07%3A00&limit=50", {
  method: "GET",
  headers: { "Authorization": "Bearer <API_KEY>" },
});
console.log(r.status, await r.text());

Respons 200

{}

Ekspor Rekaman Kamera Hingga 60 Menit Ke MP4 (Berupa Job; Dicatat Di Log Audit)

POST/recordings/export

Siapa yang dapat memanggil: Akun dengan peran (Pemantau atau Admin) di lokasi kamera tersebut. Cakupan token: write, export, personal_data.

Body

KolomTipeDeskripsi
camerawajibinteger
fromwajibdate-time
towajibdate-time

Respons

StatusArti
202berupa job; pantau Location-nya (/api/v1/recordings/exports/{job})
400Permintaan tidak valid
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)
409Konflik
413Isi permintaan terlalu besar
415Bukan JSON
422Isi permintaan tidak valid
502Mesin analitik menolak permintaan (engine_refused)
503Mesin analitik tidak menjawab (engine_unavailable); coba lagi setelah Retry-After

Permintaan

curl -s -X POST "https://<BOX_HOST>/api/v1/recordings/export" \
  -H "Authorization: Bearer <API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{"camera":12,"from":"2026-11-02T08:00:00Z","to":"2026-11-02T08:00:00Z"}'
import requests

r = requests.post(
    "https://<BOX_HOST>/api/v1/recordings/export",
    headers={"Authorization": "Bearer <API_KEY>"},
    json={
      "camera": 12,
      "from": "2026-11-02T08:00:00Z",
      "to": "2026-11-02T08:00:00Z"
    },
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/recordings/export", {
  method: "POST",
  headers: { "Authorization": "Bearer <API_KEY>", "Content-Type": "application/json" },
  body: JSON.stringify({
    "camera": 12,
    "from": "2026-11-02T08:00:00Z",
    "to": "2026-11-02T08:00:00Z"
  }),
});
console.log(r.status, await r.text());

Respons 202

{}

Job Ekspor Atau Klip (Tautan File Ke Dasbor Setelah Selesai)

GET/recordings/exports/{job}

Siapa yang dapat memanggil: Akun dengan peran (Pemantau atau Admin) di lokasi kamera tersebut. Cakupan token: read, export, personal_data.

Parameter

KolomTipeDeskripsi
jobwajib pathstring

Respons

StatusArti
200OK
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)
502Mesin analitik menolak permintaan (engine_refused)
503Mesin analitik tidak menjawab (engine_unavailable); coba lagi setelah Retry-After

Permintaan

curl -s -X GET "https://<BOX_HOST>/api/v1/recordings/exports/{job}" \
  -H "Authorization: Bearer <API_KEY>"
import requests

r = requests.get(
    "https://<BOX_HOST>/api/v1/recordings/exports/{job}",
    headers={"Authorization": "Bearer <API_KEY>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/recordings/exports/{job}", {
  method: "GET",
  headers: { "Authorization": "Bearer <API_KEY>" },
});
console.log(r.status, await r.text());

Respons 200

{}

MP4 Hasil Ekspor (Dialirkan; Rentang Byte)

GET/recordings/exports/{job}/file

Siapa yang dapat memanggil: Akun dengan peran (Pemantau atau Admin) di lokasi kamera tersebut. Cakupan token: read, export, personal_data.

Parameter

KolomTipeDeskripsi
jobwajib pathstring

Respons

StatusArti
200OK
206rentang byte
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)
409Konflik
502Mesin analitik menolak permintaan (engine_refused)
503Mesin analitik tidak menjawab (engine_unavailable); coba lagi setelah Retry-After

Permintaan

curl -s -X GET "https://<BOX_HOST>/api/v1/recordings/exports/{job}/file" \
  -H "Authorization: Bearer <API_KEY>"
import requests

r = requests.get(
    "https://<BOX_HOST>/api/v1/recordings/exports/{job}/file",
    headers={"Authorization": "Bearer <API_KEY>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/recordings/exports/{job}/file", {
  method: "GET",
  headers: { "Authorization": "Bearer <API_KEY>" },
});
console.log(r.status, await r.text());

Klip Di Sekitar Suatu Peristiwa (Bawaan 10 Detik Sebelum Sampai 20 Detik Sesudah; Berupa Job; Dicatat Di Log Audit)

POST/events/{id}/clip

Siapa yang dapat memanggil: Akun dengan peran (Pemantau atau Admin) di lokasi kamera tersebut. Cakupan token: write, export, personal_data.

Parameter

KolomTipeDeskripsi
idwajib pathstring

Respons

StatusArti
202berupa job; pantau Location-nya (/api/v1/recordings/exports/{job})
400Permintaan tidak valid
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)
413Isi permintaan terlalu besar
415Bukan JSON
422Isi permintaan tidak valid
502Mesin analitik menolak permintaan (engine_refused)
503Mesin analitik tidak menjawab (engine_unavailable); coba lagi setelah Retry-After

Permintaan

curl -s -X POST "https://<BOX_HOST>/api/v1/events/{id}/clip" \
  -H "Authorization: Bearer <API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{}'
import requests

r = requests.post(
    "https://<BOX_HOST>/api/v1/events/{id}/clip",
    headers={"Authorization": "Bearer <API_KEY>"},
    json={},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/events/{id}/clip", {
  method: "POST",
  headers: { "Authorization": "Bearer <API_KEY>", "Content-Type": "application/json" },
  body: JSON.stringify({}),
});
console.log(r.status, await r.text());

Respons 202

{}

Peringatan

Peringatan yang muncul dari deteksi; tampilkan daftarnya, baca satu, tandai sudah ditangani.

Peringatan, Terbaru Lebih Dulu

GET/alerts

Siapa yang dapat memanggil: Setiap akun API; jawabannya mencakup lokasi tempat akun itu memiliki peran. Cakupan token: read. Tanpa personal_data jawabannya berbentuk anonim: tanpa nama, nomor polisi, gambar atau rekaman.

Parameter

KolomTipeDeskripsi
site queryintegerhanya lokasi ini
state querystringopen atau acknowledged
kind querystringhanya jenis ini
before queryintegernext_before dari halaman sebelumnya
limit queryinteger1..500, bawaan 50

Respons

StatusArti
200OK
400Permintaan tidak valid
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)

Permintaan

curl -s -X GET "https://<BOX_HOST>/api/v1/alerts?site=1&before=2026-11-02T08%3A00%3A00Z&limit=50" \
  -H "Authorization: Bearer <API_KEY>"
import requests

r = requests.get(
    "https://<BOX_HOST>/api/v1/alerts?site=1&before=2026-11-02T08%3A00%3A00Z&limit=50",
    headers={"Authorization": "Bearer <API_KEY>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/alerts?site=1&before=2026-11-02T08%3A00%3A00Z&limit=50", {
  method: "GET",
  headers: { "Authorization": "Bearer <API_KEY>" },
});
console.log(r.status, await r.text());

Respons 200

{
  "items": [
    {
      "id": 1,
      "site_id": 1,
      "camera_id": 1,
      "kind": "default",
      "severity": "info",
      "first": "2026-11-02T08:00:00Z",
      "last": "2026-11-02T08:00:00Z",
      "count": 12,
      "event_id": "<event_id>",
      "details": "<details>",
      "state": "open",
      "acked_by": "<acked_by>",
      "acked_by_name": "<acked_by_name>",
      "acked": "2026-11-02T08:00:00Z",
      "note": "<note>",
      "footage": "<footage>",
      "footage_state": "none"
    }
  ],
  "next_before": 12
}

Peringatan Terbuka Per Lokasi Yang Terlihat

GET/alerts/summary

Siapa yang dapat memanggil: Setiap akun API. Cakupan token: read.

Respons

StatusArti
200OK
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)

Permintaan

curl -s -X GET "https://<BOX_HOST>/api/v1/alerts/summary" \
  -H "Authorization: Bearer <API_KEY>"
import requests

r = requests.get(
    "https://<BOX_HOST>/api/v1/alerts/summary",
    headers={"Authorization": "Bearer <API_KEY>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/alerts/summary", {
  method: "GET",
  headers: { "Authorization": "Bearer <API_KEY>" },
});
console.log(r.status, await r.text());

Respons 200

{
  "open": 12,
  "sites": [
    {
      "site_id": 1,
      "open": 12
    }
  ]
}

Jenis Peringatan Produk

GET/alerts/kinds

Siapa yang dapat memanggil: Setiap akun API. Cakupan token: read.

Respons

StatusArti
200OK
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)

Permintaan

curl -s -X GET "https://<BOX_HOST>/api/v1/alerts/kinds" \
  -H "Authorization: Bearer <API_KEY>"
import requests

r = requests.get(
    "https://<BOX_HOST>/api/v1/alerts/kinds",
    headers={"Authorization": "Bearer <API_KEY>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/alerts/kinds", {
  method: "GET",
  headers: { "Authorization": "Bearer <API_KEY>" },
});
console.log(r.status, await r.text());

Respons 200

{
  "items": [
    {
      "id": "<id>",
      "severity": "info",
      "window_s": 60
    }
  ]
}

Satu Peringatan

GET/alerts/{id}

Siapa yang dapat memanggil: Akun dengan peran (Pemantau atau Admin) di lokasi tersebut. Cakupan token: read. Tanpa personal_data jawabannya berbentuk anonim: tanpa nama, nomor polisi, gambar atau rekaman.

Parameter

KolomTipeDeskripsi
idwajib pathinteger

Respons

StatusArti
200OK
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)

Permintaan

curl -s -X GET "https://<BOX_HOST>/api/v1/alerts/1" \
  -H "Authorization: Bearer <API_KEY>"
import requests

r = requests.get(
    "https://<BOX_HOST>/api/v1/alerts/1",
    headers={"Authorization": "Bearer <API_KEY>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/alerts/1", {
  method: "GET",
  headers: { "Authorization": "Bearer <API_KEY>" },
});
console.log(r.status, await r.text());

Respons 200

{
  "id": 1,
  "site_id": 1,
  "camera_id": 1,
  "kind": "default",
  "severity": "info",
  "first": "2026-11-02T08:00:00Z",
  "last": "2026-11-02T08:00:00Z",
  "count": 12,
  "event_id": "<event_id>",
  "details": "<details>",
  "state": "open",
  "acked_by": "<acked_by>",
  "acked_by_name": "<acked_by_name>",
  "acked": "2026-11-02T08:00:00Z",
  "note": "<note>",
  "footage": "<footage>",
  "footage_state": "none"
}

Tandai Peringatan Sudah Ditangani, Dengan Catatan Opsional (Dicatat Di Log Audit)

POST/alerts/{id}/ack

Siapa yang dapat memanggil: Akun dengan peran (Pemantau atau Admin) di lokasi tersebut. Cakupan token: write.

Parameter

KolomTipeDeskripsi
idwajib pathinteger

Body

KolomTipeDeskripsi
notestring

Respons

StatusArti
200OK
400Permintaan tidak valid
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)
409Konflik
413Isi permintaan terlalu besar
415Bukan JSON
422Isi permintaan tidak valid

Permintaan

curl -s -X POST "https://<BOX_HOST>/api/v1/alerts/1/ack" \
  -H "Authorization: Bearer <API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{"note":"<note>"}'
import requests

r = requests.post(
    "https://<BOX_HOST>/api/v1/alerts/1/ack",
    headers={"Authorization": "Bearer <API_KEY>"},
    json={
      "note": "<note>"
    },
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/alerts/1/ack", {
  method: "POST",
  headers: { "Authorization": "Bearer <API_KEY>", "Content-Type": "application/json" },
  body: JSON.stringify({
    "note": "<note>"
  }),
});
console.log(r.status, await r.text());

Respons 200

{
  "id": 1,
  "site_id": 1,
  "camera_id": 1,
  "kind": "default",
  "severity": "info",
  "first": "2026-11-02T08:00:00Z",
  "last": "2026-11-02T08:00:00Z",
  "count": 12,
  "event_id": "<event_id>",
  "details": "<details>",
  "state": "open",
  "acked_by": "<acked_by>",
  "acked_by_name": "<acked_by_name>",
  "acked": "2026-11-02T08:00:00Z",
  "note": "<note>",
  "footage": "<footage>",
  "footage_state": "none"
}

Kontak Dan Notifikasi

Siapa yang diberi tahu tentang peringatan, dan log pesan yang dikirim kepada mereka.

Kontak Peringatan Lokasi

GET/sites/{id}/contacts

Siapa yang dapat memanggil: Akun yang menjadi Admin di lokasi tersebut. Cakupan token: read, personal_data.

Parameter

KolomTipeDeskripsi
idwajib pathinteger

Respons

StatusArti
200OK
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)

Permintaan

curl -s -X GET "https://<BOX_HOST>/api/v1/sites/1/contacts" \
  -H "Authorization: Bearer <API_KEY>"
import requests

r = requests.get(
    "https://<BOX_HOST>/api/v1/sites/1/contacts",
    headers={"Authorization": "Bearer <API_KEY>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/sites/1/contacts", {
  method: "GET",
  headers: { "Authorization": "Bearer <API_KEY>" },
});
console.log(r.status, await r.text());

Respons 200

{
  "items": [
    {
      "id": 1,
      "site_id": 1,
      "name": "Main gate",
      "email": "ops@example.com",
      "whatsapp": "<whatsapp>",
      "telegram": "<telegram>",
      "language": "en",
      "channels": [
        "email"
      ],
      "kinds": [
        "default"
      ],
      "min_severity": "info",
      "quiet_start": "08:00",
      "quiet_end": "08:00",
      "active": true
    }
  ]
}

Tambahkan Kontak Peringatan

POST/sites/{id}/contacts

Siapa yang dapat memanggil: Akun yang menjadi Admin di lokasi tersebut. Cakupan token: write, personal_data.

Parameter

KolomTipeDeskripsi
idwajib pathinteger

Body

KolomTipeDeskripsi
namewajibstring
emailstring
whatsappstringE.164, misalnya +6281234567890
telegramstringid chat Telegram
languageenumen, id
channelsenum[]
kindsstring[]jenis peringatan; [] = semua jenis
min_severityenuminfo, warning, critical
quiet_startstring
quiet_endstring
activeboolean

Respons

StatusArti
201Dibuat
400Permintaan tidak valid
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)
413Isi permintaan terlalu besar
415Bukan JSON
422Isi permintaan tidak valid

Permintaan

curl -s -X POST "https://<BOX_HOST>/api/v1/sites/1/contacts" \
  -H "Authorization: Bearer <API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{"name":"Main gate","email":"ops@example.com","whatsapp":"<whatsapp>","telegram":"<telegram>","language":"en","channels":["email"],"kinds":["default"],"min_severity":"info","quiet_start":"08:00","quiet_end":"08:00","active":true}'
import requests

r = requests.post(
    "https://<BOX_HOST>/api/v1/sites/1/contacts",
    headers={"Authorization": "Bearer <API_KEY>"},
    json={
      "name": "Main gate",
      "email": "ops@example.com",
      "whatsapp": "<whatsapp>",
      "telegram": "<telegram>",
      "language": "en",
      "channels": [
        "email"
      ],
      "kinds": [
        "default"
      ],
      "min_severity": "info",
      "quiet_start": "08:00",
      "quiet_end": "08:00",
      "active": True
    },
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/sites/1/contacts", {
  method: "POST",
  headers: { "Authorization": "Bearer <API_KEY>", "Content-Type": "application/json" },
  body: JSON.stringify({
    "name": "Main gate",
    "email": "ops@example.com",
    "whatsapp": "<whatsapp>",
    "telegram": "<telegram>",
    "language": "en",
    "channels": [
      "email"
    ],
    "kinds": [
      "default"
    ],
    "min_severity": "info",
    "quiet_start": "08:00",
    "quiet_end": "08:00",
    "active": true
  }),
});
console.log(r.status, await r.text());

Respons 201

{
  "id": 1,
  "site_id": 1,
  "name": "Main gate",
  "email": "ops@example.com",
  "whatsapp": "<whatsapp>",
  "telegram": "<telegram>",
  "language": "en",
  "channels": [
    "email"
  ],
  "kinds": [
    "default"
  ],
  "min_severity": "info",
  "quiet_start": "08:00",
  "quiet_end": "08:00",
  "active": true
}

Ubah Kontak Peringatan

PATCH/contacts/{id}

Siapa yang dapat memanggil: Akun yang menjadi Admin di lokasi tersebut. Cakupan token: write, personal_data.

Parameter

KolomTipeDeskripsi
idwajib pathinteger

Body

KolomTipeDeskripsi
namestring
emailstring
whatsappstringE.164, misalnya +6281234567890
telegramstringid chat Telegram
languageenumen, id
channelsenum[]
kindsstring[]jenis peringatan; [] = semua jenis
min_severityenuminfo, warning, critical
quiet_startstring
quiet_endstring
activeboolean

Respons

StatusArti
200OK
400Permintaan tidak valid
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)
413Isi permintaan terlalu besar
415Bukan JSON
422Isi permintaan tidak valid

Permintaan

curl -s -X PATCH "https://<BOX_HOST>/api/v1/contacts/1" \
  -H "Authorization: Bearer <API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{"name":"Main gate","email":"ops@example.com","whatsapp":"<whatsapp>","telegram":"<telegram>","language":"en","channels":["email"],"kinds":["default"],"min_severity":"info","quiet_start":"08:00","quiet_end":"08:00","active":true}'
import requests

r = requests.patch(
    "https://<BOX_HOST>/api/v1/contacts/1",
    headers={"Authorization": "Bearer <API_KEY>"},
    json={
      "name": "Main gate",
      "email": "ops@example.com",
      "whatsapp": "<whatsapp>",
      "telegram": "<telegram>",
      "language": "en",
      "channels": [
        "email"
      ],
      "kinds": [
        "default"
      ],
      "min_severity": "info",
      "quiet_start": "08:00",
      "quiet_end": "08:00",
      "active": True
    },
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/contacts/1", {
  method: "PATCH",
  headers: { "Authorization": "Bearer <API_KEY>", "Content-Type": "application/json" },
  body: JSON.stringify({
    "name": "Main gate",
    "email": "ops@example.com",
    "whatsapp": "<whatsapp>",
    "telegram": "<telegram>",
    "language": "en",
    "channels": [
      "email"
    ],
    "kinds": [
      "default"
    ],
    "min_severity": "info",
    "quiet_start": "08:00",
    "quiet_end": "08:00",
    "active": true
  }),
});
console.log(r.status, await r.text());

Respons 200

{
  "id": 1,
  "site_id": 1,
  "name": "Main gate",
  "email": "ops@example.com",
  "whatsapp": "<whatsapp>",
  "telegram": "<telegram>",
  "language": "en",
  "channels": [
    "email"
  ],
  "kinds": [
    "default"
  ],
  "min_severity": "info",
  "quiet_start": "08:00",
  "quiet_end": "08:00",
  "active": true
}

Hapus Kontak Peringatan

DELETE/contacts/{id}

Siapa yang dapat memanggil: Akun yang menjadi Admin di lokasi tersebut. Cakupan token: write, personal_data.

Parameter

KolomTipeDeskripsi
idwajib pathinteger

Respons

StatusArti
204Dihapus
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)

Permintaan

curl -s -X DELETE "https://<BOX_HOST>/api/v1/contacts/1" \
  -H "Authorization: Bearer <API_KEY>"
import requests

r = requests.delete(
    "https://<BOX_HOST>/api/v1/contacts/1",
    headers={"Authorization": "Bearer <API_KEY>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/contacts/1", {
  method: "DELETE",
  headers: { "Authorization": "Bearer <API_KEY>" },
});
console.log(r.status, await r.text());

Pengiriman, Terbaru Lebih Dulu

GET/notify/deliveries

Siapa yang dapat memanggil: Akun yang menjadi Admin di suatu lokasi; jawabannya mencakup lokasi tersebut. Cakupan token: read, personal_data.

Parameter

KolomTipeDeskripsi
site queryintegerhanya lokasi ini
ref querystringmisalnya alert:12
state querystringqueued, sending, sent atau failed
before queryintegernext_before dari halaman sebelumnya
limit queryinteger1..500, bawaan 50

Respons

StatusArti
200OK
400Permintaan tidak valid
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)

Permintaan

curl -s -X GET "https://<BOX_HOST>/api/v1/notify/deliveries?site=1&before=2026-11-02T08%3A00%3A00Z&limit=50" \
  -H "Authorization: Bearer <API_KEY>"
import requests

r = requests.get(
    "https://<BOX_HOST>/api/v1/notify/deliveries?site=1&before=2026-11-02T08%3A00%3A00Z&limit=50",
    headers={"Authorization": "Bearer <API_KEY>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/notify/deliveries?site=1&before=2026-11-02T08%3A00%3A00Z&limit=50", {
  method: "GET",
  headers: { "Authorization": "Bearer <API_KEY>" },
});
console.log(r.status, await r.text());

Respons 200

{
  "items": [
    {
      "id": 1,
      "site_id": 1,
      "ref": "<ref>",
      "channel": "email",
      "recipient": "<recipient>",
      "state": "queued",
      "attempts": 12,
      "created": "2026-11-02T08:00:00Z",
      "next": "2026-11-02T08:00:00Z",
      "sent": "2026-11-02T08:00:00Z",
      "last_error": "<last_error>"
    }
  ],
  "next_before": 12
}

Antrekan Lagi Pengiriman Yang Gagal (Masa Coba Ulang Baru)

POST/notify/deliveries/{id}/retry

Siapa yang dapat memanggil: Akun yang menjadi Admin di lokasi tersebut. Cakupan token: write, personal_data.

Parameter

KolomTipeDeskripsi
idwajib pathinteger

Respons

StatusArti
200OK
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)
409Konflik

Permintaan

curl -s -X POST "https://<BOX_HOST>/api/v1/notify/deliveries/1/retry" \
  -H "Authorization: Bearer <API_KEY>"
import requests

r = requests.post(
    "https://<BOX_HOST>/api/v1/notify/deliveries/1/retry",
    headers={"Authorization": "Bearer <API_KEY>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/notify/deliveries/1/retry", {
  method: "POST",
  headers: { "Authorization": "Bearer <API_KEY>" },
});
console.log(r.status, await r.text());

Respons 200

{
  "id": 1,
  "site_id": 1,
  "ref": "<ref>",
  "channel": "email",
  "recipient": "<recipient>",
  "state": "queued",
  "attempts": 12,
  "created": "2026-11-02T08:00:00Z",
  "next": "2026-11-02T08:00:00Z",
  "sent": "2026-11-02T08:00:00Z",
  "last_error": "<last_error>"
}

Webhook

Kiriman HTTP bertanda tangan berisi peringatan ke sistem lain (Standard Webhooks).

Webhook Lokasi

GET/sites/{id}/webhooks

Siapa yang dapat memanggil: Akun yang menjadi Admin di lokasi tersebut. Cakupan token: read.

Parameter

KolomTipeDeskripsi
idwajib pathinteger

Respons

StatusArti
200OK
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)

Permintaan

curl -s -X GET "https://<BOX_HOST>/api/v1/sites/1/webhooks" \
  -H "Authorization: Bearer <API_KEY>"
import requests

r = requests.get(
    "https://<BOX_HOST>/api/v1/sites/1/webhooks",
    headers={"Authorization": "Bearer <API_KEY>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/sites/1/webhooks", {
  method: "GET",
  headers: { "Authorization": "Bearer <API_KEY>" },
});
console.log(r.status, await r.text());

Respons 200

{
  "items": [
    {
      "id": 1,
      "site_id": 1,
      "name": "Main gate",
      "url": "https://<RECEIVER_HOST>/hooks/arsa",
      "kinds": [
        "default"
      ],
      "active": true,
      "created": "2026-11-02T08:00:00Z"
    }
  ]
}

Tambahkan Webhook (Rahasianya Hanya Ada Di Jawaban Ini)

POST/sites/{id}/webhooks

Siapa yang dapat memanggil: Akun yang menjadi Admin di lokasi tersebut. Cakupan token: write.

Parameter

KolomTipeDeskripsi
idwajib pathinteger

Body

KolomTipeDeskripsi
namewajibstring
urlwajibstringhttp(s); alamat internal ditolak
kindsstring[]jenis peringatan; [] = semua jenis
activeboolean

Respons

StatusArti
201Dibuat
400Permintaan tidak valid
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)
413Isi permintaan terlalu besar
415Bukan JSON
422Isi permintaan tidak valid

Permintaan

curl -s -X POST "https://<BOX_HOST>/api/v1/sites/1/webhooks" \
  -H "Authorization: Bearer <API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{"name":"Main gate","url":"https://<RECEIVER_HOST>/hooks/arsa","kinds":["default"],"active":true}'
import requests

r = requests.post(
    "https://<BOX_HOST>/api/v1/sites/1/webhooks",
    headers={"Authorization": "Bearer <API_KEY>"},
    json={
      "name": "Main gate",
      "url": "https://<RECEIVER_HOST>/hooks/arsa",
      "kinds": [
        "default"
      ],
      "active": True
    },
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/sites/1/webhooks", {
  method: "POST",
  headers: { "Authorization": "Bearer <API_KEY>", "Content-Type": "application/json" },
  body: JSON.stringify({
    "name": "Main gate",
    "url": "https://<RECEIVER_HOST>/hooks/arsa",
    "kinds": [
      "default"
    ],
    "active": true
  }),
});
console.log(r.status, await r.text());

Respons 201

{
  "webhook": {
    "id": 1,
    "site_id": 1,
    "name": "Main gate",
    "url": "https://<RECEIVER_HOST>/hooks/arsa",
    "kinds": [
      "default"
    ],
    "active": true,
    "created": "2026-11-02T08:00:00Z"
  },
  "secret": "<WEBHOOK_SECRET>"
}

Ubah Webhook

PATCH/webhooks/{id}

Siapa yang dapat memanggil: Akun yang menjadi Admin di lokasi tersebut. Cakupan token: write.

Parameter

KolomTipeDeskripsi
idwajib pathinteger

Body

KolomTipeDeskripsi
namestring
urlstringhttp(s); alamat internal ditolak
kindsstring[]jenis peringatan; [] = semua jenis
activeboolean

Respons

StatusArti
200OK
400Permintaan tidak valid
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)
413Isi permintaan terlalu besar
415Bukan JSON
422Isi permintaan tidak valid

Permintaan

curl -s -X PATCH "https://<BOX_HOST>/api/v1/webhooks/1" \
  -H "Authorization: Bearer <API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{"name":"Main gate","url":"https://<RECEIVER_HOST>/hooks/arsa","kinds":["default"],"active":true}'
import requests

r = requests.patch(
    "https://<BOX_HOST>/api/v1/webhooks/1",
    headers={"Authorization": "Bearer <API_KEY>"},
    json={
      "name": "Main gate",
      "url": "https://<RECEIVER_HOST>/hooks/arsa",
      "kinds": [
        "default"
      ],
      "active": True
    },
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/webhooks/1", {
  method: "PATCH",
  headers: { "Authorization": "Bearer <API_KEY>", "Content-Type": "application/json" },
  body: JSON.stringify({
    "name": "Main gate",
    "url": "https://<RECEIVER_HOST>/hooks/arsa",
    "kinds": [
      "default"
    ],
    "active": true
  }),
});
console.log(r.status, await r.text());

Respons 200

{
  "id": 1,
  "site_id": 1,
  "name": "Main gate",
  "url": "https://<RECEIVER_HOST>/hooks/arsa",
  "kinds": [
    "default"
  ],
  "active": true,
  "created": "2026-11-02T08:00:00Z"
}

Hapus Webhook

DELETE/webhooks/{id}

Siapa yang dapat memanggil: Akun yang menjadi Admin di lokasi tersebut. Cakupan token: write.

Parameter

KolomTipeDeskripsi
idwajib pathinteger

Respons

StatusArti
204Selesai
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)

Permintaan

curl -s -X DELETE "https://<BOX_HOST>/api/v1/webhooks/1" \
  -H "Authorization: Bearer <API_KEY>"
import requests

r = requests.delete(
    "https://<BOX_HOST>/api/v1/webhooks/1",
    headers={"Authorization": "Bearer <API_KEY>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/webhooks/1", {
  method: "DELETE",
  headers: { "Authorization": "Bearer <API_KEY>" },
});
console.log(r.status, await r.text());

Rahasia Baru (Rahasia Lama Langsung Berhenti Berlaku)

POST/webhooks/{id}/secret

Siapa yang dapat memanggil: Akun yang menjadi Admin di lokasi tersebut. Cakupan token: write.

Parameter

KolomTipeDeskripsi
idwajib pathinteger

Respons

StatusArti
200OK
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)

Permintaan

curl -s -X POST "https://<BOX_HOST>/api/v1/webhooks/1/secret" \
  -H "Authorization: Bearer <API_KEY>"
import requests

r = requests.post(
    "https://<BOX_HOST>/api/v1/webhooks/1/secret",
    headers={"Authorization": "Bearer <API_KEY>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/webhooks/1/secret", {
  method: "POST",
  headers: { "Authorization": "Bearer <API_KEY>" },
});
console.log(r.status, await r.text());

Respons 200

{
  "secret": "<WEBHOOK_SECRET>"
}

Kirim Peristiwa Uji Sekarang Dan Laporkan Hasilnya

POST/webhooks/{id}/test

Siapa yang dapat memanggil: Akun yang menjadi Admin di lokasi tersebut. Cakupan token: write.

Parameter

KolomTipeDeskripsi
idwajib pathinteger

Respons

StatusArti
200OK
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)

Permintaan

curl -s -X POST "https://<BOX_HOST>/api/v1/webhooks/1/test" \
  -H "Authorization: Bearer <API_KEY>"
import requests

r = requests.post(
    "https://<BOX_HOST>/api/v1/webhooks/1/test",
    headers={"Authorization": "Bearer <API_KEY>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/webhooks/1/test", {
  method: "POST",
  headers: { "Authorization": "Bearer <API_KEY>" },
});
console.log(r.status, await r.text());

Respons 200

{
  "ok": true,
  "error": "Text",
  "retryable": true
}

Webhook Untuk Integrator

Langganan milik akun API: peristiwa deteksi dalam batch, ringkasan berkala dan peringatan, ditandatangani, dengan log pengiriman.

Jenis Peristiwa Produk Untuk Langganan Webhook, Beserta Batasnya

GET/webhook-event-types

Siapa yang dapat memanggil: Setiap akun API. Cakupan token: read.

Respons

StatusArti
200OK
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)

Permintaan

curl -s -X GET "https://<BOX_HOST>/api/v1/webhook-event-types" \
  -H "Authorization: Bearer <API_KEY>"
import requests

r = requests.get(
    "https://<BOX_HOST>/api/v1/webhook-event-types",
    headers={"Authorization": "Bearer <API_KEY>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/webhook-event-types", {
  method: "GET",
  headers: { "Authorization": "Bearer <API_KEY>" },
});
console.log(r.status, await r.text());

Respons 200

{
  "product": "traffic",
  "items": [
    {
      "id": "traffic.passage",
      "label": {
        "en": "Vehicle passages",
        "id": "Lintasan kendaraan"
      },
      "personal": [
        "plate",
        "photo"
      ],
      "personal_admin": false,
      "personal_only": false
    },
    {
      "id": "traffic.speeding",
      "label": {
        "en": "Speeding",
        "id": "Melaju terlalu cepat"
      },
      "personal": [
        "plate"
      ],
      "personal_admin": false,
      "personal_only": false
    }
  ],
  "summaries": true,
  "periods": [
    "15m",
    "1h",
    "1d"
  ],
  "batch_seconds": {
    "min": 1,
    "max": 3600,
    "default": 10
  },
  "batch_max": {
    "min": 1,
    "max": 1000,
    "default": 100
  },
  "max_per_account": 10
}

Langganan Webhook Milik Akun API Pemilik Token

GET/webhook-subscriptions

Siapa yang dapat memanggil: Akun API pemilik langganan tersebut (dengan tokennya sendiri). Cakupan token: read.

Parameter

KolomTipeDeskripsi
account queryintegerhanya milik akun API ini

Respons

StatusArti
200OK
400Permintaan tidak valid
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)

Permintaan

curl -s -X GET "https://<BOX_HOST>/api/v1/webhook-subscriptions?account=1" \
  -H "Authorization: Bearer <API_KEY>"
import requests

r = requests.get(
    "https://<BOX_HOST>/api/v1/webhook-subscriptions?account=1",
    headers={"Authorization": "Bearer <API_KEY>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/webhook-subscriptions?account=1", {
  method: "GET",
  headers: { "Authorization": "Bearer <API_KEY>" },
});
console.log(r.status, await r.text());

Respons 200

{
  "items": [
    {
      "id": 1,
      "account_id": 1,
      "account": "erp-sync",
      "name": "Main gate",
      "url": "https://<RECEIVER_HOST>/hooks/arsa",
      "event_types": [
        "<event_type>"
      ],
      "sites": [
        12
      ],
      "batch_seconds": 60,
      "batch_max": 12,
      "summary": "15m",
      "alerts": true,
      "active": true,
      "created": "2026-11-02T08:00:00Z",
      "created_by": "<created_by>",
      "health": {
        "state": "ok",
        "last_success": "2026-11-02T08:00:00Z",
        "last_failure": "2026-11-02T08:00:00Z",
        "last_error": "<last_error>",
        "dropped": 12,
        "queued": 12
      },
      "version": 3
    }
  ]
}

Daftarkan Akun API (Rahasianya Hanya Ada Di Jawaban Ini)

POST/webhook-subscriptions

Siapa yang dapat memanggil: Akun API pemilik langganan tersebut (dengan tokennya sendiri). Cakupan token: write.

Body

KolomTipeDeskripsi
account_idintegerakun API; untuk token: akunnya sendiri (boleh dihilangkan)
namewajibstring
urlwajibstringhttp(s); jaringan privat hanya bila perangkat mengizinkannya
event_typesstring[]jenis peristiwa produk yang aktif (GET /webhook-event-types)
sitesinteger[]id lokasi di dalam lokasi milik akun; [] = semua lokasi akun
batch_secondsintegerbawaan 10 saat dibuat
batch_maxintegerbawaan 100 saat dibuat
summaryenumringkasan berkala angka ikhtisar per lokasi, di zona waktu lokasi; null: tanpa ringkasan 15m, 1h, 1d, null
alertsbooleanbawaan false saat dibuat
activebooleanbawaan true saat dibuat

Respons

StatusArti
201Dibuat
400Permintaan tidak valid
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
409Konflik
413Isi permintaan terlalu besar
415Bukan JSON
422Isi permintaan tidak valid

Permintaan

curl -s -X POST "https://<BOX_HOST>/api/v1/webhook-subscriptions" \
  -H "Authorization: Bearer <API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{"name":"ERP receiver","url":"https://<RECEIVER_HOST>/hooks/arsa","event_types":["traffic.passage","traffic.speeding"],"sites":[1],"summary":"1h","alerts":true}'
import requests

r = requests.post(
    "https://<BOX_HOST>/api/v1/webhook-subscriptions",
    headers={"Authorization": "Bearer <API_KEY>"},
    json={
      "name": "ERP receiver",
      "url": "https://<RECEIVER_HOST>/hooks/arsa",
      "event_types": [
        "traffic.passage",
        "traffic.speeding"
      ],
      "sites": [
        1
      ],
      "summary": "1h",
      "alerts": True
    },
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/webhook-subscriptions", {
  method: "POST",
  headers: { "Authorization": "Bearer <API_KEY>", "Content-Type": "application/json" },
  body: JSON.stringify({
    "name": "ERP receiver",
    "url": "https://<RECEIVER_HOST>/hooks/arsa",
    "event_types": [
      "traffic.passage",
      "traffic.speeding"
    ],
    "sites": [
      1
    ],
    "summary": "1h",
    "alerts": true
  }),
});
console.log(r.status, await r.text());

Respons 201

{
  "subscription": {
    "id": 5,
    "account_id": 2,
    "account": "erp-sync",
    "name": "ERP receiver",
    "url": "https://<RECEIVER_HOST>/hooks/arsa",
    "event_types": [
      "traffic.passage",
      "traffic.speeding"
    ],
    "sites": [
      1
    ],
    "batch_seconds": 10,
    "batch_max": 100,
    "summary": "1h",
    "alerts": true,
    "active": true,
    "created": "2026-11-06T03:00:00Z",
    "created_by": "api:erp-sync",
    "health": {
      "state": "ok",
      "last_success": null,
      "last_failure": null,
      "last_error": null,
      "dropped": 0,
      "queued": 0
    },
    "version": 1
  },
  "secret": "<WEBHOOK_SECRET>"
}

Satu Langganan Webhook Beserta Kesehatannya

GET/webhook-subscriptions/{id}

Siapa yang dapat memanggil: Akun API pemilik langganan tersebut (dengan tokennya sendiri). Cakupan token: read.

Parameter

KolomTipeDeskripsi
idwajib pathinteger

Respons

StatusArti
200OK
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)

Permintaan

curl -s -X GET "https://<BOX_HOST>/api/v1/webhook-subscriptions/1" \
  -H "Authorization: Bearer <API_KEY>"
import requests

r = requests.get(
    "https://<BOX_HOST>/api/v1/webhook-subscriptions/1",
    headers={"Authorization": "Bearer <API_KEY>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/webhook-subscriptions/1", {
  method: "GET",
  headers: { "Authorization": "Bearer <API_KEY>" },
});
console.log(r.status, await r.text());

Respons 200

{
  "id": 1,
  "account_id": 1,
  "account": "erp-sync",
  "name": "Main gate",
  "url": "https://<RECEIVER_HOST>/hooks/arsa",
  "event_types": [
    "<event_type>"
  ],
  "sites": [
    12
  ],
  "batch_seconds": 60,
  "batch_max": 12,
  "summary": "15m",
  "alerts": true,
  "active": true,
  "created": "2026-11-02T08:00:00Z",
  "created_by": "<created_by>",
  "health": {
    "state": "ok",
    "last_success": "2026-11-02T08:00:00Z",
    "last_failure": "2026-11-02T08:00:00Z",
    "last_error": "<last_error>",
    "dropped": 12,
    "queued": 12
  },
  "version": 3
}

Ubah Langganan Webhook (Jeda, Atau Lanjutkan Mulai Saat Ini)

PATCH/webhook-subscriptions/{id}

Siapa yang dapat memanggil: Akun API pemilik langganan tersebut (dengan tokennya sendiri). Cakupan token: write.

Parameter

KolomTipeDeskripsi
idwajib pathinteger

Body

KolomTipeDeskripsi
account_idintegertidak dapat diubah
namestring
urlstringhttp(s); jaringan privat hanya bila perangkat mengizinkannya
event_typesstring[]jenis peristiwa produk yang aktif (GET /webhook-event-types)
sitesinteger[]id lokasi di dalam lokasi milik akun; [] = semua lokasi akun
batch_secondsintegerbawaan 10 saat dibuat
batch_maxintegerbawaan 100 saat dibuat
summaryenumringkasan berkala angka ikhtisar per lokasi, di zona waktu lokasi; null: tanpa ringkasan 15m, 1h, 1d, null
alertsbooleanbawaan false saat dibuat
activebooleanbawaan true saat dibuat

Respons

StatusArti
200OK
400Permintaan tidak valid
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)
413Isi permintaan terlalu besar
415Bukan JSON
422Isi permintaan tidak valid

Permintaan

curl -s -X PATCH "https://<BOX_HOST>/api/v1/webhook-subscriptions/1" \
  -H "Authorization: Bearer <API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{"account_id":1,"name":"Main gate","url":"https://<RECEIVER_HOST>/hooks/arsa","event_types":["<event_type>"],"sites":[12],"batch_seconds":60,"batch_max":12,"summary":"15m","alerts":true,"active":true}'
import requests

r = requests.patch(
    "https://<BOX_HOST>/api/v1/webhook-subscriptions/1",
    headers={"Authorization": "Bearer <API_KEY>"},
    json={
      "account_id": 1,
      "name": "Main gate",
      "url": "https://<RECEIVER_HOST>/hooks/arsa",
      "event_types": [
        "<event_type>"
      ],
      "sites": [
        12
      ],
      "batch_seconds": 60,
      "batch_max": 12,
      "summary": "15m",
      "alerts": True,
      "active": True
    },
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/webhook-subscriptions/1", {
  method: "PATCH",
  headers: { "Authorization": "Bearer <API_KEY>", "Content-Type": "application/json" },
  body: JSON.stringify({
    "account_id": 1,
    "name": "Main gate",
    "url": "https://<RECEIVER_HOST>/hooks/arsa",
    "event_types": [
      "<event_type>"
    ],
    "sites": [
      12
    ],
    "batch_seconds": 60,
    "batch_max": 12,
    "summary": "15m",
    "alerts": true,
    "active": true
  }),
});
console.log(r.status, await r.text());

Respons 200

{
  "id": 1,
  "account_id": 1,
  "account": "erp-sync",
  "name": "Main gate",
  "url": "https://<RECEIVER_HOST>/hooks/arsa",
  "event_types": [
    "<event_type>"
  ],
  "sites": [
    12
  ],
  "batch_seconds": 60,
  "batch_max": 12,
  "summary": "15m",
  "alerts": true,
  "active": true,
  "created": "2026-11-02T08:00:00Z",
  "created_by": "<created_by>",
  "health": {
    "state": "ok",
    "last_success": "2026-11-02T08:00:00Z",
    "last_failure": "2026-11-02T08:00:00Z",
    "last_error": "<last_error>",
    "dropped": 12,
    "queued": 12
  },
  "version": 3
}

Hapus Langganan Webhook Beserta Log Pengirimannya

DELETE/webhook-subscriptions/{id}

Siapa yang dapat memanggil: Akun API pemilik langganan tersebut (dengan tokennya sendiri). Cakupan token: write.

Parameter

KolomTipeDeskripsi
idwajib pathinteger

Respons

StatusArti
204Dihapus
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)

Permintaan

curl -s -X DELETE "https://<BOX_HOST>/api/v1/webhook-subscriptions/1" \
  -H "Authorization: Bearer <API_KEY>"
import requests

r = requests.delete(
    "https://<BOX_HOST>/api/v1/webhook-subscriptions/1",
    headers={"Authorization": "Bearer <API_KEY>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/webhook-subscriptions/1", {
  method: "DELETE",
  headers: { "Authorization": "Bearer <API_KEY>" },
});
console.log(r.status, await r.text());

Rahasia Penandatanganan Baru (Yang Lama Langsung Berhenti Berlaku); Hanya Ada Di Jawaban Ini

POST/webhook-subscriptions/{id}/secret

Siapa yang dapat memanggil: Akun API pemilik langganan tersebut (dengan tokennya sendiri). Cakupan token: write.

Parameter

KolomTipeDeskripsi
idwajib pathinteger

Respons

StatusArti
200OK
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)

Permintaan

curl -s -X POST "https://<BOX_HOST>/api/v1/webhook-subscriptions/1/secret" \
  -H "Authorization: Bearer <API_KEY>"
import requests

r = requests.post(
    "https://<BOX_HOST>/api/v1/webhook-subscriptions/1/secret",
    headers={"Authorization": "Bearer <API_KEY>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/webhook-subscriptions/1/secret", {
  method: "POST",
  headers: { "Authorization": "Bearer <API_KEY>" },
});
console.log(r.status, await r.text());

Respons 200

{
  "secret": "<WEBHOOK_SECRET>"
}

Kirim Pesan Uji Bertanda Tangan Sekarang Dan Laporkan Hasilnya (Disimpan Di Log Pengiriman Sebagai Uji)

POST/webhook-subscriptions/{id}/test

Siapa yang dapat memanggil: Akun API pemilik langganan tersebut (dengan tokennya sendiri). Cakupan token: write.

Parameter

KolomTipeDeskripsi
idwajib pathinteger

Respons

StatusArti
200OK
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)

Permintaan

curl -s -X POST "https://<BOX_HOST>/api/v1/webhook-subscriptions/1/test" \
  -H "Authorization: Bearer <API_KEY>"
import requests

r = requests.post(
    "https://<BOX_HOST>/api/v1/webhook-subscriptions/1/test",
    headers={"Authorization": "Bearer <API_KEY>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/webhook-subscriptions/1/test", {
  method: "POST",
  headers: { "Authorization": "Bearer <API_KEY>" },
});
console.log(r.status, await r.text());

Respons 200

{
  "ok": true,
  "error": "Text",
  "retryable": true
}

Log Pengiriman Langganan, Terbaru Lebih Dulu

GET/webhook-subscriptions/{id}/deliveries

Siapa yang dapat memanggil: Akun API pemilik langganan tersebut (dengan tokennya sendiri). Cakupan token: read.

Parameter

KolomTipeDeskripsi
idwajib pathinteger
state queryenumqueued, sending, sent, failed, dropped
before queryintegernext_before dari halaman sebelumnya
limit queryinteger1..500, bawaan 50

Respons

StatusArti
200OK
400Permintaan tidak valid
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)

Permintaan

curl -s -X GET "https://<BOX_HOST>/api/v1/webhook-subscriptions/1/deliveries?state=queued&before=2026-11-02T08%3A00%3A00Z&limit=50" \
  -H "Authorization: Bearer <API_KEY>"
import requests

r = requests.get(
    "https://<BOX_HOST>/api/v1/webhook-subscriptions/1/deliveries?state=queued&before=2026-11-02T08%3A00%3A00Z&limit=50",
    headers={"Authorization": "Bearer <API_KEY>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/webhook-subscriptions/1/deliveries?state=queued&before=2026-11-02T08%3A00%3A00Z&limit=50", {
  method: "GET",
  headers: { "Authorization": "Bearer <API_KEY>" },
});
console.log(r.status, await r.text());

Respons 200

{
  "items": [
    {
      "id": 1,
      "subscription_id": 1,
      "kind": "events",
      "site_id": 1,
      "count": 12,
      "bytes": 12,
      "webhook_id": "<webhook_id>",
      "state": "queued",
      "attempts": 12,
      "status": 12,
      "created": "2026-11-02T08:00:00Z",
      "next": "2026-11-02T08:00:00Z",
      "expires": "2026-11-02T08:00:00Z",
      "sent": "2026-11-02T08:00:00Z",
      "last_error": "<last_error>",
      "retryable": true
    }
  ],
  "next_before": 12
}

Kirim Lagi Sekarang Pengiriman Yang Gagal Atau Menunggu, Dengan Masa 24 Jam Baru

POST/webhook-deliveries/{id}/retry

Siapa yang dapat memanggil: Akun API pemilik langganan tersebut (dengan tokennya sendiri). Cakupan token: write.

Parameter

KolomTipeDeskripsi
idwajib pathinteger

Respons

StatusArti
200OK
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)
409Konflik

Permintaan

curl -s -X POST "https://<BOX_HOST>/api/v1/webhook-deliveries/1/retry" \
  -H "Authorization: Bearer <API_KEY>"
import requests

r = requests.post(
    "https://<BOX_HOST>/api/v1/webhook-deliveries/1/retry",
    headers={"Authorization": "Bearer <API_KEY>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/webhook-deliveries/1/retry", {
  method: "POST",
  headers: { "Authorization": "Bearer <API_KEY>" },
});
console.log(r.status, await r.text());

Respons 200

{
  "id": 1,
  "subscription_id": 1,
  "kind": "events",
  "site_id": 1,
  "count": 12,
  "bytes": 12,
  "webhook_id": "<webhook_id>",
  "state": "queued",
  "attempts": 12,
  "status": 12,
  "created": "2026-11-02T08:00:00Z",
  "next": "2026-11-02T08:00:00Z",
  "expires": "2026-11-02T08:00:00Z",
  "sent": "2026-11-02T08:00:00Z",
  "last_error": "<last_error>",
  "retryable": true
}

Sirene Dan Relai

Keluaran yang dinyalakan oleh peringatan: papan Modbus TCP, relai dan sirene HTTP, keluaran alarm ONVIF.

Keluaran Sirene Dan Relai Lokasi, Beserta Statusnya

GET/sites/{id}/relays

Siapa yang dapat memanggil: Akun yang menjadi Admin di lokasi tersebut. Cakupan token: read.

Parameter

KolomTipeDeskripsi
idwajib pathinteger

Respons

StatusArti
200OK
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)

Permintaan

curl -s -X GET "https://<BOX_HOST>/api/v1/sites/1/relays" \
  -H "Authorization: Bearer <API_KEY>"
import requests

r = requests.get(
    "https://<BOX_HOST>/api/v1/sites/1/relays",
    headers={"Authorization": "Bearer <API_KEY>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/sites/1/relays", {
  method: "GET",
  headers: { "Authorization": "Bearer <API_KEY>" },
});
console.log(r.status, await r.text());

Respons 200

{
  "items": [
    {
      "id": 1,
      "site_id": 1,
      "name": "Main gate",
      "kind": "modbus",
      "settings": {},
      "kinds": [
        "default"
      ],
      "cameras": [
        12
      ],
      "min_severity": "info",
      "mode": "pulse",
      "pulse_s": 60,
      "active": true,
      "password_set": true,
      "state": {
        "on": true,
        "since": "2026-11-02T08:00:00Z",
        "until": "2026-11-02T08:00:00Z",
        "last_error": "<last_error>"
      }
    }
  ]
}

Tambahkan Keluaran (Papan Modbus TCP, Relai Atau Sirene HTTP, Keluaran Alarm Kamera ONVIF)

POST/sites/{id}/relays

Siapa yang dapat memanggil: Akun yang menjadi Admin di lokasi tersebut. Cakupan token: write.

Parameter

KolomTipeDeskripsi
idwajib pathinteger

Body

KolomTipeDeskripsi
namewajibstring
kindwajibenummodbus, http, onvif
settingswajibobjectper jenis. modbus: host, port (502), unit (1), coil, invert. http: on_url, off_url, method (GET|POST|PUT), username. onvif: device_url, relay_token, username.
kindsstring[]
camerasinteger[]
min_severityenuminfo, warning, critical
modeenumpulse, until_ack
pulse_sinteger
activeboolean
passwordstring

Respons

StatusArti
201Dibuat
400Permintaan tidak valid
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)
413Isi permintaan terlalu besar
415Bukan JSON
422Isi permintaan tidak valid

Permintaan

curl -s -X POST "https://<BOX_HOST>/api/v1/sites/1/relays" \
  -H "Authorization: Bearer <API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{"name":"Main gate","kind":"modbus","settings":{},"kinds":["default"],"cameras":[12],"min_severity":"info","mode":"pulse","pulse_s":60,"active":true,"password":"<password>"}'
import requests

r = requests.post(
    "https://<BOX_HOST>/api/v1/sites/1/relays",
    headers={"Authorization": "Bearer <API_KEY>"},
    json={
      "name": "Main gate",
      "kind": "modbus",
      "settings": {},
      "kinds": [
        "default"
      ],
      "cameras": [
        12
      ],
      "min_severity": "info",
      "mode": "pulse",
      "pulse_s": 60,
      "active": True,
      "password": "<password>"
    },
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/sites/1/relays", {
  method: "POST",
  headers: { "Authorization": "Bearer <API_KEY>", "Content-Type": "application/json" },
  body: JSON.stringify({
    "name": "Main gate",
    "kind": "modbus",
    "settings": {},
    "kinds": [
      "default"
    ],
    "cameras": [
      12
    ],
    "min_severity": "info",
    "mode": "pulse",
    "pulse_s": 60,
    "active": true,
    "password": "<password>"
  }),
});
console.log(r.status, await r.text());

Respons 201

{
  "id": 1,
  "site_id": 1,
  "name": "Main gate",
  "kind": "modbus",
  "settings": {},
  "kinds": [
    "default"
  ],
  "cameras": [
    12
  ],
  "min_severity": "info",
  "mode": "pulse",
  "pulse_s": 60,
  "active": true,
  "password_set": true,
  "state": {
    "on": true,
    "since": "2026-11-02T08:00:00Z",
    "until": "2026-11-02T08:00:00Z",
    "last_error": "<last_error>"
  }
}

Ubah Keluaran (Dijeda Saat Menyala: Dimatikan)

PATCH/relays/{id}

Siapa yang dapat memanggil: Akun yang menjadi Admin di lokasi tersebut. Cakupan token: write.

Parameter

KolomTipeDeskripsi
idwajib pathinteger

Body

KolomTipeDeskripsi
namestring
kindenummodbus, http, onvif
settingsobjectper jenis. modbus: host, port (502), unit (1), coil, invert. http: on_url, off_url, method (GET|POST|PUT), username. onvif: device_url, relay_token, username.
kindsstring[]
camerasinteger[]
min_severityenuminfo, warning, critical
modeenumpulse, until_ack
pulse_sinteger
activeboolean
passwordstringtidak ada: tetap; kosong: dihapus

Respons

StatusArti
200OK
400Permintaan tidak valid
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)
413Isi permintaan terlalu besar
415Bukan JSON
422Isi permintaan tidak valid

Permintaan

curl -s -X PATCH "https://<BOX_HOST>/api/v1/relays/1" \
  -H "Authorization: Bearer <API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{"name":"Main gate","kind":"modbus","settings":{},"kinds":["default"],"cameras":[12],"min_severity":"info","mode":"pulse","pulse_s":60,"active":true,"password":"<password>"}'
import requests

r = requests.patch(
    "https://<BOX_HOST>/api/v1/relays/1",
    headers={"Authorization": "Bearer <API_KEY>"},
    json={
      "name": "Main gate",
      "kind": "modbus",
      "settings": {},
      "kinds": [
        "default"
      ],
      "cameras": [
        12
      ],
      "min_severity": "info",
      "mode": "pulse",
      "pulse_s": 60,
      "active": True,
      "password": "<password>"
    },
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/relays/1", {
  method: "PATCH",
  headers: { "Authorization": "Bearer <API_KEY>", "Content-Type": "application/json" },
  body: JSON.stringify({
    "name": "Main gate",
    "kind": "modbus",
    "settings": {},
    "kinds": [
      "default"
    ],
    "cameras": [
      12
    ],
    "min_severity": "info",
    "mode": "pulse",
    "pulse_s": 60,
    "active": true,
    "password": "<password>"
  }),
});
console.log(r.status, await r.text());

Respons 200

{
  "id": 1,
  "site_id": 1,
  "name": "Main gate",
  "kind": "modbus",
  "settings": {},
  "kinds": [
    "default"
  ],
  "cameras": [
    12
  ],
  "min_severity": "info",
  "mode": "pulse",
  "pulse_s": 60,
  "active": true,
  "password_set": true,
  "state": {
    "on": true,
    "since": "2026-11-02T08:00:00Z",
    "until": "2026-11-02T08:00:00Z",
    "last_error": "<last_error>"
  }
}

Hapus Keluaran (Dimatikan Lebih Dulu)

DELETE/relays/{id}

Siapa yang dapat memanggil: Akun yang menjadi Admin di lokasi tersebut. Cakupan token: write.

Parameter

KolomTipeDeskripsi
idwajib pathinteger

Respons

StatusArti
204Dihapus
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)

Permintaan

curl -s -X DELETE "https://<BOX_HOST>/api/v1/relays/1" \
  -H "Authorization: Bearer <API_KEY>"
import requests

r = requests.delete(
    "https://<BOX_HOST>/api/v1/relays/1",
    headers={"Authorization": "Bearer <API_KEY>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/relays/1", {
  method: "DELETE",
  headers: { "Authorization": "Bearer <API_KEY>" },
});
console.log(r.status, await r.text());

Pulsa Uji 2 Detik Sekarang; Melaporkan Apakah Perangkat Menyala

POST/relays/{id}/test

Siapa yang dapat memanggil: Akun yang menjadi Admin di lokasi tersebut. Cakupan token: write.

Parameter

KolomTipeDeskripsi
idwajib pathinteger

Respons

StatusArti
200OK
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)

Permintaan

curl -s -X POST "https://<BOX_HOST>/api/v1/relays/1/test" \
  -H "Authorization: Bearer <API_KEY>"
import requests

r = requests.post(
    "https://<BOX_HOST>/api/v1/relays/1/test",
    headers={"Authorization": "Bearer <API_KEY>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/relays/1/test", {
  method: "POST",
  headers: { "Authorization": "Bearer <API_KEY>" },
});
console.log(r.status, await r.text());

Respons 200

{
  "ok": true,
  "error": "Text"
}

Matikan Keluaran Sekarang (Hentikan Sirene)

POST/relays/{id}/off

Siapa yang dapat memanggil: Akun yang menjadi Admin di lokasi tersebut. Cakupan token: write.

Parameter

KolomTipeDeskripsi
idwajib pathinteger

Respons

StatusArti
200OK
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)
409Konflik

Permintaan

curl -s -X POST "https://<BOX_HOST>/api/v1/relays/1/off" \
  -H "Authorization: Bearer <API_KEY>"
import requests

r = requests.post(
    "https://<BOX_HOST>/api/v1/relays/1/off",
    headers={"Authorization": "Bearer <API_KEY>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/relays/1/off", {
  method: "POST",
  headers: { "Authorization": "Bearer <API_KEY>" },
});
console.log(r.status, await r.text());

Respons 200

{
  "id": 1,
  "site_id": 1,
  "name": "Main gate",
  "kind": "modbus",
  "settings": {},
  "kinds": [
    "default"
  ],
  "cameras": [
    12
  ],
  "min_severity": "info",
  "mode": "pulse",
  "pulse_s": 60,
  "active": true,
  "password_set": true,
  "state": {
    "on": true,
    "since": "2026-11-02T08:00:00Z",
    "until": "2026-11-02T08:00:00Z",
    "last_error": "<last_error>"
  }
}

50 Peralihan Terakhir, Terbaru Lebih Dulu

GET/relays/{id}/events

Siapa yang dapat memanggil: Akun yang menjadi Admin di lokasi tersebut. Cakupan token: read.

Parameter

KolomTipeDeskripsi
idwajib pathinteger

Respons

StatusArti
200OK
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)

Permintaan

curl -s -X GET "https://<BOX_HOST>/api/v1/relays/1/events" \
  -H "Authorization: Bearer <API_KEY>"
import requests

r = requests.get(
    "https://<BOX_HOST>/api/v1/relays/1/events",
    headers={"Authorization": "Bearer <API_KEY>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/relays/1/events", {
  method: "GET",
  headers: { "Authorization": "Bearer <API_KEY>" },
});
console.log(r.status, await r.text());

Respons 200

{
  "items": [
    {
      "at": "2026-11-02T08:00:00Z",
      "action": "on",
      "cause": "alert",
      "alert_id": 1,
      "ok": true,
      "error": "Text"
    }
  ]
}

Laporan

Laporan PDF dan XLSX yang dibuat sekarang atau terjadwal.

Laporan Yang Tersedia Di Dasbor Ini

GET/reports/kinds

Siapa yang dapat memanggil: Setiap akun API. Cakupan token: read.

Respons

StatusArti
200OK
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)

Permintaan

curl -s -X GET "https://<BOX_HOST>/api/v1/reports/kinds" \
  -H "Authorization: Bearer <API_KEY>"
import requests

r = requests.get(
    "https://<BOX_HOST>/api/v1/reports/kinds",
    headers={"Authorization": "Bearer <API_KEY>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/reports/kinds", {
  method: "GET",
  headers: { "Authorization": "Bearer <API_KEY>" },
});
console.log(r.status, await r.text());

Respons 200

{
  "items": [
    {
      "id": "<id>",
      "title": {
        "en": "<en>",
        "id": "<id>"
      }
    }
  ]
}

File Laporan Lokasi, Terbaru Lebih Dulu (Disimpan 90 Hari)

GET/sites/{id}/reports

Siapa yang dapat memanggil: Akun dengan peran (Pemantau atau Admin) di lokasi tersebut. Cakupan token: read.

Parameter

KolomTipeDeskripsi
idwajib pathinteger
limit queryinteger1..500, bawaan 100

Respons

StatusArti
200OK
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)

Permintaan

curl -s -X GET "https://<BOX_HOST>/api/v1/sites/1/reports?limit=50" \
  -H "Authorization: Bearer <API_KEY>"
import requests

r = requests.get(
    "https://<BOX_HOST>/api/v1/sites/1/reports?limit=50",
    headers={"Authorization": "Bearer <API_KEY>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/sites/1/reports?limit=50", {
  method: "GET",
  headers: { "Authorization": "Bearer <API_KEY>" },
});
console.log(r.status, await r.text());

Respons 200

{
  "items": [
    {
      "id": 1,
      "site_id": 1,
      "report": "<report>",
      "title": "Weekly summary",
      "period": "1h",
      "language": "en",
      "format": "pdf",
      "bytes": 12,
      "created": "2026-11-02T08:00:00Z",
      "created_by": "<created_by>",
      "schedule_id": 1,
      "download": "<download>"
    }
  ]
}

Buat Laporan Sekarang Untuk Tanggal Lokal Di Zona Waktu Lokasi (Paling Lama 366 Hari)

POST/sites/{id}/reports

Siapa yang dapat memanggil: Akun dengan peran (Pemantau atau Admin) di lokasi tersebut. Cakupan token: write.

Parameter

KolomTipeDeskripsi
idwajib pathinteger

Body

KolomTipeDeskripsi
reportwajibstring
fromwajibdate
towajibdate
languageenumen, id
formatsenum[]

Respons

StatusArti
201Dibuat
400Permintaan tidak valid
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)
413Isi permintaan terlalu besar
415Bukan JSON
422Isi permintaan tidak valid

Permintaan

curl -s -X POST "https://<BOX_HOST>/api/v1/sites/1/reports" \
  -H "Authorization: Bearer <API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{"report":"<report>","from":"2026-11-02","to":"2026-11-02","language":"en","formats":["pdf"]}'
import requests

r = requests.post(
    "https://<BOX_HOST>/api/v1/sites/1/reports",
    headers={"Authorization": "Bearer <API_KEY>"},
    json={
      "report": "<report>",
      "from": "2026-11-02",
      "to": "2026-11-02",
      "language": "en",
      "formats": [
        "pdf"
      ]
    },
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/sites/1/reports", {
  method: "POST",
  headers: { "Authorization": "Bearer <API_KEY>", "Content-Type": "application/json" },
  body: JSON.stringify({
    "report": "<report>",
    "from": "2026-11-02",
    "to": "2026-11-02",
    "language": "en",
    "formats": [
      "pdf"
    ]
  }),
});
console.log(r.status, await r.text());

Respons 201

{
  "items": [
    {
      "id": 1,
      "site_id": 1,
      "report": "<report>",
      "title": "Weekly summary",
      "period": "1h",
      "language": "en",
      "format": "pdf",
      "bytes": 12,
      "created": "2026-11-02T08:00:00Z",
      "created_by": "<created_by>",
      "schedule_id": 1,
      "download": "<download>"
    }
  ]
}

Unduh File Laporan

GET/reports/files/{id}

Siapa yang dapat memanggil: Akun dengan peran (Pemantau atau Admin) di lokasi tersebut. Cakupan token: read, export.

Parameter

KolomTipeDeskripsi
idwajib pathinteger

Respons

StatusArti
200File
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)

Permintaan

curl -s -X GET "https://<BOX_HOST>/api/v1/reports/files/1" \
  -H "Authorization: Bearer <API_KEY>"
import requests

r = requests.get(
    "https://<BOX_HOST>/api/v1/reports/files/1",
    headers={"Authorization": "Bearer <API_KEY>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/reports/files/1", {
  method: "GET",
  headers: { "Authorization": "Bearer <API_KEY>" },
});
console.log(r.status, await r.text());

Hapus File Laporan

DELETE/reports/files/{id}

Siapa yang dapat memanggil: Akun yang menjadi Admin di lokasi tersebut. Cakupan token: write.

Parameter

KolomTipeDeskripsi
idwajib pathinteger

Respons

StatusArti
204Dihapus
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)

Permintaan

curl -s -X DELETE "https://<BOX_HOST>/api/v1/reports/files/1" \
  -H "Authorization: Bearer <API_KEY>"
import requests

r = requests.delete(
    "https://<BOX_HOST>/api/v1/reports/files/1",
    headers={"Authorization": "Bearer <API_KEY>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/reports/files/1", {
  method: "DELETE",
  headers: { "Authorization": "Bearer <API_KEY>" },
});
console.log(r.status, await r.text());

Laporan Terjadwal Lokasi

GET/sites/{id}/report-schedules

Siapa yang dapat memanggil: Akun yang menjadi Admin di lokasi tersebut. Cakupan token: read.

Parameter

KolomTipeDeskripsi
idwajib pathinteger

Respons

StatusArti
200OK
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)

Permintaan

curl -s -X GET "https://<BOX_HOST>/api/v1/sites/1/report-schedules" \
  -H "Authorization: Bearer <API_KEY>"
import requests

r = requests.get(
    "https://<BOX_HOST>/api/v1/sites/1/report-schedules",
    headers={"Authorization": "Bearer <API_KEY>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/sites/1/report-schedules", {
  method: "GET",
  headers: { "Authorization": "Bearer <API_KEY>" },
});
console.log(r.status, await r.text());

Respons 200

{
  "items": [
    {
      "id": 1,
      "site_id": 1,
      "report": "<report>",
      "period": "daily",
      "hour": 7,
      "recipients": [
        12
      ],
      "formats": [
        "pdf"
      ],
      "active": true,
      "next_run": "2026-11-02T08:00:00Z",
      "last_run": "2026-11-02T08:00:00Z",
      "last_error": "<last_error>"
    }
  ]
}

Jadwalkan Laporan (Dikirim Lewat E-Mail Ke Kontak Yang Dipilih Dalam Bahasa Mereka)

POST/sites/{id}/report-schedules

Siapa yang dapat memanggil: Akun yang menjadi Admin di lokasi tersebut. Cakupan token: write.

Parameter

KolomTipeDeskripsi
idwajib pathinteger

Body

KolomTipeDeskripsi
reportwajibstring
periodwajibenumdaily: hari sebelumnya; weekly (setiap Senin): Senin sampai Minggu sebelumnya; monthly (tanggal 1): bulan sebelumnya daily, weekly, monthly
hourintegerjam lokal pengiriman
recipientsinteger[]id kontak lokasi (kontak dengan alamat e-mail menerimanya, dalam bahasa mereka)
formatsenum[]
activeboolean

Respons

StatusArti
201Dibuat
400Permintaan tidak valid
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)
413Isi permintaan terlalu besar
415Bukan JSON
422Isi permintaan tidak valid

Permintaan

curl -s -X POST "https://<BOX_HOST>/api/v1/sites/1/report-schedules" \
  -H "Authorization: Bearer <API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{"report":"<report>","period":"daily","hour":7,"recipients":[12],"formats":["pdf"],"active":true}'
import requests

r = requests.post(
    "https://<BOX_HOST>/api/v1/sites/1/report-schedules",
    headers={"Authorization": "Bearer <API_KEY>"},
    json={
      "report": "<report>",
      "period": "daily",
      "hour": 7,
      "recipients": [
        12
      ],
      "formats": [
        "pdf"
      ],
      "active": True
    },
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/sites/1/report-schedules", {
  method: "POST",
  headers: { "Authorization": "Bearer <API_KEY>", "Content-Type": "application/json" },
  body: JSON.stringify({
    "report": "<report>",
    "period": "daily",
    "hour": 7,
    "recipients": [
      12
    ],
    "formats": [
      "pdf"
    ],
    "active": true
  }),
});
console.log(r.status, await r.text());

Respons 201

{
  "id": 1,
  "site_id": 1,
  "report": "<report>",
  "period": "daily",
  "hour": 7,
  "recipients": [
    12
  ],
  "formats": [
    "pdf"
  ],
  "active": true,
  "next_run": "2026-11-02T08:00:00Z",
  "last_run": "2026-11-02T08:00:00Z",
  "last_error": "<last_error>"
}

Ubah Jadwal (Waktu Jatuh Tempo Berikutnya Menyesuaikan)

PATCH/report-schedules/{id}

Siapa yang dapat memanggil: Akun yang menjadi Admin di lokasi tersebut. Cakupan token: write.

Parameter

KolomTipeDeskripsi
idwajib pathinteger

Body

KolomTipeDeskripsi
reportstring
periodenumdaily: hari sebelumnya; weekly (setiap Senin): Senin sampai Minggu sebelumnya; monthly (tanggal 1): bulan sebelumnya daily, weekly, monthly
hourintegerjam lokal pengiriman
recipientsinteger[]id kontak lokasi (kontak dengan alamat e-mail menerimanya, dalam bahasa mereka)
formatsenum[]
activeboolean

Respons

StatusArti
200OK
400Permintaan tidak valid
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)
413Isi permintaan terlalu besar
415Bukan JSON
422Isi permintaan tidak valid

Permintaan

curl -s -X PATCH "https://<BOX_HOST>/api/v1/report-schedules/1" \
  -H "Authorization: Bearer <API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{"report":"<report>","period":"daily","hour":7,"recipients":[12],"formats":["pdf"],"active":true}'
import requests

r = requests.patch(
    "https://<BOX_HOST>/api/v1/report-schedules/1",
    headers={"Authorization": "Bearer <API_KEY>"},
    json={
      "report": "<report>",
      "period": "daily",
      "hour": 7,
      "recipients": [
        12
      ],
      "formats": [
        "pdf"
      ],
      "active": True
    },
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/report-schedules/1", {
  method: "PATCH",
  headers: { "Authorization": "Bearer <API_KEY>", "Content-Type": "application/json" },
  body: JSON.stringify({
    "report": "<report>",
    "period": "daily",
    "hour": 7,
    "recipients": [
      12
    ],
    "formats": [
      "pdf"
    ],
    "active": true
  }),
});
console.log(r.status, await r.text());

Respons 200

{
  "id": 1,
  "site_id": 1,
  "report": "<report>",
  "period": "daily",
  "hour": 7,
  "recipients": [
    12
  ],
  "formats": [
    "pdf"
  ],
  "active": true,
  "next_run": "2026-11-02T08:00:00Z",
  "last_run": "2026-11-02T08:00:00Z",
  "last_error": "<last_error>"
}

Hapus Jadwal

DELETE/report-schedules/{id}

Siapa yang dapat memanggil: Akun yang menjadi Admin di lokasi tersebut. Cakupan token: write.

Parameter

KolomTipeDeskripsi
idwajib pathinteger

Respons

StatusArti
204Dihapus
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)

Permintaan

curl -s -X DELETE "https://<BOX_HOST>/api/v1/report-schedules/1" \
  -H "Authorization: Bearer <API_KEY>"
import requests

r = requests.delete(
    "https://<BOX_HOST>/api/v1/report-schedules/1",
    headers={"Authorization": "Bearer <API_KEY>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/report-schedules/1", {
  method: "DELETE",
  headers: { "Authorization": "Bearer <API_KEY>" },
});
console.log(r.status, await r.text());

Kirim Sekarang Untuk Periode Lengkap Terakhir

POST/report-schedules/{id}/run

Siapa yang dapat memanggil: Akun yang menjadi Admin di lokasi tersebut. Cakupan token: write.

Parameter

KolomTipeDeskripsi
idwajib pathinteger

Respons

StatusArti
200OK
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)
503Mesin analitik tidak menjawab (engine_unavailable); coba lagi setelah Retry-After

Permintaan

curl -s -X POST "https://<BOX_HOST>/api/v1/report-schedules/1/run" \
  -H "Authorization: Bearer <API_KEY>"
import requests

r = requests.post(
    "https://<BOX_HOST>/api/v1/report-schedules/1/run",
    headers={"Authorization": "Bearer <API_KEY>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/report-schedules/1/run", {
  method: "POST",
  headers: { "Authorization": "Bearer <API_KEY>" },
});
console.log(r.status, await r.text());

Respons 200

{
  "files": [
    12
  ],
  "queued": 12
}

Sistem

Apakah dasbor sedang berjalan.

Apakah Dasbor Sedang Berjalan

GET/health

Siapa yang dapat memanggil: Tanpa autentikasi.

Respons

StatusArti
200OK

Permintaan

curl -s -X GET "https://<BOX_HOST>/api/v1/health"
import requests

r = requests.get(
    "https://<BOX_HOST>/api/v1/health",
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/health", {
  method: "GET",
});
console.log(r.status, await r.text());

Respons 200

{
  "status": "ok"
}

Sertifikat TLS Dasbor Sebagai PEM (box.pem), Agar Klien Dapat Memverifikasi Sambungan

GET/system/certificate

Sertifikat perangkat sebagai berkas PEM (box.pem), hanya sertifikatnya, tidak pernah kuncinya; header X-Certificate-SHA256 memuat sidik jarinya. Sertifikat ini bersifat publik, sehingga token akun API mana pun dengan read dapat mengambilnya. Bandingkan sidik jarinya dengan sidik jari yang dibaca Admin di dasbor sebelum klien Anda memercayai berkas itu. Menjawab 404 dengan kode certificate_not_available jika dasbor diakses melalui proxy yang memegang sertifikatnya.

Siapa yang dapat memanggil: Setiap akun API. Cakupan token: read.

Respons

StatusArti
200Rantai sertifikat, hanya sertifikatnya (tidak pernah kuncinya); sidik jarinya juga ada di X-Certificate-SHA256
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)
404Tidak ditemukan (juga bila akun tidak memiliki peran di lokasi tersebut)

Permintaan

curl -s -X GET "https://<BOX_HOST>/api/v1/system/certificate" \
  -H "Authorization: Bearer <API_KEY>"
import requests

r = requests.get(
    "https://<BOX_HOST>/api/v1/system/certificate",
    headers={"Authorization": "Bearer <API_KEY>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/system/certificate", {
  method: "GET",
  headers: { "Authorization": "Bearer <API_KEY>" },
});
console.log(r.status, await r.text());

Apakah Dasbor Memiliki Sertifikat Untuk Diunduh, Sidik Jari SHA-256-nya Dan Nama Yang Dicakupnya

GET/system/certificate/info

Apakah perangkat memiliki sertifikat untuk diberikan, asalnya, sidik jari SHA-256-nya (angka yang dibandingkan dengan yang terlihat oleh klien Anda) dan nama yang dicakupnya: nama host dan alamat yang dapat dipakai klien Anda untuk tersambung.

Siapa yang dapat memanggil: Setiap akun API. Cakupan token: read.

Respons

StatusArti
200OK
401Tidak terautentikasi: token tidak ada, salah, dicabut atau kedaluwarsa (token_invalid)
403Dilarang: akun tidak memiliki peran untuk ini, tidak memiliki cakupan (scope_required), atau panggilan ini ditolak untuk token API (api_account_refused)

Permintaan

curl -s -X GET "https://<BOX_HOST>/api/v1/system/certificate/info" \
  -H "Authorization: Bearer <API_KEY>"
import requests

r = requests.get(
    "https://<BOX_HOST>/api/v1/system/certificate/info",
    headers={"Authorization": "Bearer <API_KEY>"},
)
print(r.status_code, r.text)
const r = await fetch("https://<BOX_HOST>/api/v1/system/certificate/info", {
  method: "GET",
  headers: { "Authorization": "Bearer <API_KEY>" },
});
console.log(r.status, await r.text());

Respons 200

{
  "available": true,
  "filename": "box.pem",
  "source": "self-signed",
  "sha256": "3A:1F:00:7C:AA:42:9B:10:5E:61:D3:0C:88:24:F7:93:2B:6E:C1:58:04:9A:7D:E2:13:B5:66:0F:4C:D8:A1:39",
  "certificates": 1,
  "names": [
    "<BOX_HOST>",
    "<BOX_HOST>.local",
    "localhost",
    "::1",
    "<BOX_LAN_ADDRESS>"
  ]
}
Apakah halaman ini membantu?