Tham chiếu API

Tham chiếu API

API của bito.li là một API JSON qua HTTPS, nhỏ gọn, để tạo và quản lý link rút gọn. Đây cũng chính là API trang web bito.li đang dùng, nên mọi thứ bạn làm được trên trang khi chưa đăng nhập đều làm được bằng code.

Giới thiệu

Mọi endpoint nằm dưới một base URL và chỉ phục vụ qua HTTPS:

  • Base URL: https://bito.li/api
  • Body của request là JSON. Gửi kèm Content-Type: application/json. Body không phải JSON hợp lệ được xem như rỗng.
  • Response là JSON (application/json; charset=UTF-8), trừ GET /links/create?format=simple trả về văn bản thuần.
  • Thời gian là chuỗi ISO 8601 theo UTC, ví dụ 2026-10-25T09:41:12.000Z.
  • Link tạo qua API chuyển hướng tại https://bito.li/{shortCode}; link tạo trên lnk.ink cũng chạy ở bito.li.

API không gửi header CORS nên trình duyệt sẽ chặn request từ website khác. Hãy gọi từ server, script, ứng dụng di động hoặc hàm backend.

Xác thực

Không có API key. Tạo link không cần đăng nhập, và mỗi link được bảo vệ bằng secret code riêng thay cho tài khoản.

  • Khi tạo link với controlMode: "full" (mặc định), response có secretCode, ví dụ s-3f9-a1c-07b. Mã này chỉ trả về một lần.
  • Truyền nó qua secret (query) để xem thống kê, hoặc secretCode (body JSON) để sửa hay xoá link.
  • Ai có secret code đều quản lý được link, nên hãy giữ nó như mật khẩu. Đừng đặt nó trên trang công khai hay trong URL bạn chia sẻ.

Người dùng đã đăng nhập trên web bito.li được nhận diện bằng access token Bearer ngắn hạn. Link tạo kèm token đó thuộc về tài khoản, và chủ link xem thống kê, sửa, xoá mà không cần secret code. Token này dành cho trang web và ứng dụng của bito.li; hiện chưa có cách chính thức để cấp token dài hạn cho tích hợp, nên hãy xây tích hợp dựa trên secret code.

Secret code bị mất không thể khôi phục hay cấp lại. Nếu cần quản lý nhiều link, hãy tạo chúng khi đã đăng nhập trên web, hoặc nhập vào tài khoản bằng secret code.

Chế độ quản lý

Mỗi link có controlMode quyết định ai xem được thống kê và link có sửa được về sau hay không. Giá trị được đặt lúc tạo và không đổi được sau đó.

Mỗi chế độ quản lý cho phép gì
Chế độSecret codeThống kêSửa / xoáGắn với tài khoản
fullTrả về khi tạoCần secret code, hoặc là chủ linkCó, bằng secret code hoặc là chủ linkCó, nếu tạo khi đã đăng nhập
statsOnlyKhông cóCông khai (hoặc cần mật khẩu link nếu có)KhôngKhông
noneKhông cóKhông cóKhôngKhông

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

Việc tạo link (POST /links và GET /links/create) bị giới hạn theo địa chỉ IP của client. Giới hạn dùng chung với lnk.ink, nên đổi domain không làm mới hạn mức.

  • Giới hạn ngắn hạn: 120 request trong mọi khoảng 10 phút liên tiếp. Mọi lần thử đều được tính, kể cả request lỗi validate. Vượt quá sẽ nhận 429 với rateLimit.tooManyRequests.
  • Trần theo ngày: 300 link mới mỗi IP mỗi ngày (theo UTC). Request từ tài khoản đã tạo ít nhất 7 ngày được tạo tới 2.000. Vượt quá sẽ nhận 429 với rateLimit.dailyLimit cho tới ngày UTC kế tiếp.
  • Nhập sai thông tin: mỗi lần gửi sai secretCode hoặc password của link tới các endpoint thống kê, cập nhật, xoá đều được đếm theo địa chỉ IP. Sai quá 30 lần trong 15 phút thì các endpoint này trả 429 kèm rateLimit.tooManyAttempts (kể cả khi nhập đúng) cho tới khi hết khoảng thời gian đó. Request của chủ link hoặc không gửi thông tin xác thực thì không bị đếm.

