Hướng dẫn tích hợp dữ liệu TingPush cho lập trình viên
Trang bắt đầu dành cho đơn vị làm phần mềm (bãi xe, tòa nhà, nhà máy, nhân sự – chấm công, cửa hàng…) muốn đưa dữ liệu từ camera TingPush vào hệ thống của mình: biển số, sự kiện AI (xâm nhập, khuôn mặt, đếm người / xe, quá đông, model tùy chỉnh), chấm công, và điều khiển (mở barie, danh sách xe, danh sách nhân viên). Đọc trang này trước, rồi đi vào tài liệu chi tiết của từng phần.
1. Chọn cách tích hợp
Camera TingPush gửi dữ liệu theo một trong hai đường (chủ camera chọn trên app TingPush Camera → Cài đặt camera → Gửi dữ liệu biển số → Nơi nhận dữ liệu):
(A) Camera ──đẩy ngay (HTTP POST)──────────────────────────────► Máy chủ của bạn (API riêng)
(B) Camera ──► Máy chủ TingPush (lưu theo gói) ◄──kéo về (API v1, khóa API)── Phần mềm của bạn
│
└──► app / web / phần mềm Windows xem, xuất Excel, cảnh báo điện thoại
| (A) Camera đẩy về API riêng | (B) Kéo từ TingPush qua API v1 | |
|---|---|---|
| Dữ liệu | Biển số + chấm công | Biển số, sự kiện AI, số đếm, chấm công, bảng công, nhân viên, thiết bị, danh sách xe |
| Độ trễ | Tức thì (dưới 1 giây sau khi đọc) | Theo chu kỳ bạn gọi (thường 5–30 giây) |
| Bạn cần | Một endpoint HTTP camera gọi tới được (Internet hoặc mạng nội bộ bãi xe) | Gọi ra Internet; không cần mở cổng |
| Lưu trữ | Bạn tự lưu | TingPush lưu theo gói (xem, xuất file, cảnh báo trên app vẫn dùng được) |
| Mất mạng | Camera giữ hàng đợi (tối đa 300 bản), gửi bù | Camera gửi bù về TingPush; bạn kéo tiếp từ since_id cũ — không mất |
| Tài liệu | Hướng dẫn viết API nhận kết quả đọc biển số từ camera TingPush, Chấm công bằng khuôn mặt — camera TingPush làm máy chấm công mục 5 | Hướng dẫn API công khai TingPush — lấy dữ liệu biển số đã lưu và trang này |
Gợi ý chọn:
- Phần mềm bãi xe chạy tại chỗ, cần mở barie ngay theo biển số → (A). Hoặc để camera tự mở barie theo danh sách xe (không cần phần mềm của bạn quyết định — Thiết bị ngoại vi — mở barie, cửa cuốn, còi, đèn từ camera TingPush), còn dữ liệu đi (B).
- Báo cáo, đối soát, kế toán, nhân sự – tính lương, dashboard → (B): không phải dựng máy chủ nhận, không lo mất dữ liệu, khách hàng vẫn xem được trên app.
- Sự kiện AI và số đếm chỉ đi đường (B) — camera gửi về TingPush để báo điện thoại.
- Một camera chỉ chọn một Nơi nhận cho biển số / chấm công. Cần cả hai (vừa nhận tức thì vừa lưu trên TingPush): chọn (B) và gọi API v1 mỗi 5 giây, hoặc liên hệ TingPush.
Ngoài ra không cần lập trình: xuất Excel (CSV) trên app / web, hoặc Excel / Power BI Lấy dữ liệu từ web (mục 9).
2. Bắt đầu nhanh (10 phút)
- Nhận camera vào tài khoản (app → Thêm camera), để Nơi nhận dữ liệu = Máy chủ TingPush.
- Tài khoản cần gói có quyền API (app → Tài khoản → Gói dịch vụ).
- 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 dạngtp_+ 40 ký tự, chỉ hiện một lần. Tích Điều khiển thiết bị & sửa danh sách xe nếu phần mềm cần mở barie, sửa danh sách xe hoặc nhân viên. - Gọi thử:
curl -H "X-Api-Key: tp_xxx" https://apiwebrtc.tingpush.com/api/v1/cameras
curl -H "X-Api-Key: tp_xxx" "https://apiwebrtc.tingpush.com/api/v1/plates?limit=5"
- Tạo dữ liệu thử: cho xe đi qua camera, hoặc trên app bấm Gửi thử (biển mẫu
30A-123.45) / Thử cảnh báo (sự kiện AI mẫu,test: true). - Viết vòng đồng bộ theo mục 6.
3. Xác thực, giới hạn, lỗi
Địa chỉ gốc: https://apiwebrtc.tingpush.com/api/v1
Xác thực: X-Api-Key: tp_… (hoặc Authorization: Bearer tp_…)
Giới hạn: 120 yêu cầu / phút / khóa → vượt: 429, chờ tới phút sau
Định dạng: JSON UTF-8, tên trường snake_case
- Khóa thấy mọi camera tài khoản xem được (camera mình là chủ + camera được chia sẻ). Khóa thường chỉ đọc; khóa có quyền điều khiển mới gọi được các lệnh thay đổi (mục 5, cột Quyền).
- Mỗi tài khoản tối đa 10 khóa. Mỗi phần mềm / mỗi nơi lắp đặt nên dùng một khóa riêng — xóa khóa là vô hiệu ngay, không
ảnh hưởng phần mềm khác. Tên khóa hiện trong nhật ký đóng / mở thiết bị (
API: <tên khóa>). - Gọi từ máy chủ của bạn, không nhúng khóa vào trang web / app phát cho người dùng (lộ khóa = lộ toàn bộ dữ liệu). API không mở CORS cho website khác.
- Ảnh (
*_image_url,photo_url) cũng cần header khóa API — tải về máy chủ của bạn rồi phục vụ lại, đừng đưa thẳng URL cho trình duyệt.
| Mã | Ý nghĩa | Nên làm |
|---|---|---|
| 200 / 204 | Thành công (204: xóa xong, không có nội dung) | |
| 400 | Tham số / dữ liệu sai — {"error":"bad_request","message":"…"} |
Sửa dữ liệu, không gửi lại y nguyên |
| 401 | Thiếu / sai khóa, khóa đã xóa, hoặc gói không có quyền API — {"error":"unauthorized",…} |
Dừng, báo người quản trị |
| 403 | Khóa chỉ đọc gọi lệnh thay đổi, không có quyền với camera, hoặc gói không cho xuất file | Dùng khóa có quyền điều khiển / nâng gói |
| 404 | Không có bản ghi / ảnh (hoặc không có quyền xem camera đó) | |
| 429 | Vượt 120 yêu cầu / phút | Chờ 60 giây rồi gọi tiếp |
| 503 | Camera mất kết nối / thiết bị báo lỗi (lệnh tới camera: mở barie…) | Thử lại sau, message ghi lý do |
| 5xx khác | Lỗi tạm thời phía máy chủ | Thử lại với thời gian chờ tăng dần |
Thông báo lỗi (message / title) là tiếng Việt, hiển thị được cho người dùng.
4. Quy ước dữ liệu
| Thời gian | time (ISO 8601 giờ Việt Nam, VD 2026-10-16T10:02:54+07:00) + timestamp (giây UNIX, nên dùng để lưu / so sánh). received_at = lúc máy chủ nhận — camera mất mạng gửi bù thì received_at muộn hơn time. |
| Tham số thời gian | from, to dạng ISO 8601, khoảng [from, to). Mã hóa dấu + trong URL: from=2026-10-16T00:00:00%2B07:00 (để nguyên + sẽ thành dấu cách → 400). Bảng công dùng ngày yyyy-MM-dd. |
| Mã camera | LPR- + 12 ký tự (VD LPR-9MHK902C8J5Z), không đổi suốt đời camera — dùng làm khóa camera. Tên camera (camera_name) đổi được. |
id bản ghi |
Số nguyên tăng dần theo thứ tự máy chủ nhận, không đổi — khóa đồng bộ. Mỗi loại (biển số, sự kiện, chấm công) có dãy id riêng. |
| Phân trang | Không có since_id: mới nhất trước, trang sau dùng before_id = id nhỏ nhất vừa nhận. Có since_id: cũ nhất trước (đồng bộ), trả next_since_id + has_more. limit 1–1000 (mặc định 100). |
| Biển số | plate đã chuẩn hóa (chữ in hoa + số, không dấu, VD 51G12345) để lưu / so khớp; plate_display để hiển thị (51G-123.45). Tham số lọc chấp nhận mọi cách viết. |
| Thời gian lưu | Bản ghi + ảnh quá hạn của gói bị xóa tự động (chấm công có hạn riêng, mặc định 400 ngày) — đồng bộ về hệ thống của bạn nếu cần giữ lâu. |
| Trường mới | Bản sau có thể thêm trường — bỏ qua trường không biết, đừng kiểm tra cứng danh sách trường. |
| Dữ liệu thử | test: true (sự kiện AI) — vẫn trả qua API, nên bỏ qua khi tính báo cáo. Biển số Gửi thử không lưu trên TingPush. |
5. Danh mục API v1
Tất cả dưới https://apiwebrtc.tingpush.com/api/v1. Quyền: Đ = khóa chỉ đọc là đủ, ĐK = cần khóa có quyền điều khiển.
Camera & biển số — Hướng dẫn API công khai TingPush — lấy dữ liệu biển số đã lưu
| Lệnh | Quyền | |
|---|---|---|
GET /cameras |
Đ | Camera của tài khoản: id, name, role (owner / viewer), online, last_seen |
GET /plates |
Đ | Biển số: lọc camera, plate, from, to; đồng bộ since_id; before_id, limit |
GET /plates/{id} |
Đ | Một bản ghi |
GET /plates/{id}/image/plate · /image/scene |
Đ | Ảnh cắt biển / ảnh toàn cảnh (JPEG) |
GET /export?format=csv (hoặc json) |
Đ | Xuất file (tối đa 200 000 dòng), cùng bộ lọc với /plates; gói phải cho xuất file |
Sự kiện AI — 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
| Lệnh | Quyền | |
|---|---|---|
GET /events |
Đ | Sự kiện: lọc camera, type (intrusion, face, occupancy, count, custom, io; nhiều loại cách dấu phẩy), from, to; since_id, before_id, limit |
GET /events/{id}/image/scene · /image/crop |
Đ | Ảnh toàn cảnh / ảnh cắt đối tượng |
GET /counts |
Đ | Số đếm qua vạch: camera, from, to (mặc định 24 giờ, tối đa 400 ngày), bucket = hour / day / month, by_line=true |
GET /occupancy |
Đ | Số đang ở bên trong (vào − ra) từng camera |
Chấm công & nhân viên — Chấm công bằng khuôn mặt — camera TingPush làm máy chấm công
| Lệnh | Quyền | |
|---|---|---|
GET /attendance |
Đ | Lần chấm công: lọc camera, person, from, to; since_id, before_id, limit |
GET /attendance/{id}/image/face · /image/scene |
Đ | Ảnh mặt / ảnh toàn cảnh của lần chấm |
GET /attendance/timesheet?from=&to=&department= |
Đ | Bảng công đã tính (tối đa 62 ngày, ngày yyyy-MM-dd) |
GET /employees |
Đ | Nhân viên: id, code, name, department, note, photo_url, cameras[] |
GET /employees/{id}/photo |
Đ | Ảnh chân dung đã đăng ký |
POST /employees |
ĐK | Thêm nhân viên kèm ảnh (JPEG base64) và camera |
PUT /employees/{id} |
ĐK | Sửa (chỉ trường gửi lên); photo = đổi ảnh; cameras = đặt lại camera |
DELETE /employees/{id} |
ĐK | Xóa (lịch sử chấm công vẫn giữ) |
Thiết bị ngoại vi & danh sách xe — Thiết bị ngoại vi — mở barie, cửa cuốn, còi, đèn từ camera TingPush mục 6
| Lệnh | Quyền | |
|---|---|---|
GET /cameras/{id}/outputs |
Đ | Thiết bị gắn camera (barie, cửa cuốn, còi…) + trạng thái |
POST /cameras/{id}/outputs/{index}/trigger |
ĐK | Mở (pulse) / bật (on) / tắt (off) |
GET /platelists |
Đ | Danh sách xe cho vào |
GET /platelists/{id}/entries?q=&offset=&limit= |
Đ | Xe trong danh sách |
POST /platelists/{id}/entries |
ĐK | Thêm / cập nhật 1 xe (hạn dùng valid_from, valid_to) |
DELETE /platelists/{id}/entries/{biển} |
ĐK | Xóa 1 xe |
POST /platelists/{id}/import |
ĐK | Gộp / thay cả danh sách từ CSV |
6. Đồng bộ dữ liệu về hệ thống của bạn
Cách chuẩn cho mọi loại có since_id (/plates, /events, /attendance):
với mỗi loại (plates, events, attendance):
last_id = đọc từ CSDL của bạn (lần đầu = 0)
lặp:
GET /<loại>?since_id={last_id}&limit=500
lưu từng bản ghi — UNIQUE theo id (gặp id đã có thì bỏ qua)
(tùy chọn) tải ảnh về kho của bạn
last_id = next_since_id ← ghi CÙNG giao dịch với các bản ghi
has_more = true → gọi lại ngay; false → chờ 5–30 giây
- Không sót, không trùng:
idtăng theo thứ tự máy chủ nhận, kể cả bản ghi camera gửi bù sau khi mất mạng. - Lưu
last_idcùng giao dịch với bản ghi: phần mềm tắt giữa chừng thì lần sau đọc lại từ chỗ cũ, UNIQUE theoidchặn trùng. - Ba loại × 1 lần / 10 giây = 18 yêu cầu / phút, cộng tải ảnh — còn dư nhiều trong hạn mức 120 / phút. Tải ảnh nhiều thì giãn ra hoặc chỉ tải ảnh khi người dùng mở xem.
- Gặp
429→ chờ 60 giây;5xx/ mất mạng → chờ 5 → 10 → 20 → 60 giây rồi thử lại;401→ dừng và báo người quản trị. - Sau khi đồng bộ, nên lưu
time/timestamp(giờ sự việc) để báo cáo,received_atđể soát độ trễ.
Python — đồng bộ đầy đủ (biển số, sự kiện, chấm công + ảnh)
Chạy được ngay (Python 3.9+, pip install requests), lưu vào SQLite — thay phần lưu bằng CSDL của bạn.
"""Đồng bộ dữ liệu TingPush về CSDL: biển số, sự kiện AI, chấm công (kèm ảnh)."""
import json, os, sqlite3, time
import requests
API = "https://apiwebrtc.tingpush.com/api/v1"
KEY = os.environ["TINGPUSH_KEY"] # tp_…
IMG_DIR = "anh" # thư mục lưu ảnh; None = không tải ảnh
s = requests.Session()
s.headers["X-Api-Key"] = KEY
db = sqlite3.connect("tingpush.db")
db.executescript("""
CREATE TABLE IF NOT EXISTS sync_state (kind TEXT PRIMARY KEY, last_id INTEGER NOT NULL);
CREATE TABLE IF NOT EXISTS plates (id INTEGER PRIMARY KEY, camera_id TEXT, plate TEXT, plate_display TEXT,
ts INTEGER, allowed INTEGER, raw TEXT);
CREATE TABLE IF NOT EXISTS events (id INTEGER PRIMARY KEY, camera_id TEXT, type TEXT, summary TEXT, ts INTEGER,
test INTEGER, raw TEXT);
CREATE TABLE IF NOT EXISTS attendance (id INTEGER PRIMARY KEY, camera_id TEXT, person_id TEXT, employee_code TEXT,
name TEXT, ts INTEGER, source TEXT, raw TEXT);
""")
def get(path, **params):
"""GET có thử lại: 429 chờ 60 s, lỗi mạng / 5xx chờ tăng dần."""
delay = 5
while True:
try:
r = s.get(f"{API}{path}", params=params, timeout=30)
if r.status_code == 429:
time.sleep(60); continue
if r.status_code >= 500:
raise requests.HTTPError(f"HTTP {r.status_code}")
r.raise_for_status() # 400 / 401 / 403 / 404: lỗi cần người xem, không thử lại
return r
except (requests.ConnectionError, requests.Timeout, requests.HTTPError) as e:
if isinstance(e, requests.HTTPError) and e.response is not None and e.response.status_code < 500:
raise
print("Lỗi tạm thời:", e, "- thử lại sau", delay, "giây")
time.sleep(delay); delay = min(delay * 2, 60)
def save_image(url, name):
if not url or not IMG_DIR:
return None
path = os.path.join(IMG_DIR, name)
if not os.path.exists(path):
os.makedirs(IMG_DIR, exist_ok=True)
with open(path, "wb") as f:
f.write(get(url.replace(API, "")).content)
return path
def store(kind, x):
raw = json.dumps(x, ensure_ascii=False)
if kind == "plates":
db.execute("INSERT OR IGNORE INTO plates VALUES (?,?,?,?,?,?,?)",
(x["id"], x["camera_id"], x["plate"], x["plate_display"], x["timestamp"],
None if x.get("allowed") is None else int(x["allowed"]), raw))
save_image(x.get("plate_image_url"), f"bien_{x['id']}.jpg")
elif kind == "events":
db.execute("INSERT OR IGNORE INTO events VALUES (?,?,?,?,?,?,?)",
(x["id"], x["camera_id"], x["type"], x["summary"], x["timestamp"], int(x.get("test", False)), raw))
save_image(x.get("crop_image_url"), f"su_kien_{x['id']}.jpg")
elif kind == "attendance":
db.execute("INSERT OR IGNORE INTO attendance VALUES (?,?,?,?,?,?,?,?)",
(x["id"], x.get("camera_id"), x.get("person_id"), x.get("employee_code"), x["name"],
x["timestamp"], x["source"], raw))
save_image(x.get("face_image_url"), f"cham_cong_{x['id']}.jpg")
def sync(kind):
row = db.execute("SELECT last_id FROM sync_state WHERE kind=?", (kind,)).fetchone()
last_id = row[0] if row else 0
while True:
page = get(f"/{kind}", since_id=last_id, limit=500).json()
with db: # 1 giao dịch: bản ghi + vị trí đồng bộ
for x in page["data"]:
store(kind, x)
last_id = page["next_since_id"]
db.execute("INSERT OR REPLACE INTO sync_state VALUES (?,?)", (kind, last_id))
if page["data"]:
print(kind, "+", len(page["data"]), "→ last_id", last_id)
if not page["has_more"]:
return
while True:
for kind in ("plates", "events", "attendance"):
sync(kind)
time.sleep(10)
Không dùng loại nào thì bỏ khỏi danh sách ("plates", "events", "attendance"). Gói không có chấm công: /attendance trả
danh sách rỗng.
C# (.NET 8+) — dịch vụ nền đồng bộ
using System.Net;
using System.Net.Http.Json;
using System.Text.Json;
var http = new HttpClient { BaseAddress = new Uri("https://apiwebrtc.tingpush.com/api/v1/"), Timeout = TimeSpan.FromSeconds(30) };
http.DefaultRequestHeaders.Add("X-Api-Key", Environment.GetEnvironmentVariable("TINGPUSH_KEY"));
var lastIds = new Dictionary<string, long> { ["plates"] = 0, ["events"] = 0, ["attendance"] = 0 }; // đọc từ CSDL của bạn
while (true)
{
foreach (var kind in lastIds.Keys.ToList())
{
bool more;
do
{
using var res = await http.GetAsync($"{kind}?since_id={lastIds[kind]}&limit=500");
if (res.StatusCode == HttpStatusCode.TooManyRequests) { await Task.Delay(TimeSpan.FromMinutes(1)); more = true; continue; }
res.EnsureSuccessStatusCode();
var page = await res.Content.ReadFromJsonAsync<JsonElement>();
foreach (var x in page.GetProperty("data").EnumerateArray())
{
// lưu vào CSDL của bạn — UNIQUE theo id (INSERT … WHERE NOT EXISTS / MERGE)
Console.WriteLine($"{kind} #{x.GetProperty("id")} {x.GetProperty("time")}");
}
lastIds[kind] = page.GetProperty("next_since_id").GetInt64(); // lưu cùng giao dịch với bản ghi
more = page.GetProperty("has_more").GetBoolean();
} while (more);
}
await Task.Delay(TimeSpan.FromSeconds(10));
}
Tải ảnh: await http.GetByteArrayAsync(x.GetProperty("plate_image_url").GetString()) (cùng HttpClient đã có header khóa).
Node.js (18+)
const API = 'https://apiwebrtc.tingpush.com/api/v1';
const H = { 'X-Api-Key': process.env.TINGPUSH_KEY };
const last = { plates: 0, events: 0, attendance: 0 }; // đọc từ CSDL của bạn
const sleep = ms => new Promise(ok => setTimeout(ok, ms));
for (;;) {
for (const kind of Object.keys(last)) {
for (;;) {
const r = await fetch(`${API}/${kind}?since_id=${last[kind]}&limit=500`, { headers: H });
if (r.status === 429) { await sleep(60000); continue; }
if (!r.ok) throw new Error(`${kind}: HTTP ${r.status} ${await r.text()}`);
const page = await r.json();
for (const x of page.data) console.log(kind, x.id, x.time); // lưu vào CSDL — UNIQUE theo id
last[kind] = page.next_since_id; // lưu cùng giao dịch
if (!page.has_more) break;
}
}
await sleep(10000);
}
PHP, Excel / Power BI: Hướng dẫn API công khai TingPush — lấy dữ liệu biển số đã lưu mục 4.
Dữ liệu không có since_id
| Dữ liệu | Cách lấy |
|---|---|
| Số đếm theo giờ / ngày | GET /counts?camera=…&from=…&to=…&bucket=hour — gọi riêng từng camera (không có camera = cộng mọi camera), mỗi lần lấy lại khoảng gần nhất (VD 2 giờ qua) và ghi đè theo (camera, line, start): số của giờ đang chạy còn tăng dần |
| Số đang ở bên trong | GET /occupancy mỗi 10–60 giây (camera cập nhật theo chu kỳ đếm) |
| Bảng công | GET /attendance/timesheet?from=…&to=… — tính lại toàn bộ khoảng mỗi lần (bổ sung tay, sửa ca làm việc làm thay đổi kết quả cũ) |
| Danh sách nhân viên, danh sách xe | Đọc khi cần, hoặc mỗi đêm |
7. Nhận dữ liệu đẩy thẳng từ camera (API riêng)
Khi camera đặt Nơi nhận dữ liệu = API riêng, camera POST JSON tới URL của bạn ngay khi đọc được biển hoặc chấm công
thành công — cùng URL, phân biệt bằng type:
# FastAPI — 1 endpoint nhận cả biển số và chấm công. pip install fastapi uvicorn
from fastapi import FastAPI, Header, HTTPException, Request
app = FastAPI()
SEEN = set() # thay bằng bảng có khóa UNIQUE(event_id) trong CSDL
@app.post("/api/tingpush")
async def receive(req: Request, authorization: str | None = Header(None)):
if authorization != "Bearer bi-mat-cua-ban": # header do chủ camera khai báo trên app
raise HTTPException(401) # 4xx: camera bỏ bản ghi, không gửi lại
x = await req.json()
if x.get("test"):
return {"ok": True} # nút "Gửi thử": trả 200, không lưu
if x["event_id"] in SEEN:
return {"ok": True, "duplicate": True} # camera gửi lại do mất trả lời: vẫn 200
if x["type"] == "plate":
print("Biển", x["plate_display"], "camera", x["camera_id"], "cho vào:", x.get("allowed"))
elif x["type"] == "attendance":
print("Chấm công", x["employee_code"], x["name"], x["time"])
# type khác (bản sau có thể thêm): bỏ qua, vẫn trả 200
SEEN.add(x["event_id"])
return {"ok": True} # trả trong < 8 giây; việc chậm đưa vào hàng đợi
Quy tắc bắt buộc (chi tiết: Hướng dẫn viết API nhận kết quả đọc biển số từ camera TingPush mục 3, 6):
- 2xx = đã nhận. 4xx = camera bỏ bản ghi. 5xx / quá giờ / mất kết nối = camera giữ lại và gửi lại.
Lỗi tạm thời (CSDL bận…) phải trả
503, đừng trả4xx. - Bỏ trùng theo
event_id(khóa UNIQUE), gặp trùng vẫn trả200. - Trả lời nhanh (mặc định camera chờ 8 giây); ghi nhận rồi xử lý nặng (gọi hệ thống khác, gửi thông báo) sau.
- Không chuyển hướng (3xx); khai báo đúng URL cuối cùng.
Mã mẫu đầy đủ C#, Node.js, PHP, Python và công cụ tự kiểm tra API: tải bộ mã mẫu (công cụ kiểm tra:
kiem_tra_api.py, JSON mẫu: sample_request.json).
8. Ghi dữ liệu và điều khiển
Cần khóa có quyền Điều khiển thiết bị & sửa danh sách xe.
Mở barie từ phần mềm bãi xe (VD xe vé lượt đã thanh toán):
curl -X POST -H "X-Api-Key: tp_xxx" -H "Content-Type: application/json" -d '{"action":"pulse"}' \
https://apiwebrtc.tingpush.com/api/v1/cameras/LPR-9MHK902C8J5Z/outputs/0/trigger
Đồng bộ xe tháng mỗi đêm từ phần mềm quản lý vé — thay cả danh sách (camera tự tải bản mới, mất mạng vẫn mở cho xe trong danh sách):
curl -X POST -H "X-Api-Key: tp_xxx" -H "Content-Type: application/json" \
-d '{"text":"51G12345,Nguyễn Văn A,01/10/2026,31/10/2026\n30A99999,Xe giám đốc","replace":true}' \
https://apiwebrtc.tingpush.com/api/v1/platelists/3/import
Đồng bộ nhân viên từ phần mềm nhân sự (chấm công khuôn mặt):
import base64, requests
H = {"X-Api-Key": "tp_xxx"}
API = "https://apiwebrtc.tingpush.com/api/v1"
body = {"name": "Trần Thị B", "code": "NV002", "department": "Kho",
"photo": base64.b64encode(open("NV002.jpg", "rb").read()).decode(), # ảnh thẻ JPEG, nhìn thẳng
"cameras": ["LPR-9MHK902C8J5Z"]}
r = requests.post(f"{API}/employees", json=body, headers=H, timeout=120)
emp = r.json()
bad = [c for c in emp.get("cameras", []) if c["state"] == "error"] # VD "không thấy khuôn mặt" -> gửi ảnh khác
print(r.status_code, emp.get("id"), bad)
- Mã nhân viên (
code) không trùng trong tài khoản — dùng nó để khớp với hệ thống của bạn; lưuidTingPush trả về để sửa / xóa sau (PUT/DELETE /employees/{id}). - Nghỉ việc →
DELETE /employees/{id}: camera thôi nhận diện ngay, lịch sử chấm công vẫn giữ. - Thêm nhân viên chờ camera nạp ảnh (vài giây mỗi camera): đặt thời gian chờ HTTP ≥ 60 giây.
9. Kịch bản mẫu
Bãi xe có phần mềm quản lý vé
- Xe tháng: đồng bộ vào danh sách xe cho vào (mục 8) → camera tự mở barie, mất mạng vẫn chạy.
- Xe vé lượt: phần mềm đọc biển (
/platesmỗi 2–5 giây, hoặc camera đẩy API riêng), tính tiền, gọitriggermở barie. - Đối soát: lưu
plate,time, ảnh biển;allowedcho biết camera đã nhận xe trong danh sách. - Nhật ký mở barie (ai mở, vì sao):
GET /events?type=io.
Nhân sự – tính lương (chấm công khuôn mặt)
- Nhân viên: tạo / sửa / xóa qua
/employeestheo hệ thống nhân sự. - Lần chấm:
/attendance?since_id=→ tự tính công theo ca của công ty (nhiều ca, tăng ca…). - Hoặc dùng luôn bảng công TingPush tính:
/attendance/timesheet(một ca chung, đi muộn / về sớm / vắng).
Cửa hàng, tòa nhà — dashboard lưu lượng
GET /counts?bucket=hourcho biểu đồ,GET /occupancycho số đang ở bên trong,GET /events?type=occupancycho cảnh báo quá đông.
Trung tâm giám sát — gom cảnh báo
GET /events?type=intrusion,face,custom&since_id=mỗi 5 giây; ảnh:crop_image_url. Điện thoại của chủ camera đã được báo / gọi qua app — phần mềm của bạn dùng cho trực ban, lưu vết.
Excel / Power BI / Google Sheets — không lập trình
- Excel: Data → From Web → Advanced, URL
https://apiwebrtc.tingpush.com/api/v1/export?format=csv&from=2026-10-01T00:00:00%2B07:00, thêm headerX-Api-Key. - Hoặc tải CSV trên app / web: Biển số → Xuất Excel, Chấm công → Xuất CSV.
10. Kiểm tra trước khi bàn giao
- Khóa API riêng cho phần mềm này, lưu trong cấu hình máy chủ (không trong mã nguồn, không trong ứng dụng phát cho người dùng).
-
last_idlưu bền (CSDL), cùng giao dịch với bản ghi; bảng có khóa UNIQUE theoid(API v1) /event_id(API riêng). - Xử lý
429(chờ 60 giây),5xx/ mất mạng (thử lại tăng dần),401(dừng, báo người quản trị). - Tham số
from/tomã hóa+thành%2B. - Bỏ qua trường không biết và
typekhông biết; bỏ quatest: truekhi tính báo cáo. - Ảnh cần giữ lâu hơn thời gian lưu của gói đã tải về kho của bạn.
- Thử mất mạng: tắt mạng camera 10 phút rồi bật lại — dữ liệu gửi bù về đủ, không trùng.
- API riêng: chạy công cụ kiểm tra
kiem_tra_api.py(đúng mã trả lời, bỏ trùng, chịu được ảnh lớn). - Thông báo cho người bị ghi hình / chấm công theo quy định bảo vệ dữ liệu cá nhân (ảnh khuôn mặt là dữ liệu nhạy cảm).
11. Câu hỏi thường gặp
Có webhook từ TingPush tới máy chủ của tôi không? Hiện chưa — dùng API riêng (camera đẩy thẳng, tức thì) hoặc gọi API v1
với since_id mỗi vài giây (độ trễ vài giây, không mất dữ liệu).
Dữ liệu của camera được chia sẻ cho tôi có qua API không? Có — khóa thấy mọi camera tài khoản xem được. Điều khiển thiết bị còn cần quyền điều khiển trên camera đó.
Lấy ảnh nhân viên / ảnh lần chấm công? photo_url trong /employees, face_image_url / image_url trong /attendance —
tải bằng cùng header khóa API.
Đổi chủ camera thì sao? Dữ liệu cũ thuộc chủ cũ; chủ mới chỉ thấy từ lúc nhận camera.
Môi trường thử nghiệm? Dùng một camera + tài khoản riêng cho thử nghiệm; nút Gửi thử / Thử cảnh báo trên app tạo dữ liệu mẫu không cần xe / người thật.
Cần hỗ trợ? Liên hệ TingPush qua trang Liên hệ trên website — gửi kèm mã camera (LPR-…), thời điểm, yêu cầu và mã lỗi.