TingPush Camera AI

Tài liệu tích hợp

Hướng dẫn API công khai TingPush — lấy dữ liệu biển số đã lưu

English version

Dành cho lập trình viên muốn đưa dữ liệu biển số từ camera TingPush vào phần mềm của mình (quản lý bãi xe, kế toán, chấm công…) mà không phải tự dựng máy chủ nhận dữ liệu.

Mới bắt đầu? Đọc Hướng dẫn tích hợp dữ liệu TingPush cho lập trình viên trước: chọn cách tích hợp, danh mục mọi API, mã đồng bộ đầy đủ.

Có 2 cách nhận dữ liệu từ camera — chọn trên app TingPush Camera → Cài đặt camera → Gửi dữ liệu biển số:

Cách hoạt động Tài liệu
Máy chủ TingPush (mặc định) Camera gửi về TingPush, dữ liệu được lưu theo gói dịch vụ. Bạn kéo dữ liệu về qua API này, hoặc xuất file. tài liệu này
API riêng Camera đẩy thẳng tới URL của bạn ngay khi đọc được biển. Hướng dẫn viết API nhận kết quả đọc biển số từ camera TingPush

1. Chuẩn bị

  1. Camera đã được nhận vào tài khoản (app → Thêm camera) và đặt Nơi nhận dữ liệu = Máy chủ TingPush.
  2. Tài khoản dùng gói có quyền API (app → Tài khoản → Gói dịch vụ). Liên hệ TingPush để nâng gói.
  3. Tạo khóa API: app → Tài khoản → Khóa API → Tạo khóa, hoặc web https://webrtc.tingpush.com/account. Khóa có dạng tp_ + 40 ký tự, chỉ hiện một lần — chép và lưu như mật khẩu. Mỗi tài khoản tối đa 10 khóa; xóa khóa là vô hiệu ngay.

Khóa API thấy được mọi camera tài khoản đó xem được (camera mình là chủ + camera được chia sẻ), chỉ đọc. Khóa tạo với tùy chọn Điều khiển thiết bị & sửa danh sách xe còn mở được barie và sửa danh sách xe cho vào — xem Thiết bị ngoại vi — mở barie, cửa cuốn, còi, đèn từ camera TingPush mục 6.

2. Gọi API

Địa chỉ gốc:  https://apiwebrtc.tingpush.com/api/v1
Xác thực:     X-Api-Key: tp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
              (hoặc Authorization: Bearer tp_xxxx…)
Giới hạn:     120 yêu cầu / phút / khóa — vượt thì trả 429, chờ 1 phút
Định dạng:    JSON UTF-8, tên trường snake_case; thời gian ISO 8601 giờ Việt Nam (+07:00) + "timestamp" (giây UNIX)

Ví dụ nhanh:

curl -H "X-Api-Key: tp_xxx" "https://apiwebrtc.tingpush.com/api/v1/plates?limit=10"
Mã Ý nghĩa
200 Thành công
401 Thiếu / sai khóa, khóa đã xóa, tài khoản bị khóa, hoặc gói không có quyền API
403 Gói không có quyền xuất file (/export)
404 Không có bản ghi / ảnh (hoặc không có quyền với camera đó)
429 Gọi quá nhanh

3. Danh sách endpoint

GET /api/v1/cameras — camera của tài khoản

[
  { "id": "LPR-9MHK902C8J5Z", "name": "Cổng vào", "role": "owner", "online": true, "last_seen": "2026-10-16T03:02:26+00:00" }
]

GET /api/v1/plates — biển số đã lưu

Tham số
camera tùy chọn ID camera (LPR-…)
plate tùy chọn lọc biển chứa chuỗi này, không phân biệt dấu / gạch (VD 30A123)
from, to tùy chọn khoảng thời gian [from, to), ISO 8601, VD 2026-10-16T00:00:00+07:00
since_id tùy chọn đồng bộ tăng dần: trả bản ghi có id > since_id, cũ trước — xem mục 4
before_id tùy chọn phân trang lùi: bản ghi có id < before_id, mới trước
limit tùy chọn 1–1000, mặc định 100