Mọi response 429 đều có header Retry-After (giây) và trường retryAfter cùng giá trị trong body. Hãy chờ ít nhất chừng đó rồi mới thử lại. Trần theo ngày có thể bị siết lại khi có đợt lạm dụng.

Xem trước và các lần đọc thành công không bị giới hạn theo từng request, nhưng lưu lượng tự động có dấu hiệu lạm dụng có thể bị làm chậm hoặc chặn.

Lỗi

bito.li dùng mã HTTP thông thường: 2xx là thành công, 4xx khi request không thực hiện được như đã gửi và 5xx khi lỗi ở phía chúng tôi. Mọi body lỗi có cùng cấu trúc:

  • error: thông báo tiếng Anh dễ đọc. Có thể thay đổi, đừng phân tích chuỗi này.
  • errorKey: mã cố định, dành cho máy. Hãy rẽ nhánh theo trường này.
  • Một số lỗi có thêm trường ngữ cảnh, ví dụ reason với link hết hạn hoặc blockedType với link bị chặn.

Bảng dưới liệt kê mọi errorKey mà các endpoint link có thể trả về.

HTTP/1.1 409 Conflict
Content-Type: application/json

{
  "error": "Custom code already taken.",
  "errorKey": "customCodeErr.codeTaken"
}
MãerrorKeyÝ nghĩa
400customCodeErr.endsWithSymbolMã tuỳ chỉnh kết thúc bằng . _ hoặc -
400customCodeErr.invalidLengthMã tuỳ chỉnh không gồm 5–64 ký tự chữ, số, . _ -
400customCodeErr.repeatedSymbolsMã tuỳ chỉnh có hai ký hiệu liền nhau.
400customCodeErr.startsWithSymbolMã tuỳ chỉnh bắt đầu bằng . _ hoặc -
400validation.expirationInPastKhi tạo: `expiresAt` không nằm trong tương lai. Khi cập nhật: hạn mới không muộn hơn hạn hiện tại.
400validation.expirationTooFarexpiresAt xa hơn 100 năm.
400validation.invalidClickLimitGiới hạn click không phải số nguyên trong khoảng cho phép (hoặc, khi sửa, không lớn hơn số click hiện tại).
400validation.invalidControlModecontrolMode không phải full, statsOnly hoặc none.
400validation.invalidExpiration`expiresAt` không phải ngày hợp lệ, hoặc `expireAfter` không phải số nguyên từ 1 trở lên.
400validation.invalidExpireModeexpireMode không thuộc các giá trị được chấp nhận.
400validation.invalidPasswordCharsMật khẩu có dấu cách hoặc ký tự không hỗ trợ.
400validation.invalidPasswordLengthMật khẩu rỗng hoặc dài hơn 64 ký tự.
400validation.invalidTitletitle không phải chuỗi.
400validation.invalidUrlURL không phải địa chỉ http(s) hợp lệ có domain.
400validation.originalUrlRequiredThiếu URL đích hoặc URL rỗng.
400validation.titleTooLongtitle dài hơn 200 ký tự.
400validation.urlTooLongURL dài hơn 2.048 ký tự.
401auth.invalidPasswordThiếu mật khẩu link hoặc sai.
401auth.invalidSecretThiếu secret code hoặc sai.
401auth.noPermissionLink này không quản lý được (không phải link full, hoặc bạn không phải chủ link).
401auth.passwordRequiredLink có mật khẩu; đích không được hiển thị.
401auth.secretRequiredLink này chỉ chủ sở hữu mới quản lý được.
403customCodeErr.blockedKeywordMã tuỳ chỉnh chứa từ bị cấm (trả về trong blockedKeyword).
403forbidden.noTrackingLink tạo với controlMode none nên không có thống kê.
403link.maliciousLink bị chặn vì độc hại (xem blockedType). Link bị chặn được giữ lại làm bằng chứng.
403validation.blacklistedDomainĐích nằm trong blocklist hoặc bị đánh dấu không an toàn.
403validation.selfShortenBlockedURL trỏ về chính bito.li hoặc lnk.ink.
404notFound.linkKhông có link nào với mã rút gọn này.
404notFound.routeEndpoint không tồn tại. Kiểm tra method và đường dẫn.
409customCodeErr.codeTakenMã tuỳ chỉnh đã được dùng hoặc được giữ chỗ.
410expired.clicksLink đã đạt giới hạn click.
410expired.deletedLink đã bị xoá.
410expired.timeLink đã quá thời hạn.
429rateLimit.dailyLimitĐã chạm trần tạo link trong ngày của địa chỉ IP này.
429rateLimit.tooManyAttemptsIP này nhập sai secret code hoặc mật khẩu quá nhiều lần. Chờ số giây trong `Retry-After`.
429rateLimit.tooManyRequestsHơn 120 request tạo link trong 10 phút.
500server.createFailedKhông sinh được mã rút gọn không trùng. Hãy gửi lại request.
500server.errorLỗi máy chủ ngoài dự kiến. Thử lại sau; liên hệ chúng tôi nếu vẫn lỗi.
POST /api/links

