Nhà phát triển

Mobility Hub API

Kết nối CSMS, ứng dụng và phần mềm của bạn với Mobility Hub: đọc trạm, nhận sự kiện qua webhook. Voucher, khách hàng thân thiết và hồ sơ doanh nghiệp sẽ dùng cùng nền tảng này.

curl http://localhost:3000/api/v1/stations?limit=10 \
  -H "Authorization: Bearer mh_sk_test_…"

Xác thực

Gửi khóa bí mật trong tiêu đề Authorization: Bearer. Khóa live (mh_sk_live_…) làm việc với dữ liệu thật; khóa test (mh_sk_test_…) với dữ liệu thử, không bao giờ hiện cho người lái. Khóa live tạo được sau khi Mobility Hub xác minh tổ chức. Đừng bao giờ đặt khóa bí mật trong ứng dụng di động hay trang web.

Quyền (scope)

Mỗi khóa chỉ gọi được những thao tác mà quyền của nó cho phép; thiếu quyền, API trả 403 insufficient_scope.

  • stations:read: Đọc trạm sạc
  • events:read: Đọc sự kiện

Các thao tác

  • get /v1/me

    The key that made the request, and its organization. Mọi khóa

  • get /v1/stations

    List the organization's stations, by id. Quyền: stations:read

  • get /v1/stations/{id}

    Retrieve a station. Quyền: stations:read

  • get /v1/events

    List the events of the last 30 days, newest first. Quyền: events:read

  • get /v1/events/{id}

    Retrieve an event. Quyền: events:read

Phiên bản

Phiên bản API theo ngày (2026-11-01). Tổ chức được gắn phiên bản mới nhất khi tạo khóa đầu tiên; gửi tiêu đề MH-Version để chọn một phiên bản khác. Trong cùng một phiên bản, Mobility Hub chỉ thêm, không đổi hay bỏ.

Lỗi

Mọi lỗi trả về dạng application/problem+json (RFC 9457) với code ổn định để lập trình theo, và request_id để báo cho Mobility Hub.

MãÝ nghĩa
authentication_requiredThiếu khóa, hoặc khóa sai, đã thu hồi hay hết hạn (401).
permission_deniedTổ chức không dùng được API ở chế độ này (403).
insufficient_scopeKhóa thiếu quyền cho thao tác (403).
resource_missingKhông tìm thấy, hoặc thuộc tổ chức hay chế độ khác (404).
invalid_requestTham số hoặc MH-Version không hợp lệ (400).
rate_limitedQuá giới hạn tần suất, đợi Retry-After giây (429).
internal_errorLỗi phía Mobility Hub; báo kèm request_id (500).

Giới hạn tần suất

Mỗi khóa live gửi tối đa 200 yêu cầu mỗi 10 giây, khóa test 50. Tiêu đề RateLimit cho biết còn bao nhiêu; quá giới hạn, API trả 429 kèm Retry-After.

Phân trang

Danh sách trả về object: "list", data và has_more. Lấy trang sau bằng starting_after = id cuối cùng của trang trước; limit từ 1 đến 100.

Webhook

Mỗi lần gửi là một sự kiện JSON với ba tiêu đề webhook-id, webhook-timestamp, webhook-signature theo chuẩn Standard Webhooks. Trả 2xx trong 10 giây; nếu không, Mobility Hub gửi lại với khoảng cách tăng dần trong khoảng ba ngày. Trả 410 để Mobility Hub tắt địa chỉ. Sự kiện có thể đến không theo thứ tự và có thể lặp: dùng webhook-id để bỏ qua bản trùng.

Các loại sự kiện

  • station.created: Trạm được thêm
  • station.updated: Trạm được sửa
  • station.removed: Trạm bị gỡ

Xác minh chữ ký (Node.js)

import { createHmac, timingSafeEqual } from "node:crypto";

// body: the raw request body, as received, before any JSON parsing.
export function verifyWebhook(secret, headers, body) {
  const id = headers["webhook-id"];
  const timestamp = Number(headers["webhook-timestamp"]);
  if (!id || Math.abs(Date.now() / 1000 - timestamp) > 300) return false;
  const key = Buffer.from(secret.slice("whsec_".length), "base64");
  const expected = createHmac("sha256", key).update(`${id}.${timestamp}.${body}`).digest();
  return String(headers["webhook-signature"] ?? "").split(" ").some((part) => {
    const [version, signature] = part.split(",");
    const given = Buffer.from(signature ?? "", "base64");
    return version === "v1" && given.length === expected.length && timingSafeEqual(given, expected);
  });
}