Không có since_id: trả mới nhất trước. Có since_id: trả cũ nhất trước (để đồng bộ).

{
  "data": [
    {
      "id": 1842,
      "camera_id": "LPR-9MHK902C8J5Z",
      "camera_name": "Cổng vào",
      "plate": "51G11111",
      "plate_display": "51G-111.11",
      "raw_text": "51G-11111",
      "confidence": 0.9,
      "read_count": 3,
      "time": "2026-10-16T10:02:54+07:00",
      "timestamp": 1792119774,
      "received_at": "2026-10-16T10:02:55+07:00",
      "box": [520, 320, 760, 400],
      "frame_width": 1280,
      "frame_height": 720,
      "plate_image_url": "https://apiwebrtc.tingpush.com/api/v1/plates/1842/image/plate",
      "image_url": null,
      "allowed": true,
      "allow_name": "Nguyễn Văn A"
    }
  ],
  "next_since_id": 1842,
  "has_more": false
}
Trường Ý nghĩa
id Mã bản ghi trên TingPush, tăng dần, không đổi — dùng làm khóa đồng bộ
plate Biển đã chuẩn hóa (chữ in hoa + số, không dấu) — dùng để lưu / so khớp
plate_display Biển để hiển thị kiểu Việt Nam
time / timestamp Lúc camera xác nhận biển
received_at Lúc máy chủ nhận (camera mất mạng thì gửi bù sau, received_at muộn hơn time)
confidence, read_count Độ tin cậy 0–1, số lần camera đọc trùng trước khi xác nhận
box, frame_width, frame_height Vị trí biển trên khung hình
plate_image_url Ảnh cắt biển số (JPEG) — tải bằng cùng header khóa API; null nếu camera không gửi ảnh biển
image_url Ảnh toàn cảnh — chỉ có khi camera bật gửi ảnh và gói cho lưu ảnh toàn cảnh
allowed, allow_name true = biển trong danh sách xe cho vào (camera đã mở barie nếu có luật), false = không có, null = camera chưa có danh sách; allow_name = tên chủ xe trong danh sách
next_since_id (chỉ khi gọi với since_id) giá trị since_id cho lần gọi sau
has_more còn dữ liệu — gọi tiếp ngay

`GET /api/v1/plates/

Trả một object như phần tử trong data.

`GET /api/v1/plates/

Trả image/jpeg. Ảnh bị xóa cùng bản ghi khi hết thời gian lưu của gói.

GET /api/v1/export?format=csv|json — xuất file

Cùng tham số lọc camera, plate, from, to. Tối đa 200 000 dòng mỗi lần.

  • CSV: UTF-8 có BOM (mở thẳng bằng Excel không lỗi tiếng Việt), dấu phẩy, dòng đầu là tên cột: id,camera_id,camera_name,plate,plate_display,time,timestamp,confidence,read_count,raw_text,plate_image_url,image_url (time dạng yyyy-MM-dd HH:mm:ss giờ Việt Nam).
  • JSON: mảng object, các trường như CSV.

Người dùng không lập trình cũng xuất được: app → tab Biển số → Đã lưu → nút tải; hoặc web → Biển số → Xuất Excel.

GET /api/v1/events — sự kiện AI (xâm nhập, khuôn mặt, đếm)

Tham số giống /plates: camera, type (intrusion, occupancy, face, count, custom, io — đóng / mở thiết bị ngoại vi; nhiều loại cách nhau dấu phẩy), from, to, since_id (đồng bộ tăng dần), before_id, limit (1–1000, mặc định 100).

{
  "data": [
    {
      "id": 812, "camera_id": "LPR-9MHK902C8J5Z", "camera_name": "Cổng kho", "type": "intrusion",
      "summary": "Có người xâm nhập vùng Kho",
      "data": { "zone": "Kho", "class": "person", "box": [0.67, 0.5, 0.83, 0.8], "dwell_s": 2 },
      "time": "2026-10-16T22:15:03+07:00", "timestamp": 1792170903,
      "image_url": "https://apiwebrtc.tingpush.com/api/v1/events/812/image/scene",
      "crop_image_url": "https://apiwebrtc.tingpush.com/api/v1/events/812/image/crop",
      "test": false
    }
  ],
  "next_since_id": null, "has_more": false
}