Rút gọn một URL, có thể kèm mã tuỳ chỉnh, mật khẩu, hạn dùng và chế độ quản lý.

Tạo link rút gọn mới và trả về với 201 Created. Link được kiểm tra với blocklist trước khi lưu và được Google Safe Browsing quét ngay sau đó, nên link vẫn có thể bị chặn một lúc sau khi tạo.

Dùng lại. Nếu không có customCode mà đã tồn tại một link còn hiệu lực giống hệt (cùng đích, chế độ quản lý, mật khẩu, chủ sở hữu và hạn dùng tương thích), link đó được trả về với 200 OK, khi đó secretCode và password là null. Nếu cần link quản lý được, hãy dùng customCode hoặc đích khác.

Mã tuỳ chỉnh. Nếu customCode đã được dùng cho link có cùng đích, link đó được trả về với 200 OK; ngược lại bạn nhận 409 customCodeErr.codeTaken. Mã trùng tên trang của bito.li (như login hay docs) đã được giữ chỗ.

Hạn dùng. Dùng hạn tương đối (expireMode + expireAfter) hoặc thời điểm tuyệt đối expiresAt. Có thể kết hợp giới hạn thời gian với giới hạn click: link hết hạn khi chạm điều kiện nào trước. expiresAt được ưu tiên hơn expireMode dạng thời gian; expireMode: "clicks" được ưu tiên hơn maxClicks.

Tham số body (JSON)

originalUrl string Bắt buộc

URL đích. Tự thêm https:// nếu thiếu.

Chỉ http hoặc https, cần domain hợp lệ có TLD, tối đa 2.048 ký tự sau khi chuẩn hoá. Link tới bito.li hoặc lnk.ink bị từ chối.

customCode string Tuỳ chọn

Mã rút gọn do bạn chọn thay cho mã ngẫu nhiên.

5–64 ký tự: chữ, số, . _ -. Không bắt đầu/kết thúc bằng ký hiệu, không có hai ký hiệu liền nhau.

controlMode string Tuỳ chọn

Ai xem được thống kê và quản lý link. Xem Chế độ quản lý.

Một trong: fullstatsOnlynone Mặc định: full

password string Tuỳ chọn

Người truy cập phải nhập mật khẩu này trước khi được chuyển hướng.

1–64 ký tự: chữ, số và ký hiệu thông dụng, không có dấu cách. Được lưu và hiển thị cho người quản lý link đúng như đã nhập.

expireMode string Tuỳ chọn

Đơn vị hạn dùng tương đối. Dùng cùng expireAfter.

Một trong: minuteshoursdaysclicks

expireAfter integer Tuỳ chọn

Số đơn vị của expireMode: số phút, giờ, ngày tính từ bây giờ, hoặc số lượt click.

Với clicks: 1–100.000.000. Với đơn vị thời gian: số dương, mặc định 1.

Mặc định: 1

expiresAt string (ISO 8601) Tuỳ chọn

Thời điểm hết hạn tuyệt đối. Giá trị không đọc được sẽ bị bỏ qua.

Không quá 100 năm tính từ bây giờ.

maxClicks integer Tuỳ chọn

Link ngừng chuyển hướng sau chừng này lượt click.

Số nguyên, 1–100.000.000.

