Litport API
The Litport API gives an integration access to your own tokens, packages and pay-per-GB (PPG) data, plus a small set of writes: token location, rotation, new IP, and package allowed IPs.
Base URL:
https://litport.net/api/v1
Areas#
| Area | Prefix | Docs page |
|---|---|---|
| Tokens | /tokens |
Tokens API |
| Packages | /packages |
Packages API |
| Pay-per-GB | /pay-per-gb |
Pay-per-GB API |
Authentication#
Create an API key on Settings. Its full value remains available there after creation or rotation.
export LITPORT_API_KEY='lit_replace_with_your_key'
curl 'https://litport.net/api/v1/tokens' \
-H "Authorization: Bearer $LITPORT_API_KEY"
External clients use the exact Bearer scheme. Do not send a key in the query string, JSON body, cookie, or proxy username. Store it as a secret, restrict access to server-side workloads, and rotate it if it may have leaked.
The Run controls on these documentation pages use your signed-in Litport account for GET requests only. Every write needs a Bearer API key.
Credential boundaries#
| Credential | Purpose |
|---|---|
| Proxy token username |
Opens proxied data-plane connections. |
| Proxy token ID / package ID | Selects a token or package in an API call; not a secret. |
User API key (lit_…) |
Authenticates account control-plane requests. |
API-wide rules#
Every endpoint in every area follows the same rules, so an integration learns them once.
Identifiers. Use the public numeric tokenId and packageId. Select a pay-per-GB pool by its authKey and an allowed IP by the IP itself. No endpoint takes or returns a database ID.
Names. Fields are camelCase. New enumerated values and slugs are lowercase kebab-case, for example awaiting-payment, more-allowed-ips, package-inactive. Error codes stay UPPER_SNAKE. Free text (labels, credentials, pool names) is unrestricted. A few values keep their existing spelling rather than being renamed to match: trafficBasis: "customer_chargeable" and timezone: "UTC" in usage, and token type/status values.
Values. Times are ISO-8601 UTC ending in Z. Large byte counts are decimal strings, not JSON numbers, so a client never loses precision.
Response shapes. A single object is {"data": {...}}. An endpoint that returns a list always answers {"data": [...], "page": {"nextCursor": ...}}. There are two kinds of list:
- a paged list (
GET /tokens,GET /packages,GET /pay-per-gb/geo) takeslimitandcursor; - a complete list (
GET /pay-per-gb/pools,GET /tokens/{tokenId}/location/options) always returns every item, takes nolimitorcursor, and reportspage.nextCursor: null.
An array inside an object, such as usage buckets, allowed-IPs ips, or a package's tokenIds, is an ordinary field, not an endpoint list.
Paging. limit is 1–100, default 50. cursor is the previous response's page.nextCursor, sent back unchanged; treat it as opaque. A bad limit is 400 INVALID_LIMIT; a bad or foreign cursor is 400 INVALID_CURSOR. Keep requesting page.nextCursor until it is null.
Errors. Every error is {"error": {"code", "message", "requestId", "docsUrl"}}, plus nextChangeAt when a wait applies. See API errors for the full status table and one detail heading per code.
Writes. Every write needs a Bearer API key; a signed-in documentation session can only read. Send a JSON body when the endpoint has one. There is no precondition header: the latest committed write wins. Every write is safe to repeat except POST /tokens/{tokenId}/new-ip.
Rate limits#
Two limits apply, both reported through standard headers.
- 120 requests per 60 seconds, per API key. Exceeding it is
429 RATE_LIMITED. - 20 allowed-IP writes per 60 seconds, per package (
PUT/DELETE /packages/{packageId}/allowed-ips…). The key limit is checked first; a request that passes it and is also an allowed-IP write then checks the package limit and reports that limiter's headers instead.
Read RateLimit-Limit, RateLimit-Remaining, and RateLimit-Reset on every response; a rejected request also carries Retry-After.
Conventions#
- Responses are JSON.
X-Request-IDidentifies the request; include it when reporting a failure.- Authenticated responses carry
Cache-Control: private, no-storeandVary: Authorization. - There are no ETags and no
If-Matchpreconditions anywhere in this API.
Machine contract#
Use the OpenAPI 3.1 document for every path, parameter, request body, and response schema. Handle the error envelope before using individual endpoint data.