Trường data theo loại — xem Sự kiện AI & cảnh báo — đếm người / xe, xâm nhập vùng cấm, nhận diện khuôn mặt mục 5. Ảnh: GET /api/v1/events/{id}/image/scene|crop (kèm khóa API).

GET /api/v1/counts — số đếm người / xe qua vạch

camera, from, to (mặc định 24 giờ qua, tối đa 400 ngày), bucket = hour | day | month (giờ Việt Nam), by_line=true để tách theo từng vạch.

{
  "bucket": "hour",
  "data": [
    { "start": "2026-10-16T08:00:00+07:00", "line": null, "person_in": 42, "person_out": 37, "vehicle_in": 5, "vehicle_out": 4 }
  ]
}

GET /api/v1/occupancy — số đang ở bên trong (vào − ra)

Camera tự tính, về 0 mỗi ngày lúc giờ đặt lại. camera (tùy chọn).

{ "data": [ { "camera_id": "LPR-9MHK902C8J5Z", "camera_name": "Cửa hàng", "person": 12, "vehicle": 0, "total": 12, "max": 30,
              "updated_at": "2026-10-16T10:15:00+07:00" } ] }

Thiết bị ngoại vi & danh sách xe — mở barie, sửa danh sách

GET /api/v1/cameras/{id}/outputs, POST /api/v1/cameras/{id}/outputs/{index}/trigger, GET /api/v1/platelists, GET|POST /api/v1/platelists/{id}/entries, DELETE /api/v1/platelists/{id}/entries/{biển}, POST /api/v1/platelists/{id}/import — xem Thiết bị ngoại vi — mở barie, cửa cuốn, còi, đèn từ camera TingPush mục 6 (cần khóa có quyền điều khiển).

Chấm công & nhân viên

GET /api/v1/attendance (lần chấm công, đồng bộ bằng since_id như /plates), GET /api/v1/attendance/timesheet (bảng công), GET|POST /api/v1/employees, PUT|DELETE /api/v1/employees/{id} (thêm / sửa nhân viên kèm ảnh, cần khóa có quyền điều khiển) — xem Chấm công bằng khuôn mặt — camera TingPush làm máy chấm công mục 7.

4. Đồng bộ dữ liệu về phần mềm của bạn (khuyên dùng)

Lưu last_id (bắt đầu = 0) trong CSDL của bạn, chạy định kỳ (VD mỗi 10–30 giây):

loop:
    GET /api/v1/plates?since_id={last_id}&limit=500
    lưu từng bản ghi (bỏ qua nếu id đã có — UNIQUE theo id)
    last_id = next_since_id
    nếu has_more: gọi lại ngay, ngược lại: chờ tới lần chạy sau
  • Không bỏ sót, không trùng: id tăng dần theo thứ tự máy chủ nhận.
  • Ảnh: tải plate_image_url khi cần (cùng header khóa API) và lưu lại nếu muốn giữ lâu hơn thời gian lưu của gói.
  • Mỗi lần gọi tốn 1 yêu cầu trong hạn mức 120/phút — đồng bộ 10 giây/lần là thoải mái.

Python

import time, requests

API = "https://apiwebrtc.tingpush.com/api/v1"
H = {"X-Api-Key": "tp_xxx"}
last_id = 0  # đọc từ CSDL của bạn

while True:
    r = requests.get(f"{API}/plates", params={"since_id": last_id, "limit": 500}, headers=H, timeout=30)
    r.raise_for_status()
    page = r.json()
    for p in page["data"]:
        print(p["id"], p["plate_display"], p["time"], p["camera_name"])   # -> lưu vào CSDL của bạn
    last_id = page["next_since_id"]
    if not page["has_more"]:
        time.sleep(10)

C# (.NET)

using System.Net.Http.Json;
using System.Text.Json;