Lỗi

  • 400 validation.originalUrlRequired Thiếu URL đích hoặc URL rỗng.
  • 400 validation.invalidUrl URL không phải địa chỉ http(s) hợp lệ có domain.
  • 400 validation.urlTooLong URL dài hơn 2.048 ký tự.
  • 400 customCodeErr.invalidLength Mã tuỳ chỉnh không gồm 5–64 ký tự chữ, số, . _ -
  • 400 customCodeErr.startsWithSymbol Mã tuỳ chỉnh bắt đầu bằng . _ hoặc -
  • 400 customCodeErr.endsWithSymbol Mã tuỳ chỉnh kết thúc bằng . _ hoặc -
  • 400 customCodeErr.repeatedSymbols Mã tuỳ chỉnh có hai ký hiệu liền nhau.
  • 400 validation.invalidPasswordLength Mật khẩu rỗng hoặc dài hơn 64 ký tự.
  • 400 validation.invalidPasswordChars Mật khẩu có dấu cách hoặc ký tự không hỗ trợ.
  • 400 validation.invalidControlMode controlMode không phải full, statsOnly hoặc none.
  • 400 validation.invalidClickLimit Giới hạn click không phải số nguyên trong khoảng cho phép (hoặc, khi sửa, không lớn hơn số click hiện tại).
  • 400 validation.invalidExpiration `expiresAt` không phải ngày hợp lệ, hoặc `expireAfter` không phải số nguyên từ 1 trở lên.
  • 400 validation.expirationInPast Khi tạo: `expiresAt` không nằm trong tương lai. Khi cập nhật: hạn mới không muộn hơn hạn hiện tại.
  • 400 validation.expirationTooFar expiresAt xa hơn 100 năm.
  • 403 validation.selfShortenBlocked URL trỏ về chính bito.li hoặc lnk.ink.
  • 403 validation.blacklistedDomain Đích nằm trong blocklist hoặc bị đánh dấu không an toàn.
  • 403 customCodeErr.blockedKeyword Mã tuỳ chỉnh chứa từ bị cấm (trả về trong blockedKeyword).
  • 409 customCodeErr.codeTaken Mã tuỳ chỉnh đã được dùng hoặc được giữ chỗ.
  • 429 rateLimit.tooManyRequests Hơn 120 request tạo link trong 10 phút.
  • 429 rateLimit.dailyLimit Đã chạm trần tạo link trong ngày của địa chỉ IP này.
curl -X POST 'https://bito.li/api/links' \
  -H 'Content-Type: application/json' \
  -d '{
  "originalUrl": "https://example.com/spring-sale?utm_source=newsletter",
  "customCode": "spring-sale",
  "expireMode": "clicks",
  "expireAfter": 1000
}'
Response · 201
{
  "originalUrl": "https://example.com/spring-sale?utm_source=newsletter",
  "shortUrl": "https://bito.li/spring-sale",
  "shortCode": "spring-sale",
  "statsUrl": "https://bito.li/d/spring-sale",
  "clicks": 0,
  "expiresAt": null,
  "maxClicks": 1000,
  "controlMode": "full",
  "secretCode": "s-3f9-a1c-07b",
  "password": null,
  "userId": null
}

201 khi tạo link mới. 200 khi dùng lại link có sẵn (khi đó secretCode và password là null). userId chỉ có với link full do người dùng đã đăng nhập tạo.

Chạy thử

Tạo một link rút gọn thật, công khai

Gửi request thật tới bito.li ngay từ trình duyệt. Không có gì chạy cho tới khi bạn bấm Gửi. Request được gửi ẩn danh từ trình duyệt của bạn và tính vào giới hạn tần suất của địa chỉ IP.

POST /api/links
GET /api/links/create

Rút gọn trong một dòng, cho bảng tính, shell script và công cụ no-code.

Phiên bản tiện lợi của Tạo link rút gọn, gói gọn trong một URL. Link tạo theo cách này luôn có controlMode: "none": không có secret code, không có thống kê và không sửa, xoá được. Dùng POST /links nếu bạn cần những thứ đó.

Hãy URL-encode giá trị url (ví dụ bằng encodeURIComponent hoặc --data-urlencode), nếu không các ký tự như & hay # trong URL đích sẽ bị mất.

Validate, dùng lại link, mã giữ chỗ và giới hạn tần suất giống hệt POST /links.

Tham số query

url string Bắt buộc

URL đích, đã URL-encode.

custom string Tuỳ chọn

Mã rút gọn tuỳ chỉnh, cùng quy tắc với customCode.

format string Tuỳ chọn

Đặt simple để chỉ nhận link rút gọn dạng văn bản thuần thay vì JSON.

Một trong: simple

Lỗi

  • 400 validation.originalUrlRequired Thiếu URL đích hoặc URL rỗng.
  • 400 validation.invalidUrl URL không phải địa chỉ http(s) hợp lệ có domain.
  • 400 customCodeErr.invalidLength Mã tuỳ chỉnh không gồm 5–64 ký tự chữ, số, . _ -
  • 403 validation.blacklistedDomain Đích nằm trong blocklist hoặc bị đánh dấu không an toàn.
  • 409 customCodeErr.codeTaken Mã tuỳ chỉnh đã được dùng hoặc được giữ chỗ.
  • 429 rateLimit.tooManyRequests Hơn 120 request tạo link trong 10 phút.
  • 429 rateLimit.dailyLimit Đã chạm trần tạo link trong ngày của địa chỉ IP này.
curl 'https://bito.li/api/links/create?url=https%3A%2F%2Fexample.com%2Fdocs%2Fgetting-started&format=simple'
Response · 201
https://bito.li/k3Xb9

Với format=simple, body là link rút gọn dạng text/plain. Nếu không, body JSON có cùng cấu trúc với POST /links. Lỗi luôn là JSON, kể cả khi dùng format=simple.

Chạy thử

Tạo một link rút gọn thật, công khai

Gửi request thật tới bito.li ngay từ trình duyệt. Không có gì chạy cho tới khi bạn bấm Gửi. Request được gửi ẩn danh từ trình duyệt của bạn và tính vào giới hạn tần suất của địa chỉ IP.

GET /api/links/create
GET /api/links/{code}/stats

Lấy thống kê link

Tổng lượt click, biểu đồ 30 ngày và phân bổ theo quốc gia, thành phố, thiết bị, trình duyệt, hệ điều hành, nguồn truy cập.

Trả về cài đặt của link và thống kê lượt click. Ai được xem tuỳ vào link:

  • Link full có secret code: truyền secret. Mật khẩu link không mở được thống kê.
  • Link statsOnly: công khai, trừ khi link có mật khẩu, khi đó truyền password.
  • Link none: không thu thập thống kê, endpoint trả 403 forbidden.noTracking.
  • Chủ link đã đăng nhập trên bito.li luôn xem được thống kê link của mình.

Link đã hết hạn trả 410, trừ khi bạn truyền đúng secret code (hoặc là chủ link), để vẫn xem được số liệu cuối cùng.

Các bảng phân bổ được cache tối đa 5 phút và xử lý nền, nên một lượt click có thể mất vài phút mới hiện. clicks và recentClicks (50 lượt gần nhất) cập nhật sớm hơn. engagementsOverTime gồm 30 ngày gần nhất theo ngày UTC. qrClicks đếm lượt truy cập qua mã QR của link.

Chỉ lấy đích. Với mode=redirect, endpoint chỉ trả { "originalUrl": "…" } và chỉ kiểm tra mật khẩu link, hữu ích khi cần lấy đích của link có mật khẩu.

Tham số đường dẫn

code string Bắt buộc

Mã rút gọn, ví dụ spring-sale của https://bito.li/spring-sale.

Tham số query

secret string Có điều kiện

Secret code của link full.

password string Có điều kiện

Mật khẩu của link có mật khẩu (link statsOnly và mode=redirect).

mode string Tuỳ chọn

Đặt redirect để chỉ lấy URL đích.

Một trong: redirect

Lỗi

  • 401 auth.invalidSecret Thiếu secret code hoặc sai.
  • 401 auth.invalidPassword Thiếu mật khẩu link hoặc sai.
  • 401 auth.secretRequired Link này chỉ chủ sở hữu mới quản lý được.
  • 403 forbidden.noTracking Link tạo với controlMode none nên không có thống kê.
  • 404 notFound.link Không có link nào với mã rút gọn này.
  • 410 expired.deleted Link đã bị xoá.
  • 410 expired.time Link đã quá thời hạn.
  • 410 expired.clicks Link đã đạt giới hạn click.
  • 429 rateLimit.tooManyAttempts IP này nhập sai secret code hoặc mật khẩu quá nhiều lần. Chờ số giây trong `Retry-After`.