var http = new HttpClient { BaseAddress = new Uri("https://apiwebrtc.tingpush.com/api/v1/") };
http.DefaultRequestHeaders.Add("X-Api-Key", "tp_xxx");
long lastId = 0; // đọc từ CSDL của bạn

while (true)
{
    var page = await http.GetFromJsonAsync<JsonElement>($"plates?since_id={lastId}&limit=500");
    foreach (var p in page.GetProperty("data").EnumerateArray())
        Console.WriteLine($"{p.GetProperty("id")} {p.GetProperty("plate_display")} {p.GetProperty("time")}");
    lastId = page.GetProperty("next_since_id").GetInt64();
    if (!page.GetProperty("has_more").GetBoolean()) await Task.Delay(TimeSpan.FromSeconds(10));
}

Node.js (18+)

const API = 'https://apiwebrtc.tingpush.com/api/v1', H = { 'X-Api-Key': 'tp_xxx' };
let lastId = 0; // đọc từ CSDL của bạn
for (;;) {
  const r = await fetch(`${API}/plates?since_id=${lastId}&limit=500`, { headers: H });
  if (!r.ok) throw new Error(`HTTP ${r.status}`);
  const page = await r.json();
  for (const p of page.data) console.log(p.id, p.plate_display, p.time);
  lastId = page.next_since_id;
  if (!page.has_more) await new Promise(ok => setTimeout(ok, 10000));
}

PHP

$ctx = stream_context_create(['http' => ['header' => "X-Api-Key: tp_xxx\r\n"]]);
$page = json_decode(file_get_contents("https://apiwebrtc.tingpush.com/api/v1/plates?since_id=$lastId&limit=500", false, $ctx), true);
foreach ($page['data'] as $p) echo $p['id'], ' ', $p['plate_display'], ' ', $p['time'], "\n";
$lastId = $page['next_since_id'];

Excel / Power BI / Google Sheets

Dùng Lấy dữ liệu từ web (Excel: Data → From Web) với URL https://apiwebrtc.tingpush.com/api/v1/export?format=csv&from=2026-10-01T00:00:00%2B07:00 và header X-Api-Key, hoặc tải file CSV từ app / web rồi mở.

5. Gói dịch vụ & tính phí

Do quản trị viên TingPush quy định, xem trên app → Tài khoản → Gói dịch vụ:

Lượt / tháng Mỗi biển số camera gửi về = 1 lượt (bản gửi trùng do mất mạng không tính). Gói "ngừng khi hết": vượt hạn mức thì máy chủ không nhận thêm tới tháng sau (app báo số lượt bị từ chối). Gói khác: tính phí vượt mỗi 1000 lượt.
Thời gian lưu Bản ghi + ảnh quá số ngày của gói bị xóa tự động — đồng bộ về hệ thống của bạn nếu cần giữ lâu.
Ảnh toàn cảnh Chỉ lưu với gói có quyền này; ảnh biển số luôn lưu.
API / xuất file Theo quyền của gói.
Chấm công Gói có quyền chấm công mới nhận bản ghi chấm công; thời gian lưu riêng (mặc định 400 ngày).

Tháng tính theo giờ Việt Nam. Phí tháng = phí gói + phần vượt.

6. Câu hỏi thường gặp

  • Muốn nhận ngay lập tức thay vì kéo định kỳ? Đặt camera sang API riêng để camera đẩy thẳng tới máy chủ của bạn (Hướng dẫn viết API nhận kết quả đọc biển số từ camera TingPush). Một camera chọn một nơi nhận.
  • Không thấy dữ liệu? Kiểm tra: camera Nơi nhận = TingPush; camera đã có chủ; gói chưa hết lượt; biển nằm trong giờ đọc và vùng đọc của camera (app → Cài đặt đọc biển số).
  • Người khác nhận lại camera (bán / chuyển camera): lịch sử cũ thuộc chủ cũ, chủ mới chỉ thấy dữ liệu từ lúc nhận.
  • Xóa tài khoản: toàn bộ biển số, ảnh và khóa API của tài khoản bị xóa ngay.