curl 'https://bito.li/api/links/spring-sale/stats?secret=s-3f9-a1c-07b'
Response · 200
{
  "duration": "18 ms",
  "shortCode": "spring-sale",
  "originalUrl": "https://example.com/spring-sale?utm_source=newsletter",
  "title": null,
  "shortUrl": "https://bito.li/spring-sale",
  "clicks": 128,
  "qrClicks": 12,
  "createdAt": "2026-10-20T08:14:03.000Z",
  "lastAccessed": "2026-10-20T08:14:03.000Z",
  "expiresAt": null,
  "maxClicks": 1000,
  "controlMode": "full",
  "hasPassword": false,
  "isOwner": false,
  "stats": {
    "engagementsOverTime": [
      {
        "date": "2026-10-24",
        "clicks": 41
      },
      {
        "date": "2026-10-25",
        "clicks": 87
      }
    ],
    "topPerformingDate": {
      "date": "2026-10-25",
      "clicks": 87
    },
    "topCountries": [
      {
        "countryCode": "VN",
        "clicks": 90,
        "percent": 70.3
      }
    ],
    "topPlatforms": [
      {
        "platform": "Android",
        "clicks": 70,
        "percent": 55
      }
    ],
    "topReferrers": [
      {
        "referer": "(direct)",
        "clicks": 80,
        "percent": 63
      }
    ],
    "deviceStats": [
      {
        "deviceType": "Mobile",
        "clicks": 96,
        "percent": 75
      }
    ],
    "browserStats": [
      {
        "browser": "Chrome",
        "clicks": 81,
        "percent": 63
      }
    ],
    "allCountries": [
      {
        "countryCode": "VN",
        "clicks": 90,
        "percent": 70.3
      }
    ],
    "allCities": [
      {
        "city": "Hanoi",
        "countryCode": "VN",
        "clicks": 52,
        "percent": 40.6
      }
    ],
    "recentClicks": [
      {
        "timestamp": "2026-10-25T09:41:12.000Z",
        "countryCode": "VN",
        "city": "Hanoi",
        "deviceType": "Mobile",
        "browser": "Chrome",
        "platform": "Android",
        "referer": "(direct)"
      }
    ]
  },
  "secretCode": "s-3f9-a1c-07b"
}

Không bao giờ trả về mật khẩu; hasPassword cho biết link có mật khẩu hay không. secretCode chỉ trả cho chủ link, người gửi đúng secret, và link full không có mật khẩu. lastAccessed là thời điểm link được tạo hoặc sửa lần cuối, không phải lượt click cuối; muốn biết lượt click cuối hãy dùng recentClicks[0].timestamp.

Chạy thử

Gửi request thật tới bito.li ngay từ trình duyệt. Không có gì chạy cho tới khi bạn bấm Gửi. Request được gửi ẩn danh từ trình duyệt của bạn và tính vào giới hạn tần suất của địa chỉ IP.

GET /api/links/%7Bcode%7D/stats
GET /api/links/{code}/preview

Xem link rút gọn dẫn tới đâu mà không cần mở và không tính lượt click.

Trả về đích và cài đặt cơ bản của một link còn hiệu lực. Không cần xác thực và không ghi nhận lượt click, phù hợp cho công cụ kiểm tra link và hiển thị bản xem trước.

Đích không được tiết lộ với link có mật khẩu (401), hết hạn hoặc đã xoá (410) hay bị chặn vì độc hại (403 link.malicious, kèm blockedType). Với link bị chặn, reveal=1 thêm originalUrl vào body lỗi để trang cảnh báo hiển thị khi người dùng yêu cầu. Đừng bao giờ tự động chuyển người dùng tới đó.

Tham số đường dẫn

code string Bắt buộc

Mã rút gọn cần tra.

Tham số query

reveal string Tuỳ chọn

Đặt 1 để kèm đích của link bị chặn trong response 403.

Một trong: 1

Lỗi

  • 401 auth.passwordRequired Link có mật khẩu; đích không được hiển thị.
  • 403 link.malicious Link bị chặn vì độc hại (xem blockedType). Link bị chặn được giữ lại làm bằng chứng.
  • 404 notFound.link Không có link nào với mã rút gọn này.
  • 410 expired.deleted Link đã bị xoá.
  • 410 expired.time Link đã quá thời hạn.
  • 410 expired.clicks Link đã đạt giới hạn click.
curl 'https://bito.li/api/links/spring-sale/preview'
Response · 200
{
  "shortCode": "spring-sale",
  "originalUrl": "https://example.com/spring-sale?utm_source=newsletter",
  "createdAt": "2026-10-20T08:14:03.000Z",
  "expiresAt": null,
  "maxClicks": 1000,
  "controlMode": "full",
  "passwordProtected": false,
  "blockedType": null
}

blockedType là null với link không bị chặn. Response hết hạn có expired: true và reason (time hoặc clicks).

Chạy thử

Gửi request thật tới bito.li ngay từ trình duyệt. Không có gì chạy cho tới khi bạn bấm Gửi. Request được gửi ẩn danh từ trình duyệt của bạn và tính vào giới hạn tần suất của địa chỉ IP.

GET /api/links/%7Bcode%7D/preview
PATCH /api/links/{code}

Đổi đích, tiêu đề, mật khẩu hoặc hạn dùng của link full.

Chỉ những trường bạn gửi mới thay đổi; phần còn lại giữ nguyên. Body rỗng vẫn thành công nhưng không đổi gì. Chỉ link full sửa được: xác thực bằng secretCode của link, hoặc là chủ link đã đăng nhập. Thay đổi có hiệu lực ngay với người truy cập.

  • originalUrl mới được kiểm tra như lúc tạo, cộng thêm kiểm tra Google Safe Browsing ngay lập tức. Đích không an toàn bị từ chối với 403 validation.blacklistedDomain.
  • password: null hoặc "" để bỏ mật khẩu.
  • expireMode: "never" bỏ cả giới hạn thời gian lẫn giới hạn click.
  • Hạn theo thời gian tính từ bây giờ và phải muộn hơn hạn hiện tại (nếu không: 400 validation.expirationInPast). Đặt hạn thời gian sẽ bỏ giới hạn click.
  • Giới hạn click phải lớn hơn số click link đã có. Đặt giới hạn click sẽ bỏ hạn thời gian.

Link đã hết hạn vẫn sửa được, đó là cách gia hạn hoặc mở lại link. Link bị chặn không sửa được.

Tham số đường dẫn

code string Bắt buộc

Mã rút gọn của link cần sửa.

Tham số body (JSON)

secretCode string Có điều kiện

Secret code của link. Không cần nếu gọi với tư cách chủ link đã đăng nhập.

originalUrl string Tuỳ chọn

URL đích mới. Cùng quy tắc như lúc tạo.

title string Tuỳ chọn

Nhãn của link, hiện trong dashboard. Được cắt khoảng trắng hai đầu.

Tối đa 200 ký tự.

password string | null Tuỳ chọn

Mật khẩu mới, hoặc null / "" để bỏ.

1–64 ký tự, không có dấu cách.

expireMode string Tuỳ chọn

Hạn dùng mới: never, một đơn vị thời gian, hoặc clicks.

Một trong: neverminuteshoursdaysclicks

expireAfter integer Tuỳ chọn

Số đơn vị tính từ bây giờ, hoặc giới hạn click khi expireMode là clicks.

Đơn vị thời gian: số nguyên ≥ 1. Click: 1–100.000.000 và lớn hơn số click hiện tại.

Lỗi

  • 400 validation.invalidUrl URL không phải địa chỉ http(s) hợp lệ có domain.
  • 400 validation.invalidTitle title không phải chuỗi.
  • 400 validation.titleTooLong title dài hơn 200 ký tự.
  • 400 validation.invalidPasswordLength Mật khẩu rỗng hoặc dài hơn 64 ký tự.
  • 400 validation.invalidPasswordChars Mật khẩu có dấu cách hoặc ký tự không hỗ trợ.
  • 400 validation.invalidExpireMode expireMode không thuộc các giá trị được chấp nhận.
  • 400 validation.invalidExpiration `expiresAt` không phải ngày hợp lệ, hoặc `expireAfter` không phải số nguyên từ 1 trở lên.
  • 400 validation.expirationInPast Khi tạo: `expiresAt` không nằm trong tương lai. Khi cập nhật: hạn mới không muộn hơn hạn hiện tại.
  • 400 validation.invalidClickLimit Giới hạn click không phải số nguyên trong khoảng cho phép (hoặc, khi sửa, không lớn hơn số click hiện tại).
  • 401 auth.invalidSecret Thiếu secret code hoặc sai.
  • 401 auth.noPermission Link này không quản lý được (không phải link full, hoặc bạn không phải chủ link).
  • 403 validation.blacklistedDomain Đích nằm trong blocklist hoặc bị đánh dấu không an toàn.
  • 403 link.malicious Link bị chặn vì độc hại (xem blockedType). Link bị chặn được giữ lại làm bằng chứng.
  • 404 notFound.link Không có link nào với mã rút gọn này.
  • 410 expired.deleted Link đã bị xoá.
  • 429 rateLimit.tooManyAttempts IP này nhập sai secret code hoặc mật khẩu quá nhiều lần. Chờ số giây trong `Retry-After`.
curl -X PATCH 'https://bito.li/api/links/spring-sale' \
  -H 'Content-Type: application/json' \
  -d '{
  "secretCode": "s-3f9-a1c-07b",
  "originalUrl": "https://example.com/autumn-sale",
  "expireMode": "days",
  "expireAfter": 30
}'
Response · 200
{
  "success": true
}

Chạy thử

Thay đổi một link thật

Gửi request thật tới bito.li ngay từ trình duyệt. Không có gì chạy cho tới khi bạn bấm Gửi. Request được gửi ẩn danh từ trình duyệt của bạn và tính vào giới hạn tần suất của địa chỉ IP.

PATCH /api/links/%7Bcode%7D
POST /api/links/{code}/delete

Ngừng chuyển hướng một link full.

Xoá link. Người truy cập thấy trang “không tìm thấy link” thay vì được chuyển hướng, và thống kê không còn xem được. Mã rút gọn vẫn bị giữ và không dùng lại được.

Xác thực bằng secretCode của link, hoặc là chủ link đã đăng nhập. Link thuộc tài khoản có thể khôi phục từ Thùng rác trong dashboard trong vòng 30 ngày; link không có tài khoản thì không khôi phục được.

Endpoint dùng POST (không phải DELETE) để chạy được với client và proxy không gửi được body kèm DELETE.

Tham số đường dẫn

code string Bắt buộc

Mã rút gọn của link cần xoá.

Tham số body (JSON)

secretCode string Có điều kiện

Secret code của link. Không cần nếu gọi với tư cách chủ link đã đăng nhập.

Lỗi

  • 401 auth.invalidSecret Thiếu secret code hoặc sai.
  • 401 auth.noPermission Link này không quản lý được (không phải link full, hoặc bạn không phải chủ link).
  • 403 link.malicious Link bị chặn vì độc hại (xem blockedType). Link bị chặn được giữ lại làm bằng chứng.
  • 404 notFound.link Không có link nào với mã rút gọn này.
  • 410 expired.deleted Link đã bị xoá.
  • 429 rateLimit.tooManyAttempts IP này nhập sai secret code hoặc mật khẩu quá nhiều lần. Chờ số giây trong `Retry-After`.
curl -X POST 'https://bito.li/api/links/spring-sale/delete' \
  -H 'Content-Type: application/json' \
  -d '{
  "secretCode": "s-3f9-a1c-07b"
}'
Response · 200
{
  "success": true
}

Chạy thử

Xoá một link thật

Gửi request thật tới bito.li ngay từ trình duyệt. Không có gì chạy cho tới khi bạn bấm Gửi. Request được gửi ẩn danh từ trình duyệt của bạn và tính vào giới hạn tần suất của địa chỉ IP.

POST /api/links/%7Bcode%7D/delete
GET /api/links/stats/total

Tổng số link đã được tạo trên bito.li và lnk.ink.

Bộ đếm công khai, cache 60 giây. Hữu ích cho trang trạng thái và widget.

Endpoint này không có tham số.

Lỗi

Endpoint này không có lỗi riêng.

curl 'https://bito.li/api/links/stats/total'
Response · 200
{
  "total": 685214
}

Chạy thử

Gửi request thật tới bito.li ngay từ trình duyệt. Không có gì chạy cho tới khi bạn bấm Gửi. Request được gửi ẩn danh từ trình duyệt của bạn và tính vào giới hạn tần suất của địa chỉ IP.

GET /api/links/stats/total

Cần hỗ trợ?

Có chỗ chưa rõ hoặc API chạy khác với tài liệu? Gửi email tới [email protected], kèm request bạn đã gửi và errorKey nhận được.